conway game of life neighbor issue(java) - java

I'm currrently having issues with the neighbors in my project where i have to modify two diffrent methods for a conway game of life. My TA says my code looks like it should work but the neightbor count isn't working. I'v been printing the neightbor code and it works for the first time than it just goes to 0 for the rest of the run. Anyone have an idea where I am messing up?
public static void updateLife(Boolean[][] gameCellAlive) {
int size = gameCellAlive.length;
System.out.println("size of temp--->"+size);
Boolean[][] tempCell = new Boolean [size][size];
int row = 0;
int col = 0;
for (row = 0; row<tempCell.length; row++) {
for(col=0; col<tempCell[0].length; col++) {
tempCell[row][col] = gameCellAlive[row][col];
}
}
for (int i = 0; i<tempCell.length; i++) {
for (int j = 0; j<tempCell[0].length; j++) {
int tempInt = getLifeNeighborCount(gameCellAlive, j, i);
System.out.println("neighbors---->"+tempInt);
if ((tempInt>3) || (tempInt<2)) {
tempCell[i][j] = false;
}
else if(tempInt == 3) {
tempCell[i][j] = true;
}
else if(tempInt==2) {
tempCell[i][j]=true;
}
/*else {
tempCell[row][col]=gameCellAlive[row][col];
}*/
}//2nd for loop
}//for loop
for (int x = 0; x<tempCell.length; x++) {
for(int y=0; y<tempCell[0].length; y++) {
gameCellAlive[x][y] = tempCell[x][y];
}
}
// METHOD STUB - This method needs to be implemented!
//if statemeent for requirements.
} // end method updateLife
/**
*
* #param gameBoard A 2D boolean array containing the current life status of
* each cell at each x,y coordinate on the board. true indicates that the
* cell is alive. false indicates no life in that cell.
* #param colIndex The x position of the cell in the game board whose
* neighbors are to be counted.
* #param rowIndex The y position of the cell in the game board whose
* neighbors are to be counted.
* #return the number of cells adjacent to the cell at the specified row and
* column that contain life. This value ranges between 0 (no adjacent cells
* contain life) and 8 (all adjacent cells contain life).
*
* CS1180 Note: YOU NEED TO IMPLEMENT THIS METHOD
*/
public static int getLifeNeighborCount(Boolean[][] gameBoard, int colIndex, int rowIndex) {
// METHOD STUB - THIS METHOD NEEDS TO BE IMPLEMENTED
int neighborCount = 0;
//check for alive or dead
for (int i = rowIndex-1; i<=rowIndex+1; i++) {
for (int j = colIndex-1; j<=rowIndex+1; j++) {
try {
if (gameBoard[i][j]==true && (i !=rowIndex || j!=colIndex)) {
//System.out.println("hello");
neighborCount++;
}//end if
}//end try
catch (ArrayIndexOutOfBoundsException e){
}//end catch
}//end second foor loop
}//end first foor loop
return neighborCount;
}// end method getLifeNeighborCount

You are using the wrong variable in the condition in this loop:
for (int j = colIndex-1; j<=rowIndex+1; j++) {
It should be:
for (int j = colIndex-1; j<=colIndex+1; j++) {

Related

Passed a 2D Array to another class but can't get the object returned

I'm currently developing an algorithm for my Tictactoe Android App (using Java) with Minimax, but first, I just want to make sure the algorithm works, so I made the algorithm to "suggests" the next move to the player.
The player is declared as String player = "x"; in the Minimax class.
Minimax.java
package com.firaz.tictactoe;
public class Minimax {
public static class Move {
int row, col;
}
static String player = "x";
static String opponent = "o";
String[][] board = new String[3][3];
// This function returns true if there are moves
// remaining on the board. It returns false if
// there are no moves left to play.
static Boolean isMovesLeft(String[][] board) {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (board[i][j].equals("_"))
return true;
return false;
}
// This is the evaluation function
static int evaluate(String[][] b) {
// Checking for Rows for X or O victory.
for (int row = 0; row < 3; row++) {
if (b[row][0].equals(b[row][1]) &&
b[row][1].equals(b[row][2])) {
if (b[row][0].equals(player))
return +10;
else if (b[row][0].equals(opponent))
return -10;
}
}
// Checking for Columns for X or O victory.
for (int col = 0; col < 3; col++) {
if (b[0][col].equals(b[1][col])
&& b[1][col].equals(b[2][col])) {
if (b[0][col].equals(player))
return +10;
else if (b[0][col].equals(opponent))
return -10;
}
}
// Checking for Diagonals for X or O victory.
if (b[0][0].equals(b[1][1])
&& b[1][1].equals(b[2][2])) {
if (b[0][0].equals(player))
return +10;
else if (b[0][0].equals(opponent))
return -10;
}
if (b[0][2].equals(b[1][1])
&& b[1][1].equals(b[2][0])) {
if (b[0][2].equals(player))
return +10;
else if (b[0][2].equals(opponent))
return -10;
}
// Else if none of them have won then return 0
return 0;
}
// This is the minimax function. It considers all
// the possible ways the game can go and returns
// the value of the board
static int minimax(String[][] board,
int depth, Boolean isMax) {
int score = evaluate(board);
// If Maximizer has won the game
// return his/her evaluated score
if (score == 10)
return score;
// If Minimizer has won the game
// return his/her evaluated score
if (score == -10)
return score;
// If there are no more moves and
// no winner then it is a tie
if (isMovesLeft(board) == false)
return 0;
// If this maximizer's move
if (isMax) {
int best = -1000;
// Traverse all cells
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// Check if cell is empty
if (board[i][j].equals("_")) {
// Make the move
board[i][j] = player;
// Call minimax recursively and choose
// the maximum value
best = Math.max(best, minimax(board,
depth + 1, !isMax));
// Undo the move
board[i][j] = "_";
}
}
}
return best;
}
// If this minimizer's move
else {
int best = 1000;
// Traverse all cells
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// Check if cell is empty
if (board[i][j].equals("_")) {
// Make the move
board[i][j] = opponent;
// Call minimax recursively and choose
// the minimum value
best = Math.min(best, minimax(board,
depth + 1, !isMax));
// Undo the move
board[i][j] = "_";
}
}
}
return best;
}
}
// This will return the best possible
// move for the player
static Move findBestMove(String[][] board) {
int bestVal = -1000;
Move bestMove = new Move();
bestMove.row = -1;
bestMove.col = -1;
// Traverse all cells, evaluate minimax function
// for all empty cells. And return the cell
// with optimal value.
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// Check if cell is empty
if (board[i][j].equals("_")) {
// Make the move
board[i][j] = player;
// compute evaluation function for this
// move.
int moveVal = minimax(board, 0, false);
// Undo the move
board[i][j] = "_";
// If the value of the current move is
// more than the best value, then update
// best/
if (moveVal > bestVal) {
bestMove.row = i;
bestMove.col = j;
bestVal = moveVal;
}
}
}
}
return bestMove;
}
public void setBoard(String[][] Board){
this.board = Board;
Move bestMove = findBestMove(board);
PlayerVersusComputer playerVersusComputer = new PlayerVersusComputer();
playerVersusComputer.setRow(bestMove.row);
playerVersusComputer.setCol(bestMove.col);
}
}
I'm expecting a return integer (row and col) from the Minimax.java to the PlayerVersusComputer.java in this code snippet.
PlayerVersusComputer.java
String buttonID = getResources().getResourceEntryName(v.getId()); //button_ij
int pointerOne = Integer.parseInt(buttonID.substring(7, buttonID.length()-1)); //obtain i
int pointerTwo = Integer.parseInt(buttonID.substring(buttonID.length()-1)); //obtain j
if (player1Turn) {
((Button) v).setText("x");
board[pointerOne][pointerTwo] = "x";
} else {
((Button) v).setText("o");
board[pointerOne][pointerTwo] = "o";
checkBestMove();
}
protected void checkBestMove() {
minimax.setBoard(board);
row = getCol();
col = getRow();
tvAI.setText(row+"R"+" "+col+"C");
}
This is the board Array. The board will "update" itself every time I pressed the ((Button) v).setText("x"); or ("o"), then passed to Minimax.java when it's O's turn.
String[][] board = {{"_","_","_"},
{"_","_","_"},
{"_","_","_"}};
Since the row and col is not returned to the checkBestMove() function (I'm not sure if it's not returned or just can't "update" itself), the tvAI.setText keeps saying "0R0C" instead of updating itself (to 2R2C, then 0R1C, etc).
Update to the row and col are expected because the tvAI.setText is intended to suggest the player's next move. So why it's not updating?
In function setBoard is the call of findBestMove(board); but the return value of type Move is ignored. Maybe you can assign it to a variable.
this.bestMove = findBestMove(board);

Showing solutions graphically for N queens problem in java

I have the working code that you can see bellow, I just need someone to help me how to enable user to insert number of queens in a new window and then the program should show all solutions in a new window that will graphically show the chessboard and the queens.
Java program to solve N Queen
Problem using backtracking
public class GfG
{
static int N = 2;
static int k = 1;
/* A utility function to print solution */
static void printSolution(int board[][])
{
System.out.printf("%d-\n", k++);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
System.out.printf(" %d ", board[i][j]);
System.out.printf("\n");
}
System.out.printf("\n");
}
A utility function to check if a queen can
be placed on board[row][col]. Note that this
function is called when "col" queens are
already placed in columns from 0 to col -1.
So we need to check only left side for
attacking queens
static boolean isSafe(int board[][], int row, int col)
{
int i, j;
/* Check this row on left side */
for (i = 0; i < col; i++)
if (board[row][i] == 1)
return false;
/* Check upper diagonal on left side */
for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
if (board[i][j] == 1)
return false;
/* Check lower diagonal on left side */
for (i = row, j = col; j >= 0 && i < N; i++, j--)
if (board[i][j] == 1)
return false;
return true;
}
A recursive utility function
to solve N Queen problem
static boolean solveNQUtil(int board[][], int col)
{
/* base case: If all queens are placed
then return true */
if (col == N)
{
printSolution(board);
return true;
}
/* Consider this column and try placing
this queen in all rows one by one */
boolean res = false;
for (int i = 0; i < N; i++)
{
/* Check if queen can be placed on
board[i][col] */
if ( isSafe(board, i, col) )
{
/* Place this queen in board[i][col] */
board[i][col] = 1;
// Make result true if any placement
// is possible
res = solveNQUtil(board, col + 1) || res;
/* If placing queen in board[i][col]
doesn't lead to a solution, then
remove queen from board[i][col] */
board[i][col] = 0; // BACKTRACK
}
}
/* If queen can not be place in any row in
this column col then return false */
return res;
}
This function solves the N Queen problem using
Backtracking. It mainly uses solveNQUtil() to
solve the problem. It returns false if queens
cannot be placed, otherwise return true and
prints placement of queens in the form of 1s.
Please note that there may be more than one
solutions, this function prints one of the
feasible solutions.
static void solveNQ()
{
int board[][] = new int[N][N];
if (solveNQUtil(board, 0) == false)
{
System.out.printf("Solution does not exist");
return ;
}
return ;
}
// Driver code
public static void main(String[] args)
{
solveNQ();
}
}

Tic Tac Toe winning condition change when scalable board is larger than 4x4

So, I have been making this Tic Tac Toe program for a while now.
It's a basic Tic Tac Toe game but the game board is scalable. The program is almost finished but one little feature is missing.
I have to make the game end if player gets five or more marks in a row when the game board is larger than 4x4.
F.E. If the game board is 9x9 the game has to end when the player or the computer gets five marks in a row.
(Mark = "O" or "X").
The game now ends when someone gets marks in a row equals to the size of the board (if 9x9 you need 9 marks in a row to win).
I have to implement a feature in the playerHasWon and I've been having a lot of trouble finding out how. I think it's a simple to implement thing but I have not found out how to do it.
Hope my explanation is easy enough to understand. Here's the code:
package tictac;
import java.util.Scanner;
import java.util.Random;
public class Tictac {
public static final int DRAW = 0; // game ends as a draw
public static final int COMPUTER = 1; // computer wins
public static final int PLAYER = 2; // player wins
public static final char PLAYER_MARK = 'X'; // The "X"
public static final char COMPUTER_MARK = 'O'; // The "O"
public static int size; // size of the board
public static String[][] board; // the board itself
public static int score = 0; // game win score
public static Scanner scan = new Scanner(System.in); // scanner
/**
* Builds the board with the integer size and user input.
*
* Displays game win message and switches play turns.
*
* #param args the command line parameters. Not used.
*/
public static void main(String[] args) {
while (true) {
System.out.println("Select board size");
System.out.print("[int]: ");
try {
size = Integer.parseInt(scan.nextLine());
} catch (Exception e) {
System.out.println("You can't do that.");
continue; // after message, give player new try
}
break;
}
int[] move = {};
board = new String[size][size];
setupBoard();
int i = 1;
loop: // creates the loop
while (true) {
if (i % 2 == 1) {
displayBoard();
move = getMove();
} else {
computerTurn();
}
switch (isGameFinished(move)) {
case PLAYER:
System.err.println("YOU WIN!");
displayBoard();
break loop;
case COMPUTER:
System.err.println("COMPUTER WINS!");
displayBoard();
break loop;
case DRAW:
System.err.println("IT'S A DRAW");
displayBoard();
break loop;
}
i++;
}
}
/**
* Checks for game finish.
*
* #param args command line parameters. Not used.
*
* #return DRAW the game ends as draw.
* #return COMPUTER the game ends as computer win.
* #return PLAYERE the game ends as player win.
*/
private static int isGameFinished(int[] move) {
if (isDraw()) {
return DRAW;
} else if (playerHasWon(board, move,
Character.toString(COMPUTER_MARK))) {
return COMPUTER;
} else if (playerHasWon(board, move,
Character.toString(PLAYER_MARK))) {
return PLAYER;
}
return -1; // can't be 0 || 1 || 2
}
/**
* Checks for win for every direction on the board.
*
* #param board the game board.
* #param move move on the board.
* #param playerMark mark on the board "X" or "O".
* #return the game is won.
*/
public static boolean playerHasWon(String[][] board, int[] move,
String playerMark) { //playermark x || o
// horizontal check
for (int i = 0; i < size; i++) {
if (board[i][0].equals(playerMark)) {
int j;
for (j = 1; j < size; j++) {
if (!board[i][j].equals(playerMark)) {
break;
}
}
if (j == size) {
return true;
}
}
}
// vertical check
for (int i = 0; i < size; i++) {
if (board[0][i].equals(playerMark)) {
int j;
for (j = 1; j < size; j++) {
if (!board[j][i].equals(playerMark)) {
break;
}
}
if (j == size) {
return true;
}
}
}
// diagonals check
int i;
for (i = 0; i < size; i++) {
if (!board[i][i].equals(playerMark)) {
break;
}
}
if (i == size) {
return true;
}
for (i = 0; i < size; i++) {
if (!board[i][(size - 1) - i].equals(playerMark)) {
break;
}
}
return i == size;
}
/**
* Checks for draws.
*
* #return if this game is a draw.
*/
public static boolean isDraw() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (board[i][j] == " ") {
return false;
}
}
}
return true;
}
/**
* Displays the board.
*
*
*/
public static void displayBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
System.out.printf("[%s]", board[i][j]);
}
System.out.println();
}
}
/**
* Displays the board.
*
*
*/
public static void setupBoard() {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
board[i][j] = " ";
}
}
}
/**
* Takes in user input and sends it to isValidPlay.
*
* #return null.
*/
public static int[] getMove() {
Scanner sc = new Scanner(System.in);
System.out.println("Your turn:");
while (true) {
try {
System.out.printf("ROW: [0-%d]: ", size - 1);
int x = Integer.parseInt(sc.nextLine());
System.out.printf("COL: [0-%d]: ", size - 1);
int y = Integer.parseInt(sc.nextLine());
if (isValidPlay(x, y)) {
board[x][y] = "" + PLAYER_MARK;
return new int[]{x, y};
} else { // if input is unallowed
System.out.println("You can't do that");
continue; // after message, give player new try
}
} catch (Exception e) {
System.out.println("You can't do that.");
}
return null;
}
}
/*
* Randomizes computer's turn, where it inputs the mark 'O'.
*
*
*/
public static void computerTurn() {
Random rgen = new Random(); // Random number generator
while (true) {
int x = (int) (Math.random() * size);
int y = (int) (Math.random() * size);
if (isValidPlay(x, y)) {
board[x][y] = "" + COMPUTER_MARK;
break;
}
}
}
/**
* Checks if a move is possible.
*
* #param inX x-move is out of bounds.
* #param inY y-move is out of bounds.
* #return false
*/
public static boolean isValidPlay(int inX, int inY) {
// Play is out of bounds and thus not valid.
if ((inX >= size) || (inY >= size)) {
return false;
}
// Checks if a play have already been made at the location,
// and the location is thus invalid.
return (board[inX][inY] == " ");
}
}
// End of file
Took a quick look, detected the problem and came up with a quick fix:
public static boolean checkDiagonal(String markToLook) {
// how many marks are we looking for in row?
int sizeToWin = Math.min(size, 5);
// running down and right
// don't need to iterate rows that can't be the starting point
// of a winning diagonal formation, thus can exlude some with
// row < (size - (sizeToWin - 1))
for (int row = 0; row < (size - (sizeToWin - 1)); row++) {
for (int col = 0; col < size; col++) {
int countOfMarks = 0;
// down and right
for (int i = row; i < size; i++) {
if (board[i][i] == null ? markToLook == null :
board[i][i].equals(markToLook)) {
countOfMarks++;
if (countOfMarks >= sizeToWin) {
return true;
}
}
}
countOfMarks = 0;
// down and left
for (int i = row; i < size; i++) {
if (board[i][size - 1 - i] == null ? markToLook == null :
board[i][size - 1 - i].equals(markToLook)) {
countOfMarks++;
if (countOfMarks >= sizeToWin) {
return true;
}
}
}
}
}
return false;
}
And call it from your PlayerHasWon method instead of performign the checks there. Basically we iterate each possible starting square on the board for a diagonal winning formation, and run check down+left and down+right for each of the squares.
I am in awful hurry and did not test it much, but will return in couple of hours to improve this solution. Seems to work.
Edit: My previous solution I found lacking in further tests, I've updated the above code to function as desired.
First, I think playerMark should be a char and not a String. That said, let's go for the answer. The "horizontal" case would be:
// This is the number of marks in a row required to win
// Adjust formula if necessary
final int required = size > 4 ? 5 : 3;
for (int i = 0; i < size; i++) {
int currentScore = 0;
for (j = 0; j < size; j++) {
if (board[i][j].equals(playerMark)) {
currentScore++;
if (currentScore >= required)
return true;
}
else {
currentScore = 0;
}
}
}
}
The vertical case would be analogous. The diagonal one is a bit trickier as now it would require board[i][i+k] for the main diagonal and board[i][k-i] for the secondary; and it may not be obvious which values k and i must traverse. Here's my attempt (variable required as in horizontal case):
Note: everything from here down has been completely rewritten on 2015-12-16. The previous versions didn't work and the algorithm was not explained.
After two failed attempts I decided to do my homework and actually sort things out instead of doing everything in my head thinking I can keep track of all variables. The result is this picture:
Main diagonals are painted in blue, secondary diagonals in green.
Each diagonal is identified by a value of k, with k=0 being always being the longest diagonal of each set. Values of k grow as diagonals move down, so diagonals above the longest one have negative k while diagonals below the longest one have positive k.
Things that hold for both diagonals:
Diagonal contains size-abs(k) elements. Diagonals in which size-abs(k) is less than required need not be searched. This means that, for board size size and required length required, we'll search values of k from required-size to size-required. Notice that these have the same absolute value, with the first being <=0 and the second >=0. These values are both zero only when required==size, i.e. when we need the full diagonal to claim a win, i.e. when we only need to search k=0.
For k<=0, possible values of i (row) go from 0 to size+k. Values greater than or equal to size+k cross the right edge of the board and are thus outside the board.
For k>=0, possible values of i (row) go from k to size. Values below k cross the left edge of the board and are thus outside the board.
Only for main (blue) diagonals:
Value of j (column) is k+i.
Only for secondary (green) diagonals:
Value of j (column) is size-1+k-i. In case this is not obvious, just pick the top right corner (k=0,i=0) and notice j=size-1. Then notice that adding 1 to k (keeping i constant) always moves j by 1 right (it would go out of the board if done from k=0,i=0, just think about the intersection of horizontal line i=0 with diagonal k=1), and adding 1 to i (keeping k constant) always moves j by 1 to the left.
The ressulting code would be:
// Main diagonal
for (int k = required - size; k < size - required; k++)
{
int currentScore = 0;
startI = Math.max (0, k);
endI = Math.min (size, size+k);
for (int i = startI, i < endI; i++)
{
if (board[i][k+i].equals (playerMark))
{
currentScore++;
if (currentScore >= required)
return true;
}
else
currentScore = 0;
}
}
// Secondary diagonal
for (int k = required - size; k < size - required; k++)
{
int currentScore = 0;
startI = Math.max (0, k);
endI = Math.min (size, size+k);
for (int i = startI, i < endI; i++)
{
if (board[i][size-1+k-i].equals (playerMark))
{
currentScore++;
if (currentScore >= required)
return true;
}
else
currentScore = 0;
}
}
At this point, the code is nearly identical in both cases, changing only the j index in board[i][j]. In fact, both loops could be merged, taking care only of keeping two currentScore variables, one for the main (blue) diagonal and the other for the secondary (green) diagonal.

Strange Stack Overflow Error in Sudoko Backtracker

(Disclaimer: There are maybe 20 different versions of this question on SO, but a reading through most of them still hasn't solved my issue)
Hello all, (relatively) beginner programmer here. So I've been trying to build a Sudoku backtracker that will fill in an incomplete puzzle. It seems to works perfectly well even when 1-3 rows are completely empty (i.e. filled in with 0's), but when more boxes start emptying (specifically around the 7-8 column in the fourth row, where I stopped writing in numbers) I get a Stack Overflow Error. Here's the code:
import java.util.ArrayList;
import java.util.HashSet;
public class Sudoku
{
public static int[][] puzzle = new int[9][9];
public static int filledIn = 0;
public static ArrayList<Integer> blankBoxes = new ArrayList<Integer>();
public static int currentIndex = 0;
public static int runs = 0;
/**
* Main method.
*/
public static void main(String args[])
{
//Manual input of the numbers
int[] completedNumbers = {0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,3,4,
8,9,1,2,3,4,5,6,7,
3,4,5,6,7,8,9,1,2,
6,7,8,9,1,2,3,4,5,
9,1,2,3,4,5,6,7,8};
//Adds the numbers manually to the puzzle array
ArrayList<Integer> completeArray = new ArrayList<>();
for(Integer number : completedNumbers) {
completeArray.add(number);
}
int counter = 0;
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
puzzle[i][j] = completeArray.get(counter);
counter++;
}
}
//Adds all the blank boxes to an ArrayList.
//The index is stored as 10*i + j, which can be retrieved
// via modulo and integer division.
boolean containsEmpty = false;
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(puzzle[i][j] == 0) {
blankBoxes.add(10*i + j);
containsEmpty = true;
}
}
}
filler(blankBoxes.get(currentIndex));
}
/**
* A general method for testing whether an array contains a
* duplicate, via a (relatively inefficient) sort.
* #param testArray The int[] that is being tested for duplicates
* #return True if there are NO duplicate, false if there
* are ANY duplicates.
*/
public static boolean checkDupl(int[] testArray) {
for(int i = 0; i < 8; i++) {
int num = testArray[i];
for(int j = i + 1; j < 9; j++) {
if(num == testArray[j] && num != 0) {
return false;
}
}
}
return true;
}
/**
* If the puzzle is not full, the filler will be run. The filler is my attempt at a backtracker.
* It stores every (i,j) for which puzzle[i][j] == 0. It then adds 1 to it's value. If the value
* is already somewhere else, it adds another 1. If it is 9, and that's already there, it loops to
* 0, and the index beforehand is rechecked.
*/
public static void filler(int indexOfBlank) {
//If the current index is equal to the size of blankBoxes, meaning that we
//went through every index of blankBoxes, meaning the puzzle is full and correct.
runs++;
if(currentIndex == blankBoxes.size()) {
System.out.println("The puzzle is full!" + "\n");
for(int i = 0; i < 9; i++) {
System.out.println();
for(int j = 0; j < 9; j++) {
System.out.print(puzzle[i][j]);
}
}
System.out.println("\n" + "The filler method was run " + runs + " times");
return;
}
//Assuming the puzzle isn't full, find the row/column of the blankBoxes index.
int row = blankBoxes.get(currentIndex) / 10;
int column = blankBoxes.get(currentIndex) % 10;
//Adds one to the value of that box.
puzzle[row][column] = (puzzle[row][column] + 1);
//Just used as a breakpoint for a debugger.
if(row == 4 && column == 4){
int x = 0;
}
//If the value is 10, meaning it went through all the possible values:
if(puzzle[row][column] == 10) {
//Do filler() on the previous box
puzzle[row][column] = 0;
currentIndex--;
filler(currentIndex);
}
//If the number is 1-9, but there are duplicates:
else if(!(checkSingleRow(row) && checkSingleColumn(column) && checkSingleBox(row, column))) {
//Do filler() on the same box.
filler(currentIndex);
}
//If the number is 1-9, and there is no duplicate:
else {
currentIndex++;
filler(currentIndex);
}
}
/**
* Used to check if a single row has any duplicates or not. This is called by the
* filler method.
* #param row
* #return
*/
public static boolean checkSingleRow(int row) {
return checkDupl(puzzle[row]);
}
/**
* Used to check if a single column has any duplicates or not.
* filler method, as well as the checkColumns of the checker.
* #param column
* #return
*/
public static boolean checkSingleColumn(int column) {
int[] singleColumn = new int[9];
for(int i = 0; i < 9; i++) {
singleColumn[i] = puzzle[i][column];
}
return checkDupl(singleColumn);
}
public static boolean checkSingleBox(int row, int column) {
//Makes row and column be the first row and the first column of the box in which
//this specific cell appears. So, for example, the box at puzzle[3][7] will iterate
//through a box from rows 3-6 and columns 6-9 (exclusive).
row = (row / 3) * 3;
column = (column / 3) * 3;
//Iterates through the box
int[] newBox = new int[9];
int counter = 0;
for(int i = row; i < row + 3; i++) {
for(int j = row; j < row + 3; j++) {
newBox[counter] = puzzle[i][j];
counter++;
}
}
return checkDupl(newBox);
}
}
Why am I calling it a weird error? A few reasons:
The box that the error occurs on changes randomly (give or take a box).
The actual line of code that the error occurs on changes randomly (it seems to usually happen in the filler method, but that's probably just because that's the biggest one.
Different compilers have different errors in different boxes (probably related to 1)
What I assume is that I just wrote inefficient code, so though it's not an actual infinite recursion, it's bad enough to call a Stack Overflow Error. But if anyone that sees a glaring issue, I'd love to hear it. Thanks!
Your code is not backtracking. Backtracking implies return back on failure:
if(puzzle[row][column] == 10) {
puzzle[row][column] = 0;
currentIndex--;
filler(currentIndex);// but every fail you go deeper
}
There are must be something like:
public boolean backtrack(int currentIndex) {
if (NoBlankBoxes())
return true;
for (int i = 1; i <= 9; ++i) {
if (NoDuplicates()) {
puzzle[row][column] = i;
++currentIndex;
if (backtrack(currentIndex) == true) {
return true;
}
puzzle[row][column] = 0;
}
}
return false;
}

alogrithim possible values java sudoku

Where am I going wrong? This doesn't seem to work. I'm trying to specify in the parameter an i and j which locates the cell. And returns the possible values in a 9 x 9 sudoku grid.
What this does it that the first array i.e a[0]= true if the cell is empty and false if its being played or occupied.
the rest of the array consists of values which are possible values that can be inserted into that i and j cell. therefore a possible value is 4 then it will return a[4]= true and the rest of the boolean array would be possible. can anyone tel me where I'm going wrong? Is the while loop incorrect?
public boolean[] getPossible( int i, int j)
{
final int booArraySize = 10;
boolean[] possibleArray = new boolean[booArraySize];
int zero = 0;
if ( game[i][j] == 0)
{
for( int b=1; b < possibleArray.length; b++)
{
possibleArray[b] = true;
}
int row=i;
int col= 0;
int[] copyy = new int[GRID_SIZE];
for( int m = 0; m < copyy.length; m++)
{
copyy[m] = 1;
}
while ( (copyy[0] < 10) && (copyy[0] >0))
{
for ( int q= col+1; q < game.length; q++)
{
if( copyy[0] == game[row][q])
{
possibleArray[q] = false;
}
else
{
possibleArray[q] = possibleArray[q];
}
}
copyy[0] = copyy[0] + 1;
}
possibleArray[0]= true;
}
return possibleArray;
}
As I understand it, you are trying to set possibleArray to be true at positions corresponding to allowed values. You seem to be scanning the game board and doing some testing in order to decide when to set each index position to true. I would suggest you reverse your logic: set possibleArray to true for all values and then scan the board for values that would rule out particular values. You can do that by using the value of the game board at each position relevant to (i, j) as an index to set possibleArray to false, as in this pseudocode:
// initialize possibleArray to true at all positions
for (each board position u,v along row i, column j, and square containing (i,j)) {
possibleArray[game[u][v]] = false;
}
possibleArray[0] = true; // do this after instead of before
For empty game positions, this will set possibleArray[0] to false, but you fix that after the loop exits.
EDIT:
Here's my attempt to deal with rows and columns simultaneously. It doesn't deal with the 3x3 box containing position (i,j); that's left as an exercise. :)
public boolean[] getPossible( int i, int j)
{
boolean[] possibleArray = new boolean[10];
if (game[i][j] == 0)
{
for( int b=1; b < 10; b++)
{
possibleArray[b] = true;
}
for (int n = 1; n < GRID_SIZE; ++n) {
possibleArray[game[i][n]] = possibleArray[game[n][j]] = false;
}
// TODO Scan the 3x3 square containing cell (i,j)
possibleArray[0]= true;
}
return possibleArray;
}
I assume (based on your code) that game[1][1] through game[GRID_SIZE][GRID_SIZE] are the right index range for the game board.

Categories

Resources