[Java] Sudoku tester in an “object oriented” way

As a result of one of my job small talks, It emerged the need to propose a possible solution to the following: “if a system receives a filled sudoku, what and how do you process that information to return a simple boolean variable that tells if the sudoku is solved right or wrong?”.

Once at home, I decided to give a formal an “object oriented” solution to this. Here is my approach.

1) Foreword: information about the problem

The system receive a sudoku filled, as seen in the picture below:

We are going to model the sudoku as a 9×9 matrix.

We need to check 3 conditions to decide if the sudoku is rightly or wrongly filled:

  1. Check if each of the 9 rows contains 1 to 9 numbers, once each.
  2. Check if each of the 9 columns contains 1 to 9 numbers, once each.
  3. Check if each of the 9 3×3 squares contains 1 to 9 numbers, once each.

2) Classes description

As you have found out, the three conditions above are very similar: we can check them by using a 1×9 vector. So, the first class we have to implement is that vector (Vector.java), which is going to be also a bean.

What we are going to need also is a class that contains one of these vectos, and with some methods implemented that let us check the three conditions. Actually, we need only one method, because (due to the vector implementation), the 3 conditions have the same purpose: check that the 9 numbers from 1 to 9 are inside the vector.  So, we are going to implement a class (called Vectest.java), that is a bean too, and contains a vector, and a “method to check the if the input vector is correct” in 2 different ways:

  • Passing the vector while initializing the object (through the constructor Vectest(vector))  and then calling the boolean method check().
  • Initializing the object, then passing the vector though a setter (setVectorTest(Vector)) and then calling the boolean method check().

The last method we need is (due to the typical Java SE implementation) a class that contains a main method (which is called Sudoku.java).

3) Solution: Java code

3.1) Vector class:


package beans;

public final class Vector {
	protected int [] vectortest = {1,1,1,1,1,1,1,1,1};

	public  Vector(String ent){
		//check if the string size is 8 characters and is formed by numbers from 1 to 9
		if (ent.length()== 9 && ent.matches("[1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9][1-9]"))
			{
				for (int i=0;i<=8;i++){
					//pass the input to the vectortest
					this.vectortest[i]=Integer.parseInt(ent.substring(i, i+1));
				}
			}
		//if the ent String does not match the above conditions, it continues with the initialized values
	}
	//constructor overriding
	public Vector(){

	}

}

3.2) Vectest class:


package beans;

/*
 * This class can be used in two ways:
 * 1. Instantiate a Vectest()-> set the vector->check()
 * 2. Instantiate a Vectest(string)-> check()
 */

public class Vectest {

	private boolean resultVect;
	private Vector vecTest;

	public Vectest(){

	}
	public Vectest(String s) {
		Vector vectorint = new Vector (s);
		vecTest = vectorint;
		//by default, resultVect=true. just in case all the 9 numbers are not found, then it will be changed to resultVect=false
		this.resultVect=true;
	}

	public void setVectortest(String s){
		Vector vectorint = new Vector (s);
		vecTest = vectorint;
		//by default, resultVect=true. just in case all the 9 numbers are not found, then it will be changed to resultVect=false
		this.resultVect=true;
	}

	public boolean check (){
		//by default, resultVect=true. just in case all the 9 numbers are not found, then it will be changed to resultVect=false
		//i= numbers to check (from 1 to 9)
		for (int i= 1; i<=9;i++){
			//j = vector occurrencies (from 0 to 8)
			for (int j= 0; j<=8;j++){
				if (vecTest.vectortest[j] == i)
					break;
				else if(j == 8)
					//if we get to the last occurrence and we do not find the number "i", the result is not-ok (resultVect=false)
					this.resultVect=false;
			}
		}
		return this.resultVect;
	}

}

3.3) Sudoku class (main class):


package core;

import beans.Vectest;;

public class Sudoku {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		String sudoku = new String ("164739528" +
									"857462319" +
									"923815674" +
									"682543197" +
									"341987256" +
									"795621483" +
									"479256831" +
									"518394762" +
									"236178945");
		boolean result=true;

		boolean finalCondition1=true;
		boolean finalCondition2=true;
		boolean finalCondition3=true;

		Vectest vectorRow = new Vectest();

		//first condition: rows
		for (int i=0; i<=8; i++){
			//passing the row to the vectorRow
			vectorRow.setVectortest(sudoku.substring(i*8, i*8+9));
			if(!vectorRow.check())
				finalCondition1=false;
				break;
		}
		if (finalCondition1==false)
			result=false;
		else{
			//second condition: columns
			for (int i=0; i<=8; i++){
				//passing the column to the vectorRow
				String column = sudoku.substring(i, i+1) + sudoku.substring(i+9,i+10) + sudoku.substring(i+18,i+19)+ sudoku.substring(i+27,i+28)+ sudoku.substring(i+36,i+37)+ sudoku.substring(i+45,i+46)+ sudoku.substring(i+54,i+55)+ sudoku.substring(i+63,i+64)+ sudoku.substring(i+72,i+73);
				vectorRow.setVectortest(column);
				if(!vectorRow.check()){
					finalCondition2=false;
					break;
				}
			}
			if (finalCondition2==false)
				result=false;
			else{
				for (int i=0; i<=8; i++){
					int x=0;//default
					int y=0;//default
					//third condition: 3x3 squares
					switch (i){
						case 1:
							x=3;
							break;
						case 2:
							x=6;
							break;
						case 3:
							y=3;
							break;
						case 4:
							x=3;
							y=3;
							break;
						case 5:
							x=6;
							y=3;
							break;
						case 6:
							y=6;
							break;
						case 7:
							x=3;
							y=6;
							break;
						case 8:
							x=6;
							y=6;
							break;
					}

					//lets extract each of the three rows of the square using the x and y positions
					String row1= sudoku.substring((9*y)+x,(9*y)+x+3);
					String row2= sudoku.substring((9*(y+1))+x,(9*(y+1))+x+3);
					String row3= sudoku.substring((9*(y+2))+x,(9*(y+2))+x+3);
					//now we can join the 3 rows
					String square= row1+row2+row3;
					vectorRow.setVectortest(square);
					if(!vectorRow.check()){
						finalCondition3=false;
						break;
					}
				}
				if (finalCondition3==false)
					result=false;
			}
		}
		if (result)
			System.out.println("The sudoku is correct");
		else
			System.out.println("The sudoku is wrong");
	}

}

I have been putting off this post some in order to write with the aim that it should be shown in the most formal and detailed way, and maybe anyday in the future I will modify it, introducing some UML2 diagrams or additional implementation. But I think it is easier and the code is clearer enough to release it in its current status.

Any suggestion through comments are welcome.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s