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:
📥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) == -1) return 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 x, int y) {
super(x, y); //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 x, int y, int value){
if(isValid(x, y, value)){
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 x, int 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 x, int y, int value){
if (value < 1 || value > 9) return 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() == value) return false;
}
if(!isValidInSquare(x, y, value)) 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 x, int y, int 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() == value) return 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 x, int y, int value){
if(this.field[x][y].markValue(value)){
System.out.printf("Marked Value %d for (%d: %d)\n", value, x, y);
return true;
}
System.out.printf("Value %d was already marked for (%d: %d)\n", value, x, y);
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 x, int y, int value){
if(this.field[x][y].unmarkValue(value)){
System.out.printf("Unmarked Value %d for (%d: %d)\n", value, x, y);
return true;
}
System.out.printf("Value %d doesn't exist for (%d: %d)\n", value, x, y);
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 x, int 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 x, int 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:
please watch the video.
____________________________________________________
Comments
Post a Comment