Sudoku Game (java)


This is a simple Sudoku game made in Java.

This Sudoku game has always the same numbers in the playing grid.

This game can be run in the command line without a GUI.


    Videos from the game:


    📢RecommendedPlease watch the video first of all. Try to understand the game and the idea behind it and then try to implement  the game on your own first, before looking at the code down below.


    📥Download the Code📥

    package structure:


















    ____________________________________________________

    🎁Code:


    Main.java:


    package src;

    import src.start.Play;

    /**
     * The is the Main class
     * 
     * This class contains the main method, where we can list the tasks   
     * of the whole program 
     * @author  Khaled Badran <gym4programming@gmail.com>
     * @version 19 May 2020  
    */
    public class Main{
        /**
         * The is the Main method.
         * 
         * In this method we can list the tasks of the program   
         *
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @version 19 May 2020  
         * @param args an array of Strings 
        */
        public static void main(String[] args){
            byte[][] sudoku1 = {
                {-1,  6-1-1-1-1,  4,  2,  5},
                { 5,  7-1-1-1-1-1,  8,  1},
                {-1-1-1,  4,  3-1,  9-1-1},
                {-1,  5-1,  9,  2-1-1,  7,  4},
                {-1-1-1,  3,  8,  4-1-1-1},
                { 8,  4-1,  5,  6,  7-1,  9-1},
                {-1-1,  2-1,  1-1-1-1-1},
                {-1,  3,  9-1-1,  6,  7-1,  8},
                {-1-1-1-1-1,  9,  6-1-1}
            };

            Play game = new Play(sudoku1);
            game.start();
            
        }

    }

    ____________________________________________________

    Util.java:

    package src.util;

    import java.io.*;

    /**
     * This class is to clear the screen.   
     * 
     * @author  Khaled Badran <gym4programming@gmail.com>
     * @version 19 May 2020  
    */
    public class Util {
        
        /**
         * to clear the screen.   
         * 
         * @author  Khaled Badran <gym4programming@gmail.com>
        */
        public static void cls() {//to clear the screen 
            try {
                new ProcessBuilder("cmd""/c""cls").inheritIO().start().waitFor();
            } catch (Exception e) {
                // handle exception
                System.out.println(e);
            }
        }

    }

    ____________________________________________________

    Play.java:


    package src.start;

    import java.util.Scanner;
    import src.util.*;
    /**
     * This class simulates the sudoku game 
     * This class extends the sudokufield class   
     * 
     * @author  Khaled Badran <gym4programming@gmail.com>
     * @version 19 May 2020  
    */
    public class Play extends src.model.SudokuField{
        /** 
         *  these all fields are "private" because other classes should not access them directly,
         *  rather with setter and getter. 
        */ 
        /** row is the x axis of the cell*/
        /** column is the y axis of the cell*/
        /** value is the value of the cell*/
        private int row, column, value;
        private String command; /** A String to store the commands of the user*/ 
        private String oldLayout; /** A String to store the layout of the old sudokufield. */
        private Scanner scan = new Scanner(System.in); /**to scan value from the user */
        
        /**
         * Cunstroctor that accepts 2d array
         * it calls the Cunstroctor of the SudokuField
         * to initialize the sudokufield with the values of the 2d array
         * 
         * "public" beause Cunstroctors should always be public 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param f 2d array that has the initiate values of the sudokufield.
        */
        public Play(byte[][] f){
            super(f);
        }
        /**
         * "private" cause it would only be used in this class.
         * to scan the commands from the user
         * @author  Khaled Badran <gym4programming@gmail.com>
        */
        private void getData(){
            this.command = scan.next();
            this.row = scan.nextInt();
            this.column = scan.nextInt();
            this.value = scan.nextInt();  
        }    

        /**
         * to check weather the sudokufield is completely full or still has an empty cell.
         * "private" cause it would only be used in this class.
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @return weather the field is empty or not
        */
        private boolean isfieldfull(){
            for(int i = 0; i < 9; i++){
                for(int j = 0; j < 9; j++){
                    if(this.getCellVal(i, j) == -1return false//if only one cell is still empty then field still not full 
                }
            }
            return true;
        }

        /**
         * to print the sudokufield and the instructions to the user 
         * to show the user which commands are accepted  
         * "private" cause it would only be used in this class.
         * @author  Khaled Badran <gym4programming@gmail.com>
        */
        private void printWithInstructions(){
            Util.cls(); //to clear the  screan 
            System.out.println("\nenter your command in one of the following forms:");
            System.out.println
                                "enter <row> <column> <value> /or\n"+
                                "mark <row> <column> <value> /or\n"+
                                "unmark <row> <column> <value> /or\n"+
                                "viewmarks <row> <column> 0 /or\n"+
                                "exit 0 0 0"
            );
            System.out.println(this); //to print the field
        }

        /**
         * executes the game 
         * stops the game if the sudokufield is full or if the player wants to exit the game.
         * @author  Khaled Badran <gym4programming@gmail.com>
        */
        public void start(){
            printWithInstructions();

            boolean execute = true;
            this.oldLayout = this.toString();
            
            while(!isfieldfull() && execute){
                this.getData();
                switch(command){
                    case "enter": this.setCellVal(row, column, value);  break;
                    case "mark": this.mark(row, column, value);         break;
                    case "unmark":  this.unmark(row, column, value);    break;
                    case "viewmarks": this.viewMarks(row, column);      break;
                    case "exit" : execute = false;                      break;
                    default : System.out.println("your command isn't valid");   
                }

                if(!this.oldLayout.equals(this.toString())) { //to check weather there is a new value entered or not. If yes, the field should be printed again including this new value
                    printWithInstructions();
                    this.oldLayout = this.toString();
                }

            }
            //if the sudokufield is completely full that means the playes has won. 
            if(isfieldfull()) System.out.println("YOU WIN!! :) YAHOO :)");
            
        }

        
    }

    ____________________________________________________

    Cell.java:


    package src.model;
    /**
     * This class represents the cell/tile of the sudokufield
     * the sudokufield has 9*9 Cells 
     * 
     * @author  Khaled Badran <gym4programming@gmail.com>
     * @version 19 May 2020  
    */
    class Cell extends Position{
        /** 
         *  these fields are "private" because other classes should not access them directly,
         *  rather with setter and getter. 
        */ 
        private int value; /**value of the cell*/
        private int[] markArr = new int[5]; /**array for marking values for every single cell */

        /**
         * Cunstroctor that sets the position of the cell and
         * initializes it as an empty cell with an empty array of marked values.
         * "public" beause Cunstroctors should always be public 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x x axis of the cell
         * @param y y axis of the cell
         */
        public Cell(int xint y) {
            super(xy); //assigning the position
            this.value = -1//initiates the value of the Cell with -1 (empty).
            for(int i = 0; i < markArr.length; i++)
                this.markArr[i] = -1//initiates the values of the Marking array with -1 (empty).
        }

        /**
         * sets the value of the cell with given value
         * "public" so that we can access the private fields without calling them directly. 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param value to be assigned to cell 
         */
        public void setValue(int value) {
            this.value = value;
        }
        /**
         * gets the value of a cell
         * "public" so that we can access the private fields without calling them directly. 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @return value of the cell
         */
        public int getValue() {
            return value;
        }
        /**
         * mark/store given value to the array of marked values.
         * "protected" because it should only be accessible to the inheriting classes
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param value
         * @return  weather the value is successfully marked or not.
         */
        protected boolean markValue(int value){
            for(int i = 0; i < markArr.length; i++){
                if(markArr[i] == value)  break;//avoid adding tha same value
                if (markArr[i] == -1) {
                    this.markArr[i] = value;
                    return true;
                }
            }   
            return false
        }

        /**
         * remove the given value from the array of marked values 
         * "protected" because it should only be accessible to the inheriting classes
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param value
         * @return  weather the value is successfully removed or not
         */
        protected boolean unmarkValue(int value){
            for(int i = 0; i < markArr.length; i++){
                if(markArr[i] == value) {
                    markArr[i] = -1
                    this.fixIndices();
                    return true;
                }    
            }
            return false;
        }

        /**
         * fixes the indices of the array of marked values 
         * by removing the -1 value from first places and puts it in the back
         * "private" cause it would only be used in this class.
         * @author  Khaled Badran <gym4programming@gmail.com>
         */
        private void fixIndices(){ //it fixes the indices of the marking arr by removing the -1 value from first places and puts it in the back
            for(int i = 0; i < markArr.length-1; i++){
                int next = i+1;
                if (markArr[i] == -1 && markArr[next] != -1){ //swap 
                    markArr[i] = markArr[next];
                    markArr[next] = -1;
                }
            }
        }

        /**
         * stores the array of marked values in a string so we can print it later.
         * "protected" because it should only be accessible to the inheriting classes
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @return  the formatted string 
         */
        protected String printMarkArr(){
            String s = "[";
            
            if (markArr[0== -1) { //if the first element of the marking array is empty that means the whole array is empty as well.
                s += "]";
                return s;
            }

            for(int i = 0; i < markArr.length; i++)
                if (markArr[i] != -1) s += String.valueOf(markArr[i]) + ", "
            s += "\b\b]"//to remove the space and the comma before the closing brackets 
                
            return s;
        }

    }

    ____________________________________________________

    SudokuField.java:

    package src.model;

    /**
     * This class represents the sudokufield 
     * the sudokufield has 9*9 Cells 
     * 
     * public because it should be called in the Play class, which is in different package. 
     * @author  Khaled Badran <gym4programming@gmail.com>
     * @version 19 May 2020  
    */
    public class SudokuField{
        /** 
         *  2d array that has all the values of the Sudoku field 
         *  "private" because other classes should not access it directly, rather with setter and getter. 
        */ 
        private Cell[][] field = new Cell[9][9]; // the playing field 
        
        /**
         * Cunstroctor that accepts 2d array
         * it initializes the sudokufield with the values of the 2d array
         * 
         * "public" beause Cunstroctors should always be public 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param f 2d array that has the initiate values of the sudokufield.
        */
        public SudokuField(byte[][] f){
            //checking number of rows
            if(f.length != 9){ System.err.println("The playing field isn't valid"); System.exit(2); }
            //checking number of cols per each row
            for(int i = 0; i < 9; i++
                if(f[i].length != 9){ System.err.println("The playing field isn't valid"); System.exit(2); }
            //now the field is valid 
            for(int i = 0; i < 9; i++){
                for(int j = 0; j < 9; j++){
                    this.field[i][j] = new Cell(i,j); //assigning the position (x and y) to every single cell
                    this.field[i][j].setValue(f[i][j]); //assigning the values 
                }
            }        
        }

        /**
         * sets a cell at a specific index/position with the given value
         * "public" so that we can access the private fields in the different classes
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x x axis of the cell
         * @param y y axis of the cell
         * @param value value of the cell
         * @return weather the cell got the new value or not 
         */
        public boolean setCellVal(int xint yint value){
            if(isValid(xyvalue)){
                this.field[x][y].setValue(value);
                return true;
            }
            
            System.out.println("Invalid entry.");    
            return false;
        }

        /**
         * gets the value of a cell at a specific index/position
         * "public" so that we can access the private fields in the different classes
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x x axis of the cell
         * @param y y axis of the cell
         * @return the value of the cell
         */
        public int getCellVal(int xint y){
            return this.field[x][y].getValue();
        }

        /**
         * checks weather the position and the value are valid to be assigned or not 
         * "private" cause it would only be used in this class.
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x  x axis of the cell
         * @param y  y axis of the cell
         * @param value value of the cell
         * @return weather the position and the value are valid  
         */
        private boolean isValid(int xint yint value){
            if (value < 1 || value > 9return false;
            for(int i = 0; i < 9; i++){ //if the value already exists in same row or column
                if(field[x][i].getValue() == value || field[i][y].getValue() == valuereturn false;
            }
            if(!isValidInSquare(xyvalue)) return false//if the value already exists in its 3x3 square
            return true;
        }

        /**
         * checks weather  the value already exists in its 3x3 square or not.
         * "private" cause it would only be used in this class.
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x  x axis of the cell
         * @param y  y axis of the cell
         * @param value value of the cell
         * @return weather the value already exists in its 3x3 square or not.
         */
        private boolean isValidInSquare(int xint yint value){ //to check weather the value already exists in its 3x3 square or not.
            int rows = -1//the index of rows from which the loop will start.
            int cols = -1//the index of cols from which the loop will start.
            
            if (x < 3) rows = 0//rows will get its value depending on the value of x 
            else if(x < 6) rows = 3;
            else if(x < 9) rows = 6;

            if (y < 3) cols = 0//cols will get its value depending on the value of y
            else if(y < 6) cols = 3;
            else if(y < 9) cols = 6;
            //now we know in which square we should compare and check the values.
            int limitCols = cols+3//where the loop of cols should stop
            int holdCols = cols;    //to reassign the value of cols in each row. 
            for(int limitRows = rows+3; rows < limitRows; rows++){
                for(cols = holdCols; cols < limitCols; cols++){
                    if (field[rows][cols].getValue() == valuereturn false;
                }    
            }        
            
            return true;
        }

        /**
         * mark values for a specific cell
         * so that we can later choose from the array of the marked values the accurate one. 
         * "public" because it should be called in the Play class, which is in different package. 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x  x axis of the cell
         * @param y  y axis of the cell
         * @param value value of the cells
         * @return weather the value is successfully marked or not.
         */
        public boolean mark(int xint yint value){
            if(this.field[x][y].markValue(value)){
                System.out.printf("Marked Value %d for (%d: %d)\n"valuexy);
                return true;
            } 
             
            System.out.printf("Value %d was already marked for (%d: %d)\n"valuexy);
            return false;
        }

        /**
         * remove the given value from the array of marked values of a specific cell
         * "public" because it should be called in the Play class, which is in different package. 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x  x axis of the cell
         * @param y  y axis of the cell
         * @param value value of the cells
         * @return weather the value is successfully removed or not
         */
        public boolean unmark(int xint yint value){
            if(this.field[x][y].unmarkValue(value)){
                System.out.printf("Unmarked Value %d for (%d: %d)\n"valuexy);
                return true;
            }    

            System.out.printf("Value %d doesn't exist for (%d: %d)\n"valuexy);
            return false;
        }

        /**
         * prints the array of marked values for a specific cell
         * "public" because it should be called in the Play class, which is in different package. 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x  x axis of the cell
         * @param y  y axis of the cell
         */
        public void viewMarks(int xint y){
            System.out.println(field[x][y].printMarkArr()); 
        }

        /**
         * stores the playing field in a String so that we can print it later.
         * "public" because it is already implemented like that in the Object.java class 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @return the formated string
         */
        @Override
        public String toString(){
            String s = "   **SUDOKU GAME**\n";

            s += " |0 1 2|3 4 5|6 7 8|";
            s += "\n-+-----+-----+-----+\n";
            
            for(int i = 0; i < 9; i++){
                s += String.valueOf(i) + "|";

                for(int j = 0, count = 1; j < 9; j++,count++){
                    if (this.field[i][j].getValue() == -1) s += " ";
                    else s +=  String.valueOf(this.field[i][j].getValue());
                    if (count == 3){
                        s += "|";
                        count = 0;
                    }else s += " ";
                }
                s += "\n";
                
                if(i+1 == 3 || i+1 == 6 || i+1 == 9) s += "-+-----+-----+-----+\n"
                else s += " |     |     |     |\n";
            }
            return s;
        }
    }

    ____________________________________________________

    Position.java:



    package src.model;
    /**
     * This class represents the position of a cell in the sudokufield
     * the position consists of the x axis and y axis
     * 
     * default because it should only be called only in the same package. 
     * @author  Khaled Badran <gym4programming@gmail.com>
     * @version 19 May 2020  
    */
    class Position{
        /** 
         *  these fields are "private" because other classes should not access them directly,
         *  rather with setter and getter. 
        */ 
        private int x; /** x axis of the cell*/
        private int y; /** y axis of the cell*/

        /**
         * Cunstroctor that sets the given values to the x and y axis.
         * 
         * "public" beause Cunstroctors should always be public 
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @param x  x axis of the cell
         * @param y  y axis of the cell
        */
        public Position(int xint y){
            this.x = x;
            this.y = y;
        }

        /**
         * gets the value of the x axis 
         * "protected" because it should only be accessible to the inheriting classes
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @return value of the x axis
         */
        protected int getX() {
            return this.x;
        }

        /**
         * gets the value of the y axis 
         * 
         * "protected" because it should only be accessible to the inheriting classes
         * @author  Khaled Badran <gym4programming@gmail.com>
         * @return value of the y axis
         */
        protected int getY() {
            return this.y;
        }

    }

    ____________________________________________________

    Output:

    ____________________________________________________




    Comments