When I call method backtrack a second time from within it (backtrack) because I need to go back two moves, it does not work. Does anyone have any idea? Here is my code:
// width of board
static final int SQUARES = 8;
// board
static boolean[][] board = new boolean[SQUARES][SQUARES];
// represents values for number of squares eliminated if queen is placed in square
static int[][] elimination = new int[SQUARES][SQUARES];
// store position of queens
static boolean[][] position = new boolean[SQUARES][SQUARES];
// store row
static int[] row = new int[8];
// store column
static int[] column = new int[8];
// Write a program to solve the Eight Queens problem
public static void main(String[] args)
{
Arrays.fill(row, -1);
Arrays.fill(column, -1);
// reset elimination table
fillElim();
// count queens on board
short counter = 0;
// while board is not full
while(counter < 8) {
// place next queen on board
placeQueen(-1, -1);
// reset elimination table
fillElim();
// backtrack and fill board back to this point
while(isFull() && counter < 7)
backtrack(counter);
counter++;
} // end while
System.out.println("Queens on board: " + counter);
printBoard();
for(int i = 0; i < row.length; i++)
System.out.println(column[i] + "/" + row[i]);
} // end method main
// Print elimination table
public static void printE()
{
for(int i[] : elimination) {
for(int j = 0; j < i.length; j++)
System.out.printf("%-3d", i[j]);
System.out.println();
} // end for
} // end printE
public static void printBoard()
{
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board.length; j++) {
if(board[i][j] && position[i][j])
System.out.print("o ");
else if(board[i][j])
System.out.print("x ");
else
System.out.print("% ");
} // end inner for
System.out.println();
} // end outer for
} // end method printBoard
// Write method to calculate how many squares are eliminated if queen is placed in that square
public static void fillElim()
{
// if any squares that could be eliminated already are eliminated, subtract 1
for(int i = 0; i < elimination.length; i++) {
for(int j = 0; j < elimination[i].length; j++) {
elimination[i][j] = openSquares(i, j);
} // end inner for
} // end outer for
} // end method fillElimination
// Number of squares eliminatable by placing queen in any given square
public static int openSquares(int row, int column)
{
// if square is already eliminated, it cannot be used
if(board[row][column])
return 0;
// total number of squares elimintable from any given square, count square itself
int total = 1 + openHorizontal(row) + openVertical(column) + openUpSlope(row, column) + openDownSlope(row, column);
return total;
} // end method openSquares
// Return number of open squares in a row
public static int openHorizontal(int row)
{
// total of row
int total = 0;
for(boolean b : board[row]) {
// if square is "true" (open), increment total open squares
if(!b)
total++;
} // end for
// return total not counting current square
return total - 1;
} // end method openHorizontal
// Return number of open squares in a column
public static int openVertical(int column)
{
// total of column
int total = 0;
// if square is "true" (open), increment total open squares
for(boolean[] b : board) {
// if square is "true" (open), increment total open square
if(!b[column])
total++;
} // end for
// return total not counting current square
return total - 1;
} // end method openVertical
// Return number of open squares in a column
public static int openDownSlope(int x, int y)
{
// total of downward-sloping diagonal
int total = 0;
// if square is "true" (open), increment total open squares
for(int i = 0; i < board.length; i++) {
// test all values before use to prevent array index errors
// all squares to the top right of the checking square
if(x+i >= 0 && x+i < board.length && y+i >= 0 && y+i < board.length) {
// else increment total
if(!board[x+i][y+i])
total++;
} // end if
// all squares to the bottom left of the checking square
if(x-i >= 0 && x-i < board.length && y-i >= 0 && y-i < board.length) {
// else increment total
if(!board[x-i][y-i])
total++;
} // end if
} // end for
// return total not counting current square
return total - 2;
} // end method openDownSlope
// Return number of open squares in a column
public static int openUpSlope(int x, int y)
{
// total of upward-sloping diagonal
int total = 0;
// if square is "true" (open), increment total open squares
for(int i = 0; i < board.length; i++) {
// test all values before use to prevent array index errors
// all squares to the top right of the checking square
if(x+i >= 0 && x+i < board.length && y-i >= 0 && y-i < board.length) {
// else increment total
if(!board[x+i][y-i])
total++;
} // end if
// all squares to the bottom left of the checking square
if(x-i >= 0 && x-i < board.length && y+i >= 0 && y+i < board.length) {
// else increment total
if(!board[x-i][y+i])
total++;
} // end if
} // end for
// return total not counting current square
return total - 2;
} // end method openDownSlope
// Are all squares on the board filled?
public static boolean isFull()
{
for(boolean b[] : board) {
for(boolean bb : b) {
if(!bb)
return false;
} // end inner for
} // end outer for
// if this point is reached, board is full
return true;
} // end method isFull
// Place a queen on the board
public static void placeQueen(int lastRow, int lastCol)
{
int[] bestSquare = bestMove(lastRow, lastCol);
System.out.println("&&&&&&");
for(int i = 0; i < row.length; i++)
System.out.println(row[i] + "/" + column[i]);
System.out.println("&&&&&&");
// assign queen to board
board[bestSquare[0]][bestSquare[1]] = true;
printBoard();
System.out.println();
// clear blocked squares from board
elimSquares(bestSquare[0], bestSquare[1]);
// reset elimination table
fillElim();
// store squares
for(int i = 0; i < row.length; i++) {
if(row[i] == -1) {
row[i] = bestSquare[0];
column[i] = bestSquare[1];
break;
} // end if
} // end for
// mark queen's position
position[bestSquare[0]][bestSquare[1]] = true;
printBoard();
} // end method placeQueen
// Return lowest number in elimination table
public static int[] bestMove(int lastRow, int lastCol)
{
// store lowest number - set to impossibly low
int low = 100;
// store coordinates
int[] move = {-1, -1};
// store limit of use
int limit;
if(lastRow == -1)
limit = 0;
else
limit = elimination[lastRow][lastCol];
// if lastRow is not -1, search for duplicate numbers after current square
if(lastRow != -1) {
// test for equal elimination numbers farther down on board
for(int i = lastRow; i < board.length; i++) {
for(int j = lastCol+1; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] == limit) {
move[0] = i;
move[1] = j;
return move;
}
} // end inner for
} // end outer for
} // end if
// test for any available squares left on board
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] > limit && elimination[i][j] < low)
low = elimination[i][j];
} // end inner for
} // end outer for
// get move coordinates for square, if needed to get best square after two backtracks
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] == low) {
move[0] = i;
move[1] = j;
return move;
} // end if
} // end inner for
} // end outer for
return move;
} // end method bestMove
public static void elimSquares(int row, int column)
{
// total number of squares elimintable from any given square, count square itself
elimHorizontal(row);
elimVertical(column);
elimUpSlope(row, column);
elimDownSlope(row, column);
} // end method openSquares
// Eliminate row
public static void elimHorizontal(int row)
{
// eliminate row
for (int i = 0; i < board[row].length; i++)
board[row][i] = true;
} // end method elimHorizontal
// Eliminate column
public static void elimVertical(int column)
{
// eliminate column
for(boolean[] b : board)
b[column] = true;
} // end method elimVertical
// Eliminate downward slope
public static void elimDownSlope(int x, int y)
{
// loop through downward slope
for(int i = 0; i < board.length; i++) {
// test all values before use to prevent array index errors
// eliminate all squares to the bottom right of the checking square
if(x+i >= 0 && x+i < board.length && y+i >= 0 && y+i < board.length)
board[x+i][y+i] = true;
// eliminate all squares to the top left of the checking square
if(x-i >= 0 && x-i < board.length && y-i >= 0 && y-i < board.length)
board[x-i][y-i] = true;
} // end for
} // end method elimDownSlope
// Eliminate upward slope
public static void elimUpSlope(int x, int y)
{
// loop through upward slope
for(int i = 0; i < board.length; i++) {
// test all values before use to prevent array index errors
// eliminate all squares to the bottom right of the checking square
if(x+i >= 0 && x+i < board.length && y-i >= 0 && y-i < board.length)
board[x+i][y-i] = true;
// eliminate all squares to the top left of the checking square
if(x-i >= 0 && x-i < board.length && y+i >= 0 && y+i < board.length)
board[x-i][y+i] = true;
} // end for
} // end method elimDownSlope
// If not found solution and board is full
public static void backtrack(int lastMove)
{
// store last move
int lastRow = row[lastMove];
int lastCol = column[lastMove];
// clear board
resetBoard();
// go back 1 move
goBack(lastMove);
// refill board
for(int i = 0; i < row.length; i++) {
// escape if out of bounds
if(row[i] == -1)
break;
// replace queens
board[row[i]][column[i]] = true;
// fill elimination table
elimSquares(row[i], column[i]);
} // end for
// while no open squares, go back one more row
// keep track of times looped
int counter = 0;
while(!openSpaces(lastRow, lastCol)) {
System.out.println("backtrack " + counter);
backtrack(lastMove-1);
counter++;
} // end while
// set queen in square
placeQueen(lastRow, lastCol);
} // end method backtrack
// Clear board
public static void resetBoard()
{
// clear board
for(boolean[] b : board)
for(int j = 0; j < b.length; j++)
b[j] = false;
} // end method resetBoard
// Go back 1 move
public static void goBack(int lastMove)
{
// remove queen from last position
position[row[lastMove]][column[lastMove]] = false;
// remove last move from table
row[lastMove] = -1;
column[lastMove] = -1;
} // end method goBack
// Return number of open, untested spaces on board
public static boolean openSpaces(int lastRow, int lastCol)
{
// store number of open, untested squares
int squares = 0;
// store limit of use
int limit = elimination[lastRow][lastCol];
// store next limit for use if no more squares at limit
int nextLimit = limit + 1;
// test for equal elimination numbers farther down on board
for(int i = lastRow; i < board.length; i++) {
for(int j = lastCol+1; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] == limit)
squares++;
} // end inner for
} // end outer for
// test for any available squares left on board
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] >= nextLimit)
squares++;
} // end inner for
} // end outer for
return squares != 0;
} // end method openSpaces
This calls method goBack; method placeQueen, which calls method bestMove; and a few others. These three mentioned methods may also have an error, I do not know for sure:
// Go back 1 move
public static void goBack(int lastMove)
{
// remove queen from last position
position[row[lastMove]][column[lastMove]] = false;
// remove last move from table
row[lastMove] = -1;
column[lastMove] = -1;
} // end method goBack
// Place a queen on the board
public static void placeQueen(int lastRow, int lastCol)
{
int[] bestSquare = bestMove(lastRow, lastCol);
System.out.println("&&&&&&");
for(int i = 0; i < row.length; i++)
System.out.println(row[i] + "/" + column[i]);
System.out.println("&&&&&&");
// assign queen to board
board[bestSquare[0]][bestSquare[1]] = true;
printBoard();
System.out.println();
// clear blocked squares from board
elimSquares(bestSquare[0], bestSquare[1]);
// reset elimination table
fillElim();
// store squares
for(int i = 0; i < row.length; i++) {
if(row[i] == -1) {
row[i] = bestSquare[0];
column[i] = bestSquare[1];
break;
} // end if
} // end for
// mark queen's position
position[bestSquare[0]][bestSquare[1]] = true;
printBoard();
} // end method placeQueen
// Return lowest number in elimination table
public static int[] bestMove(int lastRow, int lastCol)
{
// store lowest number - set to impossibly low
int low = 100;
// store coordinates
int[] move = {-1, -1};
// store limit of use
int limit;
if(lastRow == -1)
limit = 0;
else
limit = elimination[lastRow][lastCol];
// if lastRow is not -1, search for duplicate numbers after current square
if(lastRow != -1) {
// test for equal elimination numbers farther down on board
for(int i = lastRow; i < board.length; i++) {
for(int j = lastCol+1; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] == limit) {
move[0] = i;
move[1] = j;
return move;
}
} // end inner for
} // end outer for
} // end if
// test for any available squares left on board
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] > limit && elimination[i][j] < low)
low = elimination[i][j];
} // end inner for
} // end outer for
// get move coordinates for square, if needed to get best square after two backtracks
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
if(!board[i][j] && elimination[i][j] == low) {
move[0] = i;
move[1] = j;
return move;
} // end if
} // end inner for
} // end outer for
return move;
} // end method bestMove
I think that placeQueen is somehow being called before backtrack within the backtrack method.
P.S. This is not the same question as https://stackoverflow.com/questions/20111154/use-elimination-heuristic-to-solve-eight-queens-puzzle. There I was asking what I needed to do; here I am asking why my method did not work.
There is btw. a simpler way to solve the queens problem.
This program will print out all 92 solutions.
public class Queens {
static int counter = 0;
static int[] pos = new int[8];
static void printBoard(){
for(int p: pos) {
for(int i = 0; i < p; i++) System.out.print(".");
System.out.print("Q");
for(int i = p+1; i < 8; i++) System.out.print(".");
System.out.println();
}
System.out.println();
}
static boolean threatened(int x, int y){
for (int i = 0; i < y; i++){
int d = y - i;
if(pos[i] == x || pos[i] == x - d || pos[i] == x + d) {
return true;
}
}
return false;
}
static void place(int y) {
for(int x = 0; x < pos.length ; x++){
if(!threatened(x, y)){
pos[y] = x;
if(y == 7){
printBoard();
counter++;
} else{
place(y + 1);
}
}
}
}
public static void main(String[] args){
place(0);
System.out.print("found " + counter + " solutions");
}
}
Related
I made the 8x8 chess board and have a lot of the code done, but for some reason it only print out one solution, does anyone know why this may be and how I can fix it?
public class NonAttackingQueens {
private int[][] board;
private int solutionCount = 0;
private boolean solutionFound = false;
public NonAttackingQueens() {
board = new int[8][8];
}
public boolean canPlace(int x, int y) {
// Check if a queen is already placed at position (x, y)
if (board[x][y] == 1) {
return false;
}
// Check horizontal positions
for (int i = 0; i < 8; i++) {
if (board[x][i] == 1) {
return false;
}
}
// Check vertical positions
for (int i = 0; i < 8; i++) {
if (board[i][y] == 1) {
return false;
}
}
// Check diagonal positions
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (board[i][j] == 1 && (Math.abs(i - x) == Math.abs(j - y))) {
return false;
}
}
}
return true;
}
public void solve() {
// Check if the solutionCount has reached 92
if (solutionCount == 92) {
return;
}
// Check if all 8 queens have been placed
int queensPlaced = 0;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (board[i][j] == 1) {
queensPlaced++;
}
}
}
if (queensPlaced == 8) {
// All positions have been checked, so we have found a solution
solutionCount++;
System.out.println("Solution " + solutionCount + ":");
print();
return;
}
// Try to place a queen at each position on the board
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (canPlace(i, j)) {
// Place a queen at position (i, j) and try to solve the rest of the board
board[i][j] = 1;
solve();
// Backtrack: remove the queen from position (i, j) and try the next position
board[i][j] = 0;
}
}
}
}
public void print() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (board[i][j] == 1) {
System.out.print(" X");
} else {
System.out.print(" O");
}
}
System.out.println();
}
System.out.println("---------------");
}
}
I'm doing this in blueJ, so I tried to run the void solve(); method and it runs, but it only prints out the first of 92 solutions 92 times. It should print out all 92 different solutions.
I have coded for Sudoku puzzle in Java. The thing is my code has limitation for giving inputs for 9*9 grid. How do I make my code adaptable for all the grids. Please have patience. I am new to java.
What changes do I need to make so that the code can run on all grid sizes?The grid is square not a rectangle.
class Solution {
public void solveSudoku(char[][] board) {
if(solveSudoku2(board)) {
return;
}
}
public boolean solveSudoku2(char[][] board) {
boolean isEmpty = true;
int row = -1;
int col = -1;
int n = board.length;
//this code is used to check if there exists any empty cell in sudoku board
//if there is any empty cell, that means we are not done yet and we need to solve it further,
// so we cannot return true at any point until all the cells are full
//by empty cell, I mean cells having '.' as the value
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[0].length; j++) {
if(board[i][j] == '.') {
row = i;
col = j;
isEmpty = false;
break;
}
}
if(!isEmpty) {
break;
}
}
if(isEmpty) {
return true;
}
//loop for all the numbers and start placing in the empty cells
//numbers start from 1 to n
for(int num = 1; num <= n; num++) {
//convert number to char
char char_num = (char)(num + '0');
//check if the number we are adding satisfies all the sudoku rules,
// if it does, then we place that number in the cell
if(checkSafe(board,char_num,row,col)) {
board[row][col] = (char)(num + '0');
//using this number in place row,col, we check for all the other empty places and see if the board is returning true or not
// if the board is not filled that means that we need to use other number in row,col place.
//hence backtrack.
if(solveSudoku2(board)) {
return true;
} else {
board[row][col] = '.';
}
}
}
return false;
}
public boolean checkSafe(char[][] board, char num, int row, int col) {
//checkk if num is present in the row
for(int i = 0; i< board.length; i++ ) {
if(board[row][i] == num) {
return false;
}
}
for(int j = 0; j < board[0].length; j++) {
if(board[j][col] == num) {
return false;
}
}
int checknum = (int)Math.sqrt(board.length);
//check for the current grid. grid will be basically checknum*checknum matrix. where every matrix will start from startrow to startrow + checknum having checknum length.
// so, we we have row = 0, then matrix will start from 0 to 2, i.e. the first 3x3 matrix.
// however, we have row = 2, then also the matrix will start from 0 to 2 - the first 3x3 matrix.
//however, if row = 3, then we will start our matrix from 3 and cotinute upto 5.
int startrow = row - row % checknum;
int startcol = col - col % checknum;
for(int k = startrow; k < startrow + checknum; k++) {
for(int l = startcol; l < startcol + checknum; l++) {
if(board[k][l] == num) {
return false;
}
}
}
return true;
}
}
My problem is when i change the first parameter into over 300 in line 133, i get a java.lang.StackOverflowError in line 37.This line is a recursion. How can i solve this?
public class PathFindingOnSquaredGrid {
// given an N-by-N matrix of open cells, return an N-by-N matrix
// of cells reachable from the top
public static boolean[][] flow(boolean[][] open) {
int N = open.length;
boolean[][] full = new boolean[N][N];
for (int j = 0; j < N; j++) {
flow(open, full, 0, j);
}
return full;
}
// determine set of open/blocked cells using depth first search
public static void flow(boolean[][] open, boolean[][] full, int i, int j) {
int N = open.length;
// base cases
if (i < 0 || i >= N) return; // invalid row
if (j < 0 || j >= N) return; // invalid column
if (!open[i][j]) return; // not an open cell
if (full[i][j]) return; // already marked as open
full[i][j] = true;
flow(open, full, i+1, j); // down line 37
flow(open, full, i, j+1); // right line 38
flow(open, full, i, j-1); // left line 39
flow(open, full, i-1, j); // up line 40
}
// does the system percolate?
public static boolean percolates(boolean[][] open) {
int N = open.length;
boolean[][] full = flow(open);
for (int j = 0; j < N; j++) {
if (full[N-1][j]) return true;
}
return false;
}
//does the system percolate vertically in a direct way?
public static boolean percolatesDirect(boolean[][] open) {
int N = open.length;
boolean[][] full = flow(open);
int directPerc = 0;
for (int j = 0; j < N; j++) {
if (full[N-1][j]) {
// StdOut.println("Hello");
directPerc = 1;
int rowabove = N-2;
for (int i = rowabove; i >= 0; i--) {
if (full[i][j]) {
//StdOut.println("i: " + i + " j: " + j + " " + full[i][j]);
directPerc++;
}
else break;
}
}
}
// StdOut.println("Direct Percolation is: " + directPerc);
if (directPerc == N) return true;
else return false;
}
// draw the N-by-N boolean matrix to standard draw
public static void show(boolean[][] a, boolean which) {
int N = a.length;
StdDraw.setXscale(-1, N);;
StdDraw.setYscale(-1, N);
StdDraw.setPenColor(StdDraw.BLACK);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (a[i][j] == which)
StdDraw.square(j, N-i-1, .5);
else StdDraw.filledSquare(j, N-i-1, .5);
}
// draw the N-by-N boolean matrix to standard draw, including the points A (x1, y1) and B (x2,y2) to be marked by a circle
public static void show(boolean[][] a, boolean which, int x1, int y1, int x2, int y2) {
int N = a.length;
StdDraw.setXscale(-1, N);;
StdDraw.setYscale(-1, N);
StdDraw.setPenColor(StdDraw.BLACK);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (a[i][j] == which)
if ((i == x1 && j == y1) ||(i == x2 && j == y2)) {
StdDraw.circle(j, N-i-1, .5);
}
else StdDraw.square(j, N-i-1, .5);
else StdDraw.filledSquare(j, N-i-1, .5);
}
// return a random N-by-N boolean matrix, where each entry is
// true with probability p
public static boolean[][] random(int N, double p) {
boolean[][] a = new boolean[N][N];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
a[i][j] = StdRandom.bernoulli(p);
return a;
}
// test client
public static void main(String[] args) {
ArrayList<Node> path=null;
Stopwatch timer;
// The following will generate a 10x10 squared grid with relatively few
obstacles in it
//The lower the second parameter, the more obstacles (black cells) are
generated
In here I was changing gird values to get test cases.
boolean[][] randomlyGenMatrix = random(350, 0.8); //line133
StdArrayIO.print(randomlyGenMatrix);
show(randomlyGenMatrix, true);
System.out.println();
//System.out.println("The system percolates: " + percolates(randomlyGenMatrix));
System.out.println();
//System.out.println("The system percolates directly: " + percolatesDirect(randomlyGenMatrix));
System.out.println();
Stopwatch timerFlow = new Stopwatch();
Scanner in = new Scanner(System.in);
System.out.println("Enter i for A > ");
int Ai = in.nextInt();
System.out.println("Enter j for A > ");
int Aj = in.nextInt();
System.out.println("Enter i for B > ");
int Bi = in.nextInt();
System.out.println("Enter j for B > ");
int Bj = in.nextInt();
// THIS IS AN EXAMPLE ONLY ON HOW TO USE THE JAVA INTERNAL WATCH
// Stop the clock ticking in order to capture the time being spent on inputting the coordinates
// You should position this command accordingly in order to perform the algorithmic analysis
StdOut.println("Elapsed time = " + timerFlow.elapsedTime());
//StdDraw.point(Ai, Bj);
// System.out.println("Coordinates for A: [" + Ai + "," + Aj + "]");
// System.out.println("Coordinates for B: [" + Bi + "," + Bj + "]");
show(randomlyGenMatrix, true, Ai, Aj, Bi, Bj);
String dis="";
while(!dis.equalsIgnoreCase("X")){
//Selecting the path
System.out.println("Enter Distance: (M)Manhattan|(E)Euclidean|(C)Chebyshev|(X)Exit");
dis=in.next();
timer=new Stopwatch();
path = new DijkstraAlgorithm(dis).distance(randomlyGenMatrix, Ai, Aj, Bi, Bj);
System.out.println("Elapsed time: "+timer.elapsedTime());
//Draw the path in the grid
for (Node node : path) {
StdDraw.filledCircle(node.y, 10 - node.x -1, .2);
}
}
System.exit(0);
}
}
The only thing you are using recursion for is to keep track of the locations that need to be checked. So you could instead have a queue of those locations, and keep processing the one popped off the head of the queue until the queue is empty. The body of the loop would look like the body of your flow method (except the initial tests would continue the loop instead of returning), but you would initialize the queue with the initial (i,j) location, and replace the recursive calls with enqueues of those locations.
I have run my code to get shorted distance from two point which we giving.my grid & everything working suddenly there got issue with jave PriorityQueue error n another error in my code i cant figure out what is it.help me to sort out this.
I have two classes called pathfinding & algo code separately.I'm passing 4 values to methord,start point n ending point ,grid size & blocked areas.
public class PathFindingOnSquaredGrid {
// given an N-by-N matrix of open cells, return an N-by-N matrix
// of cells reachable from the top
public static boolean[][] flow(boolean[][] open) {
int N = open.length;
boolean[][] full = new boolean[N][N];
for (int j = 0; j < N; j++) {
flow(open, full, 0, j);
}
return full;
}
// determine set of open/blocked cells using depth first search
public static void flow(boolean[][] open, boolean[][] full, int i, int j) {
int N = open.length;
// base cases
if (i < 0 || i >= N) return; // invalid row
if (j < 0 || j >= N) return; // invalid column
if (!open[i][j]) return; // not an open cell
if (full[i][j]) return; // already marked as open
full[i][j] = true;
flow(open, full, i+1, j); // down
flow(open, full, i, j+1); // right
flow(open, full, i, j-1); // left
flow(open, full, i-1, j); // up
}
// does the system percolate?
public static boolean percolates(boolean[][] open) {
int N = open.length;
boolean[][] full = flow(open);
for (int j = 0; j < N; j++) {
if (full[N-1][j]) return true;
}
return false;
}
// does the system percolate vertically in a direct way?
public static boolean percolatesDirect(boolean[][] open) {
int N = open.length;
boolean[][] full = flow(open);
int directPerc = 0;
for (int j = 0; j < N; j++) {
if (full[N-1][j]) {
// StdOut.println("Hello");
directPerc = 1;
int rowabove = N-2;
for (int i = rowabove; i >= 0; i--) {
if (full[i][j]) {
// StdOut.println("i: " + i + " j: " + j + " " + full[i][j]);
directPerc++;
}
else break;
}
}
}
// StdOut.println("Direct Percolation is: " + directPerc);
if (directPerc == N) return true;
else return false;
}
// draw the N-by-N boolean matrix to standard draw
public static void show(boolean[][] a, boolean which) {
int N = a.length;
StdDraw.setXscale(-1, N);;
StdDraw.setYscale(-1, N);
StdDraw.setPenColor(StdDraw.BLACK);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (a[i][j] == which)
StdDraw.square(j, N-i-1, .5);
else StdDraw.filledSquare(j, N-i-1, .5);
}
// draw the N-by-N boolean matrix to standard draw, including the points A (x1, y1) and B (x2,y2) to be marked by a circle
public static void show(boolean[][] a, boolean which, int x1, int y1, int x2, int y2) {
int N = a.length;
StdDraw.setXscale(-1, N);;
StdDraw.setYscale(-1, N);
StdDraw.setPenColor(StdDraw.BLACK);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
if (a[i][j] == which)
if ((i == x1 && j == y1) ||(i == x2 && j == y2)) {
StdDraw.circle(j, N-i-1, .5);
}
else StdDraw.square(j, N-i-1, .5);
else StdDraw.filledSquare(j, N-i-1, .5);
}
// return a random N-by-N boolean matrix, where each entry is
// true with probability p
public static boolean[][] random(int N, double p) {
boolean[][] a = new boolean[N][N];
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
a[i][j] = StdRandom.bernoulli(p);
return a;
}
// test client
public static void main(String[] args) {
// boolean[][] open = StdArrayIO.readBoolean2D();
// The following will generate a 10x10 squared grid with relatively few obstacles in it
// The lower the second parameter, the more obstacles (black cells) are generated
boolean[][] randomlyGenMatrix = random(10, 0.8);
StdArrayIO.print(randomlyGenMatrix);
show(randomlyGenMatrix, true);
System.out.println();
System.out.println("The system percolates: " + percolates(randomlyGenMatrix));
System.out.println();
System.out.println("The system percolates directly: " + percolatesDirect(randomlyGenMatrix));
System.out.println();
// Reading the coordinates for points A and B on the input squared grid.
// THIS IS AN EXAMPLE ONLY ON HOW TO USE THE JAVA INTERNAL WATCH
// Start the clock ticking in order to capture the time being spent on inputting the coordinates
// You should position this command accordingly in order to perform the algorithmic analysis
Stopwatch timerFlow = new Stopwatch();
Scanner in = new Scanner(System.in);
System.out.println("Enter i for A > ");
int Ai = in.nextInt();
System.out.println("Enter j for A > ");
int Aj = in.nextInt();
System.out.println("Enter i for B > ");
int Bi = in.nextInt();
System.out.println("Enter j for B > ");
int Bj = in.nextInt();
// THIS IS AN EXAMPLE ONLY ON HOW TO USE THE JAVA INTERNAL WATCH
// Stop the clock ticking in order to capture the time being spent on inputting the coordinates
// You should position this command accordingly in order to perform the algorithmic analysis
StdOut.println("Elapsed time = " + timerFlow.elapsedTime());
// System.out.println("Coordinates for A: [" + Ai + "," + Aj + "]");
// System.out.println("Coordinates for B: [" + Bi + "," + Bj + "]");
ArrayList<int[]> blockList=new ArrayList<>();
for (int i = 0; i < randomlyGenMatrix.length; i++) {
for (int j = 0; j < randomlyGenMatrix[i].length; j++) {
if(randomlyGenMatrix[i][j]){
blockList.add(new int[]{i,j});
}
}
}
int[][] blockArray=new int[blockList.size()][2];
for (int i = 0; i < blockList.size(); i++) {
blockArray[i] = blockList.get(i);
System.out.println("############"+blockList.get(i));
// blockArray[j] = blockList.get(j);
}
//show(randomlyGenMatrix, true, Ai, Aj, Bi, Bj,);
show(randomlyGenMatrix, true, Ai, Aj, Bi, Bj);
AStarCopied.test(10,10, Ai, Aj, Bi, Bj, blockArray);
}
}
Here is my code. I am trying to check for the winner. I am only a beginner, so please make it easy. I wanted the board to change sizes. So, I want the check for winner can get use to the size, it will not just check the 9 blocks.
import java.util.*;
public class TicTacToe {
private String[][] board;
private Scanner console;
public TicTacToe(String[][] table, Scanner console) {
this.board = table;
this.console = console;
}
public void makeTable() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
board[i][j] = "_";
}
}
}
public void printTable() {
System.out.print(" ");
for (int i = 0; i < board.length; i++) {
System.out.print(" " + i);
}
System.out.println();
for (int i = 0; i < board.length; i++) {
System.out.print(i + "│");
for (int j = 0; j < board[i].length; j++) {
System.out.print(board[i][j] + "│");
}
System.out.println();
}
}
public void play(Scanner console) {
int turn = 0;
String player = "_";
makeTable();
printTable();
while (turn != 9) {
int x = console.nextInt();
int y = console.nextInt();
while (x >= board.length || y >= board[1].length) {
System.out.println("Out of bounce, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
while (board[y][x] != "_") {
System.out.println("Occupied, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
if (turn % 2 == 0) {
player = "X";
} else {
player = "O";
}
board[y][x] = player;
turn++;
printTable();
}
}
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
String[][] board = new String[3][3];
TicTacToe ttt = new TicTacToe(board, console);
ttt.play(console);
}
}
A winning move can only happen when a piece is placed on the board, so you only need to check winning combinations that involve the piece that was just placed on the board.
For example, if the current state of the board is:
O X O
X X
O
And O places their piece in the middle of the board:
O X O
X O X
O
Then you only need to check the winning combinations that involve this middle piece, namely both diagonals, and the middle column and middle row (4 combinations) out of the total number of winning combinations (8 combinations).
Thus, tracking the last move made is essential to effectively determining if the board is in a winning state.
EDIT
As one person already mentioned, what you're essentially doing is checking to see if the last played move is a winning move. As a result, there really isn't any need to brute force check every row, column, and diagonal systematically to see if there's a winning position or to create some sort of list or table of solutions to check the current board against.
All you really need to do is check the row, column, and diagonal (if the move was on a diagonal) that the move was played on and see if the winning condition is met there.
// Takes the row and column coordinates of the last move made
// and checks to see if that move causes the player to win
public boolean isWinner(int row, int col){
String Player = board[row][col];
int r = row;
int c = col;
boolean onDiagonal = (row == col) || (col == -1 * row + (board.length-1));
boolean HorizontalWin = true, VerticalWin = true;
boolean DiagonalWinOne = true; DiagonalWinTwo = true;
// Check the rows and columns
for(int n = 0; n < board.length; n++){
if(!board[r][n].equals(Player))
HorizontalWin = false;
if(!board[n][c].equals(Player))
VerticalWin = false;
}
// Only check diagonals if the move is on a diagonal
if(onDiagonal){
// Check the diagonals
for(int n = 0; n < board.length; n++){
if(!board[n][n].equals(Player))
DiagonalWinOne = false;
if(!board[n][-1*n+(board.length-1)].equals(Player))
DiagonalWinTwo = false;
}
}
else{
DiagonalWinOne = false;
DiagonalWinTwo = false;
}
boolean hasWon = (HorizontalWin || VerticalWin || DiagonalWinOne || DiagonalWinTwo);
return hasWon;
}
ORIGINAL
A few people have already answered this question, but here's my answer just for the heck of it.
Also, in your play method, you have a while loop to check to make sure that the user doesn't specify a move that is out-of-bounds, but then afterwards you have another while loop check to make sure that the move is in an empty space. You'll still probably want to check to make sure that their new move is also within the boundaries otherwise your loop condition will throw an ArrayOutOfBoundsException.
public boolean isWinner(String player){
// Check for N-in-a-row on the rows and columns
for(int i = 0; i < board.length; i++){
boolean verticalWin = true, horizontalWin = true;
for(int j = 0; j < board.length; j++){
if(!board[i][j].equals(player)))
horizontalWin = false;
if(!board[j][i].equals(player))
verticalWin = false;
if(!(horizontalWin || verticalWin))
break;
}
if(horizontalWin || verticalWin)
return true;
}
// If there was a N-in-a-row on the rows or columns
// the method would have returned by now, so we're
// going to check the diagonals
// Check for N-in-a-row on both the diagonals
boolean diagonalWinOne = true, diagonalWinTwo = true;
for(int n = 0; n < board.length; n++){
diagonalWinOne = true;
diagonalWinTwo = true;
int row = board.length - 1 - n;
if(!board[n][n].equals(player))
diagonalWinOne = false;
if(!board[row][n].equals(player))
diagonalWinTwo = false;
if(!(diagonalOne || diagonalTwo))
break;
}
// If either one of the diagonals has N-in-a-row, then there's a winner
if(diagonalWinOne || diagonalWinTwo)
return true;
// Otherwise, no one has won yet
else
return false;
}
Ok here is how I did it when I made tic-tac-toe. I used Strings
Create a 2D array that contains all the possible winning combinations
Create two String variables, one for each player.
Display the board on the table
Number each of the blocks from 1 to 9 starting at the top left corner
Whenever the either of the user clicks on the board, append the number to the player String
Now, here comes the magic part, checking the winner:
6. For every click on the board, start iterating on the 2d winning combination. Here is how you check if somebody has won:
String[][] winningCombo = ... initialization ...
for( int i = 0 ; i < winningCombo.length; i++){
for(j = 0; j < winningCombo[i].length; j ++){
char c1 = winningCombo[i][j].charAt(0);
char c2 = winningCombo[i][j].charAt(1);
char c3 = winningCombo[i][j].charAt(2);
if(currentPlayerString.contains(c1) && currentPlayerString.contains(c2) && currentPlayerString.contains(c3)){
// currentPlayer has won if he has all the 3 positions of a winning combo
}
}
}
So, if you may consider an alternative approach, you can use that. I used Swing for UI and used GridLayout to layout the various JPanel.
just check rows, cols and both diagonals:
import java.util.Scanner;
public class TTT {
private String[][] board;
private Scanner console;
private int size;
public TTT(String[][] table, Scanner console, int size) {
this.board = table;
this.console = console;
this.size = size;
}
public void makeTable() {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
board[i][j] = "_";
}
}
}
public void printTable() {
System.out.print(" ");
for (int i = 0; i < board.length; i++) {
System.out.print(" " + i);
}
System.out.println();
for (int i = 0; i < board.length; i++) {
System.out.print(i + "│");
for (int j = 0; j < board[i].length; j++) {
System.out.print(board[i][j] + "│");
}
System.out.println();
}
}
public void play(Scanner console) {
int turn = 0;
String player = "_";
makeTable();
printTable();
while (turn != 9) {
int x = console.nextInt();
int y = console.nextInt();
while (x >= board.length || y >= board[1].length) {
System.out.println("Out of bounce, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
while (board[y][x] != "_") {
System.out.println("Occupied, try again!!!");
x = console.nextInt();
y = console.nextInt();
}
if (turn % 2 == 0) {
player = "X";
} else {
player = "O";
}
board[y][x] = player;
turn++;
printTable();
if(check()){
System.out.println("Player "+player+" won!");
break;
}
}
}
public boolean check(){
//check diagonals
if(check00ToNN()){
return true;
}
if(check0NToN0()){
return true;
}
for(int i = 0 ; i< size ; i++){
if(checkCol(i)){
return true;
}
if(checkRow(i)){
return true;
}
}
return false;
}
public boolean checkRow(int index){
for(int i = 1 ; i< size ; i++){
if(board[i-1][index]!=board[i][index]||board[i][index]=="_"){
return false;
}
}
return true;
}
public boolean checkCol(int index){
for(int i = 1 ; i< size ; i++){
if(board[index][i-1]!=board[index][i]||board[index][i]=="_"){
return false;
}
}
return true;
}
public boolean check00ToNN(){
for(int i = 1 ; i< size ; i++){
if(board[i-1][i-1]!=board[i][i]||board[i][i]=="_"){
return false;
}
}
return true;
}
public boolean check0NToN0(){ //diagonal
for(int i = 1 ; i< size ; i++){
if(board[i-1][size-i-1]!=board[i][size-i]||board[i][size-i]=="_"){
return false;
}
}
return true;
}
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
int size = 3;
String[][] board = new String[size][size];
TTT ttt = new TTT(board, console,size);
ttt.play(console);
}
}
i just look if there is a winner, since i know who had the last turn, i know who it is.
check() calls the real checkmethods.
i added size since it is scalable.