How to find the first solution only with this backtracking - java

i'm trying to write a Sudoku solver which will return only the first possible solution.
i managed to print all possible solutions with void methods but i can't stop on the first find.
i know the preferred way is to switch to boolean methods and return true up the tree -
but i can't find the right way to write it.
any way i tried always give compilation errors (method must return boolean).
public boolean recursiveSolve(int line, int column) {
if(line == N) // N is the board size (9)
return true;
// if Cell is not empty - continue
if(board1.getCell(line, column) != 0) {
return nextCell(line, column);
}
// if Cell empty - solve
else {
for(int i = 1; i <= N; i++) {
board1.setCell(line, column, i); // set value to cell
if(board1.boardIsOk()) // check if the board is legal
return nextCell(line, column); // continue
}
board1.setCell(line, column, 0); // backtrack
}
}
private boolean nextCell(int line, int column) {
if(column < 8)
return recursiveSolve(line, column+1); // progress up the row
else
return recursiveSolve(line+1, 0); // progress down the lines
}
Any help will be most appreciated.

Here is some pseudocode for most recursive backtracking problems.
If you are already at a solution, report success.
for (every possible choice in the current position ) {
Make that choice and take one step along the path.
Use recursion to solve the problem from the new position.
If the recursive call succeeds, report the success to the next higher
level.
Back out of the current choice to restore the state at the beginning
of the loop.
}
Report failure.
Here is some actual code based on a lecture from Stanford. I re-wrote it in java and included comments.
Boolean SolveSudoku(int[][] grid)
{
int row, col;
if(!FindUnassignedLocation(grid, row, col))
//all locations successfully assigned
return true;
for(int num = 1; num <= 9; num++)
{
//if number is allowed to be placed in the square
if(NoConflicts(grid, row, col, num))
{
//place the number in the square
grid[row][col] = num;
//recur, if successful then stop
if(SolveSudoku(grid))
return true;
//undo and try again
grid[row][col] = UNASSIGNED;
}
}
//this triggers backtracking from early decisions
return false;
}
You just need to implement a few methods, which are pretty trivial.

Change
if(board1.boardIsOk()) // check if the board is legal
return nextCell(line, column); // continue
into
if(board1.boardIsOk()) { // check if the board is legal
boolean solved = nextCell(line, column); // continue
if (solved) {
return true;
]
}
...
return false;

Related

Dynamic programming process

I'm trying to implement a solution to this problem but I am having some problems.
The problem is:
"There is a robot in the upper left hand corner of a grid with r rows and c columns. The robot can only move right or down and certain cell's are "off limits" meaning the robot cannot step on them. Design an algorithm to find a path for the robot from the top left to the bottom right."
The solution looks like this:
public static ArrayList<Point> getPath(boolean[][] maze){
if(maze == null || maze.length==0) return null;
ArrayList<Point> path = new ArrayList<Point>();
HashSet<Point> failedPoints = new HashSet<Point>();
if(getPath(maze, maze.length-1,maze[0].length-1,path,failedPoints)){
return path;
}
return null;
}
public static boolean getPath(boolean[][] maze, int row, int col,
ArrayList<Point> path, HashSet<Point> failedPoints){
/*if out of bounds or not available, return*/
if(col<0 || row<0 || !maze[row][col]){
return false;
}
Point p = new Point(row,col);
/*If we've already visited this cell return*/
if(failedPoints.contains(p)){
System.out.println("Worked");
return false;
}
boolean isAtOrigin = (row == 0) && (col == 0);
/*If there's a path from start to my current location, add my location.*/
if(isAtOrigin || getPath(maze,row,col -1, path, failedPoints) || getPath(maze,row-1, col, path,failedPoints)){
path.add(p);
return true;
}
failedPoints.add(p); //Cache result
return false;
}
What's confusing to me is the attempt at Dynamic Programming.
if(failedPoints.contains(p)) never evaluates to true.
I have overridden the equals and hashCode methods in my Point class so failedPoints.contains(object) evaluates to true whenever the object compared has the same row and col values.
Perhaps it has to do with the maze input i'm using:
boolean[][] maze = new boolean[4][4];
java.util.Arrays.fill(maze[0],true);
java.util.Arrays.fill(maze[1],true);
java.util.Arrays.fill(maze[2],true);
java.util.Arrays.fill(maze[3],true);
maze[0][1] = false;
maze[3][2] = false;
ArrayList<Point> path = getPath(maze);
But I'm not sure. In the end I don't see how failedPoints.contains(p) is saving my computer any execution steps
Here is the point class:
public class Point {
int row;
int col;
Point(int row1,int col1) {
row = row1;
col = col1;
}
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
Point comp = (Point) o;
return comp.row == row && comp.col == col;
}
public int hashCode() {
return row;
}
}
It's your maze's design.
This is your maze, according to the input you have written in the question:
E O O O
O O O O
O O X X
O O X S
You start at S and are trying to reach E, with X being off limit locations.
So, you see that with S being entirely covered with off limit points, there is no way you can reach E. And hence the very first point S is a failed point which is never re-used because the algorithm halts after the evaluation of S.
Perhaps if you would set the point in 0th row and 1st column as off limit, you will have multiple explorations that will reach this point and take advantage of caching to ascertain that this point cannot be used any further for exploring the maze.
UPDATE:
After you updated the maze, I realized that there are two issues with your implementation, not one.
Change the line,
if(isAtOrigin || getPath(maze,row,col -1, path, failedPoints) || getPath(maze,row-1, col, path,failedPoints))
to
if(isAtOrigin || getPath(maze,row-1,col, path, failedPoints) || getPath(maze,row,col-1, path,failedPoints))
and the code will actually work with the new maze.
The issue is that you are returning from the getPath() as soon as you find a path. And because you are first going to left and then going up, the point [0, 2] (which is a failed point) is not hit at all, and therefore not cached, and therefore not used either.
Changing the if condition causes your algorithm to first search up and then search left. This causes you to hit [0, 2] multiple times, resulting in it being cached as well as re-used in further path searches.

How do you return a zero if there is nothing in the grid where you checked?

To start things off, I am making a game. You fight on a 3x3 Grid (using a 2 Dimensional-Array), and if the "Lane#" (Lane# = Row + Col) ahead of you is blank then you get a -15% Damage Reduction, and this stacks for every blank lane.
This means if you are on [0][0] then you are in Lane# 0, and therefore, cannot possibly have anyone ahead of you, and you will always take 100% of Damage (this is of course without defense and yadda yadda else that modifies)
And if you are on [2][2] then you are in Lane# 4, and if every lane ahead of you has atleast one space in it taken, then you will take 15*4 = 60, 100-60 = 40% of actual damage.
Now that that is out of the way. I am having difficulty returning 0... I keep getting an Error that says that you cannot return a Void value...
'cannot return a value from method whose result type is void'
public Blanks(int l) { //l = Lane
int x = 0; //The Return
for (int i = 0; i < 6; i++) //The loop
if (l=0){ //Here I keep getting an error saying 'incompatible types'
x = 0;
return x; //Here is the 'cannot return a void value' error
break;
}
if (l>=1){
x++;
}
if (l>=2){
x++;
}
if (l>=3){
x++;
}
if (l>=4){
x++;
}
return x; //for some odd reason, this is also a void value
}
}
I still have yet to add the Checking the Array / Grid part as I am stumped about that one as well.. but another problem, another question.. the actual array itself..
you should modify the method header to public int Blanks(int l) {
and you should remove break; keyword because you return method value before it and will be unreached statement.
In order to return an integer value you have to mention a return type in the method. Also, in the first if statement you have used assignment operator instead of comparing.
Also why you have used break after return. I think you have to do first break and then return in the end.
One more thing to add. Your for loop should contain braces. Only the first if statement will get executed according to your code.
public int Blanks(int l) { //l = Lane
int x = 0; //The Return
for (int i = 0; i < 6; i++) //The loop
if (l==0){ //Here I keep getting an error saying 'incompatible types'
x = 0;
break;
}
if (l>=1){
x++;
}
if (l>=2){
x++;
}
if (l>=3){
x++;
}
if (l>=4){
x++;
}
return x; //for some odd reason, this is also a void value
}
}
I haven't stepped into your logic. Comment if you face any problem after this.
I don't understand why you are using the for loop here, but this is a way to do it:
public int Blanks(int l) {
int x = 0;
for (int i = 0; i < 6; i++)
if (l==0){
x = 0;
}else {
x++;
}
return x;
}
But in case that l==0 your method will return 5;
If you want to return 0 or 1 then you need to remove the for loop
public int Blanks(int l) {
if (l==0) return 0;
else return 1;
}
And the method with true-false:
public boolean Blanks(int l) {
if (l==0) return false;
else return true;
}

Sudoku backtracking algorithm (Java)

I've created a Sudoku solver that will solve a Sudoku as a human might- by checking possibilities + definite values in squares corresponding to the square being checked.
(Source: http://pastebin.com/KVrXUDBF)
However, I would like to create a random Sudoku generator (from a blank grid), and so have decided to use a backtracking algorithm. I understand the concept of backtracking, but am confused about one thing:
How do I know which previous node to return to (and change) once I know a certain solution is not allowed?
Should I simply return to the previous node and cycle through all possibilities? (And then if this yields no correct answers, return to the value before, etc.). This seems like a viable method, but also quite inefficient. Is this the correct way of implementing a backtracking method or is there a better way to go about it?
Thanks in advance.
More can be found about backtracking here: http://en.wikipedia.org/wiki/Backtracking
Sudoku Puzzle can be reduced to graph coloring problem which can be solved using simple backtracking like assigning colors to node (1-9) till the there is no violation that all directly connected nodes have no same color.
Constructing Graph from Sudoku : -
There is an direct edge between two grid points if they are in same
row or column or square.
Backtracking :-
Assign one color (1-9) to node
Check if there is no other directly connected node with same color
If valid color move to next node.
else change the color and recheck.
If all color exhausted backtrack to previous node.
Do recursion till all nodes are color.
Once You are done with it you can start removing numbers from the grid at random till you think the problem is unsolvable if any more numbers are removed.
A simple way to generate random Sudoku is that
1) generate a random completing Sudoku, that is, generate random Sudoku no square is blank.
2) Remove numbers from squares of 1).
3) Solve Sudoku of 2). If there are many solutions, then add a number removed at 2).
If there are still many solutions, then repeat 3).
1) sample source code:
public int[][] generateRandomCompleteSudoku() {
int[][] sudoku = new int[10];
for(int i = 1; i <= 9; i++) {
sudoku[i] = new int[10];
Arrays.fill(sudoku[i], 0);
}
generateRandomCompleteSudoku(sudoku, 1, 1);
return sudoku;
}
private boolean generateRandomCompleteSudoku(int[][] sudoku, int x, int y) {
if(x > 9) {
x = 1;
y++;
}
//sudoku of the argument is completing sudoku.
//so return true
if(y > 9) {
return true;
}
// enumerate the possible numbers of the pos(x,y).
List<Integer> possibleNumbers = new ArrayList<Integer>();
for(int i = 1; i <= 9; i++) {
boolean possible = true;
//check i is a possible number.
//check there isn't i in the raw of y .
for(int j = 1; j <= x - 1; j++) {
if(sudoku[j][y] == i) {
possible = false;
break;
}
}
//check there isn't i in the column of x(omitted).
//check there isn't i in the group of x,y(omitted).
if(possible) {
possibleNumbers.add(i);
}
}
//sudoku is wrong so return false.(There is no solution of sudoku)
if(possibleNumbers.size() <= 0) {
return false;
}
Collections.shuffle(possibleNumbers);// This gives sudoku randomness.
for(Integer possibleNumber : possibleNumbers) {
sudoku[x][y] = possibleNumber;
// a sudoku is generated, so return true
if(generateRandomCompleteSudoku(sudoku, x + 1, y)) {
return true;
}
}
// No sudoku is generated, so return false
return false;
}
For a backtracking solution, the first step is to define the state. So for this problem, I think the most straightforward way is (x,y, blank , num) with x , y is the position of the current state, blank is the number of blank position left, and num is the value you want to fill in that position (from 0 to 9 and 0 means blank).
And the return type should be boolean, which determine whether the move is valid or not (which means is there any valid solution for this move).
So, the state transition is column by column, row by row: x, y to x , (y + 1) or x , y to (x + 1), 0.
Similarly, the blank will be from a -> a - 1-> ... 0.
We have a draft solution here:
public boolean move(int x, int y, int blank, int num, int[][]sudoku){
sudoku[x][y] = num;
//checking condition and return if x,y is the last position, code omitted
if(y == sudoku[x].length){
x++;
y = 0;
}else{
y++;
}
for(int i = 1; i < 10; i++){
if(move(x,y,blank,i,sudoku){//Backtrack here
return true;
}
}
if(blank > 0){
if(move(x,y,blank - 1, 0, sudoku){//Backtrack here
return true;
}
}
return false;
}
So when ever there is a false return from the current state, it will backtrack to the last state , and the last state will continue to check for the next num until it find a correct solution (or return false).

Java Maze Solver

I'm having difficulty trying to turn a algorithm that was hinted to us into usable code. We are given a Direction enum that has the 8 coordinates (N, NE, NW, S, SE. SW. E, W) along with the exit HERE.
This is the hinted algorithm:
getPathToExit(row, col):
if (row, col) is outside of the map:
return an empty list
else if (row, col) is an obstacle:
return an empty list
else if (row, col) is marked as visited or as deadend:
return an emtpy list
else if (row, col) is the exit:
//optional: mark exit as visited
return a list containing Direction.HERE
else:
//try to find a path from current square to exit:
mark current square as visited (that is, part of path)
for each neighbor of current square:
path = path from neighbor to exit
if path is not empty:
add (direction to neighbor) to start of path
return path
//after for loop: no path exists from this square to exit
mark current square as deadend
return empty list
This is the code I have been working on for a while:
public java.util.ArrayList<Direction> getPathToExit(){
for (int x=0; x<map.length; x++){
for (int y=0; y<map[x].length; y++){
if (map[x][y]=='S'){
this.startRow=x;
this.startCol=y;
}
}
}
System.out.println("start "+startRow+", "+startCol);
return getPathToExit(this.startRow, this.startCol);
}
private java.util.ArrayList<Direction> getPathToExit(int row, int col){
Direction [] dirs = Direction.values();
ArrayList<Direction> path = new ArrayList<Direction>();
getPathToExit(row, col);
if (row < 0 || col < 0 || row > map.length || col > map[row].length){
return null;
}
else if (map[row][col] != ' '){
return null;
}
else if (map[row][col] == 'E'){
path.add(Direction.HERE);
return path;
}
else {
for (int x=0; x<dirs.length-1; x++){
int nextRow = row + dirs[x].getRowModifier();
int nextCol = col + dirs[x].getColModifier();
path = getPathToExit(nextRow, nextCol);
}
}
return path;
}
This is the enum class:
public enum Direction {
N, NE, E, SE, S, SW, W, NW, HERE;
/**
* Returns the X/column change on the screen that is associated with
* this direction: -1 for W, 0 for N/S, and +1 for E.
*/
public int getColModifier() {
int mod;
switch (this) {
case NW:
case W:
case SW:
mod = -1;
break;
case NE:
case E:
case SE:
mod = +1;
break;
default:
mod = 0;
break;
}
return mod;
}
/**
* Returns the Y/row change on the screen that is associated with
* this direction: -1 for N, 0 for E/W, and +1 for south.
*/
public int getRowModifier() {
int mod;
switch (this) {
case N:
case NE:
case NW:
mod = -1;
break;
case S:
case SE:
case SW:
mod = +1;
break;
default:
mod = 0;
break;
}
return mod;
}
/** As {#link #getColModifier()} */
public int getXModifier() {
return this.getColModifier();
}
/** As {#link #getRowModifier()} */
public int getYModifier() {
return this.getRowModifier();
}
/**
* Returns the direction that is the opposite of this one.
* For example, <code>Direction.NE.reverse() == Direction.SW</code>.
* (The opposite of HERE is still HERE though.)
*/
public Direction reverse() {
if (this == HERE) {
return this;
}else {
int reversed = (this.ordinal() + 4) % 8;
Direction[] dirs = Direction.values();
return dirs[reversed];
}
}
}
Thanks in advance.
There are two issues in the code:
(1)
In the main for loop:
for (int x=0; x<dirs.length-1; x++){
int nextRow = row + dirs[x].getRowModifier();
int nextCol = col + dirs[x].getColModifier();
path = getPathToExit(nextRow, nextCol);
}
You need to check if the recursive call: getPathToExit() returned a not null list. If it had, you should break the loop and push the relevant direction to its start. You already found a path - not point to keep on checking the rest!
(2) In order for your algorithm to be complete (find a solution if one exists), you need to maintain a visited set, and avoid revisiting already visited nodes.
Have a look at the following example:
-------
|S |x1|
-------
|x2|E |
-------
where all are valid squares (no obstacles), S is the start and E is the end.
Now, assume the order of directions is right,left, ....
The code (without visited set) will do the following:
go right (to x1).
go right - out of maze, go back.
go left (to S).
go right (to x1).
go right - out of maze, go back.
go left (to S)
....
You are in an infinite loop! (one known draw back of DFS)
The StackOverflowError is usually an indication that this is the issue, the call stack is full from all the recursive calls - and an error is thrown.
To fix it, you need to maintain a visited set, and avoid revisitting already visited nodes. With this set, and the above maze (order of directions is right, left, down, ...) what will happen is:
go right (to x1)
go right - out of maze, go back.
go left (to S) - already visitted, go back.
go down (to E) - found target, return it.
A more advanced alternative is using Iterative Deepening DFS - which basically mean, you are limitting the length of the path to l, and iteratively increase this l. I'd ignore this alternative for this time, it is a bit more advanced.
As a side note, your algorithm is an implementation of DFS, which is complete with a visited set and in finite graphs (always finds a solution if one exists), but not optimal (does not guarantee to find the shortest path). To find the shortest path, you might want to use BFS instead.
Also: I assume the recursive call in the third line of the method is a leftover that is there for debugging. It shouldn't be there.

java recursion on array

I have to create a program that finds all the possible ways of filling a square of size x by y. You place a block which takes up 2 spaces to completely fill.
The problem is I don't know how to code it to the point where you can remember the placements of each square. I can get it to where it fills the board completely once and maybe twice, but nothing past that. I also know that I'm supposed to use recursion to figure this out . Here is the code I started on so far. There is also a main method and I have the initial even/odd check working fine. This is the part I have no idea on.
public void recurDomino(int row, int column) {
if (Board[2][x - 1] != false) {
} else if(Board[1][x-1]!=false)
{
}
else {
for (int n=0; n < x - 1; n++) {
Board[row][column] = true;
Board[row][column+1] = true;
column++;
counter++;
}
recurDomino(1, 0);
recurDomino(2, 0);
}
}
Thank you for any help you guys can give me.
******************* EDIT ****************************************
I am a little confused still. I came up with this algorithm but I always get 2 for any value greater or equal to 2.
public boolean tryHorizontal(int row , int col){
if( row < 0 || row >= array[0].length-1)
return false;
else
return true;
}
public boolean tryVertical(int row, int col){
if( col < 0 || col >= 2 )
return false;
else
return true;
}
public boolean tryRowCol(int row, int col){
if(this.tryHorizontal(row, col) && this.tryVertical(row, col)){
return true;
}
else
return false;
}
public int findWays(int row, int col){
int n = 0;
if( !this.tryRowCol(row, col))
return 0;
else
n =+ 1 + this.findWays(row+1, col+1);
return n;
}
This recursive solution actually generates all the possible tiling of a general MxN board. It's more general than what your program requires, and therefore not optimized to just count the number of tiling of a 3xN board.
If you just want to count how many there are, you can use dynamic programming techniques and do this much faster. Also, having the number of rows fixed at 3 actually makes the problem considerably easier. Nonetheless, this general generative solution should be instructive.
public class Domino {
final int N;
final int M;
final char[][] board;
int count;
static final char EMPTY = 0;
Domino(int M, int N) {
this.M = M;
this.N = N;
board = new char[M][N]; // all EMPTY
this.count = 0;
generate(0, 0);
System.out.println(count);
}
void printBoard() {
String result = "";
for (char[] row : board) {
result += new String(row) + "\n";
}
System.out.println(result);
}
void generate(int r, int c) {
//... see next code block
}
public static void main(String[] args) {
new Domino(6, 6);
}
}
So here's the meat and potatoes:
void generate(int r, int c) {
// find next empty spot in column-major order
while (c < N && board[r][c] != EMPTY) {
if (++r == M) {
r = 0;
c++;
}
}
if (c == N) { // we're done!
count++;
printBoard();
return;
}
if (c < N - 1) {
board[r][c] = '<';
board[r][c+1] = '>';
generate(r, c);
board[r][c] = EMPTY;
board[r][c+1] = EMPTY;
}
if (r < M - 1 && board[r+1][c] == EMPTY) {
board[r][c] = 'A';
board[r+1][c] = 'V';
generate(r, c);
board[r][c] = EMPTY;
board[r+1][c] = EMPTY;
}
}
This excerpt from the last few lines of the output gives an example of a generated board, and the final count.
//... omitted
AA<><>
VVAA<>
AAVV<>
VVAA<>
<>VVAA
<><>VV
//... omitted
6728
Note that 6728 checks out with OEIS A004003.
A few things that you need to learn from this solutions are:
Clean-up after yourself! This is a very common pattern in recursive solution that modifies a mutable shared data. Feel free to do your thing, but then leave things as you found them, so others can do their thing.
Figure out a systematic way to explore the search space. In this case, dominoes are placed in column-major order, with its top-left corner as the reference point.
So hopefully you can learn something from this and adapt the techniques for your homework. Good luck!
Tip: if you comment out the printBoard line, you can generate all ~13 million boards for 8x8 in reasonable time. It'll definitely be much faster to just compute the number without having to generate and count them one by one, though.
Update!
Here's a recursive generator for 3xN boards. It doesn't use a shared mutable array, it just uses immutable strings instead. It makes the logic simpler (no clean up since you didn't make a mess!) and the code more readable (where and how the pieces are placed is visible!).
Since we're fixed at 3 rows, the logic is more explicit if we just have 3 mutually recursive functions.
public class Domino3xN {
static int count = 0;
public static void main(String[] args) {
addRow1(8, "", "", "");
System.out.println(count);
}
static void addRow1(int N, String row1, String row2, String row3) {
if (row1.length() == N && row2.length() == N && row3.length() == N) {
count++; // found one!
System.out.format("%s%n%s%n%s%n%n", row1, row2, row3);
return;
}
if (row1.length() > row2.length()) { // not my turn!
addRow2(N, row1, row2, row3);
return;
}
if (row1.length() < N - 1)
addRow2(N, row1 + "<>",
row2,
row3);
if (row2.length() == row1.length())
addRow3(N, row1 + "A",
row2 + "V",
row3);
}
static void addRow2(int N, String row1, String row2, String row3) {
if (row2.length() > row3.length()) { // not my turn!
addRow3(N, row1, row2, row3);
return;
}
if (row2.length() < N - 1)
addRow3(N, row1,
row2 + "<>",
row3);
if (row3.length() == row2.length())
addRow1(N, row1,
row2 + "A",
row3 + "V");
}
static void addRow3(int N, String row1, String row2, String row3) {
if (row3.length() == row2.length()) { // not my turn!
addRow1(N, row1, row2, row3);
return;
}
if (row3.length() < N - 1)
addRow1(N, row1,
row2,
row3 + "<>");
}
}
You don't often see 3 mutually recursive functions like this, so this should be educational.
One way of doing it is with the CSP (Constraint Satisfaction Problem) approach:
Consider every cell in the grid to be a variable, with 4 possible values (indicating the part of the domino it takes). Some assignments are obviously illegal. Legal assignments assign values to a "neighboring variable" as well. Your goal is to assign all the 3xN variables with legal values.
The recursion here can help you cover the state space easily. On each invocation, you try to assign a value to the next unasigned cell, by trying all the 4 options. After each successfull assignment, you can call the same method recursively, and then undo your last assignment (this way you don't have to clone anything - one copy of the grid data is enough).
--EDIT--
If you want to do it efficiently so that it works for large values on N in reasonable time, you will also have to think about optimizations, in order to discard some assignment attempts.
Here are some hints:
With a fixed-size board you can precompute the exact number of steps that each solution takes, so the termination criterion is trivial: you just check the nesting level.
Starting from one corner is a good idea, because it means that you can always find a field that can only be covered in two different ways (vertically or horizontally).
That means that you have a branching factor of only 2, and a recursion depth of 3*N/2, which is probably small enough that you can just clone the sstate of the board for each call (ordinarily you would construct new states incrementally from existing states to save space, but that is a bit harder to program).
In many states here will be more than one field that allows only two possibilities; with a clever strategy for choosing the next field, you can ensure that you will never find the same solution via two different paths, so you don't even have to check the solutions for duplicates.
The state of the board must record which fields are free and which fields are occupied, but also which fields are occupied by the same domino, so an array of int could do the trick.

Categories

Resources