Eight Queens Array out of bounds (Java) - java

I'm trying to make a program that does Eight Queens with recursion but I keep on getting an array out of bounds error. I've been having problems with this for awhile now and I can't really seem to pinpoint the problem. Here's my code:
public class Queens {
public int currColumn = 0;
public static final int BOARD_SIZE = 8;
public static final int EMPTY = 0;
public static final int QUEEN = 1;
private int board[][];
public Queens() {
board = new int[BOARD_SIZE][BOARD_SIZE];
}
public void clearBoard() {
for (int x = 0; x <= BOARD_SIZE; x++) {
for (int y = 0; y <= BOARD_SIZE; y++) {
board[x][y] = 0;
}
}
}
public void displayBoard() {
for (int x = 0; x < BOARD_SIZE; x++) {
System.out.print("\n");
for (int y = 0; y < BOARD_SIZE; y++) {
System.out.print(board[x][y]);
}
}
}
public boolean placeQueens(int column) {
if (column > BOARD_SIZE) {
return true;
} else {
boolean queenPlaced = false;
int row = 1;
while (!queenPlaced && (row <= BOARD_SIZE)) {
if (isUnderAttack(row, column)) {
++row;
} else {
setQueen(row, column);
queenPlaced = placeQueens(column + 1);
if (!queenPlaced) {
removeQueen(row, column);
++row;
}
}
}
return queenPlaced;
}
}
public void setQueen(int row, int column) //SET BACK TO PRIVATE
{
board[row][column] = 1;
}
private void removeQueen(int row, int column) {
board[row][column] = 0;
}
private boolean isUnderAttack(int row, int column) {
if (column == 0) {
return false;
}
int prevColumn = column - 1;
int prevRow = index(prevColumn);
while (prevColumn >= 0) {
prevRow = index(prevColumn);
for (int i = 0; i > BOARD_SIZE; i++) {
if (prevRow == row && prevColumn + i == column) //Going right
{
return true;
}
if (prevRow + i == row && prevColumn + i == column) //Going up/right
{
return true;
}
if (prevRow - i == row && prevColumn + i == column) //Going down/right
{
return true;
}
}
prevColumn--;
}
return false;
}
public int index(int column) //BACK TO PRIVATE
{
for (int i = 0; i < 8; i++) {
if (board[i][column] == 1) {
return i;
}
}
return 0;
}
public static void main(String[] args) {
Queens x = new Queens();
if (x.placeQueens(1) == true) {
x.displayBoard();
} else {
System.out.println("No solution found");
}
}
}

First Problem:
public void clearBoard()
{
for(int x = 0; x < BOARD_SIZE; x++) // changed from x <= BOARD_SIZE
{
for(int y = 0; y < BOARD_SIZE; y++) // changed from y <= BOARD_SIZE
{
board[x][y] = 0;
}
}
}
Array index counting starts from 0 upto size-1. There is nothing in board[8][8].
Another Problem
/* ... */
while(prevColumn >= 0)
{
prevRow = index(prevColumn);
for(int i = 0; i > BOARD_SIZE; i++) // i=0; i> BOARD_SIZE is always false, so no looping mechanism
{ /* ... */ }
Change it to
for(int i = 0; i < BOARD_SIZE; i++) // corrected
Another Problem ?
if(column > BOARD_SIZE) when `column = 8`
Make it
if(column >= BOARD_SIZE)
Another Problem:
while(!queenPlaced && (row <= BOARD_SIZE))
Make it
row < BOARD_SIZE
Yet Another ?
queenPlaced = placeQueens(column + 1); // What if column = 7

for(int x = 0; x <= BOARD_SIZE; x++)
Change that to:
for(int x = 0; x < BOARD_SIZE; x++)
Since arrays are 0-indexed.

You try to access more elements than the declared array actually has:
// this means you can access index in [0, BOARD_SIZE - 1].
board = new int[BOARD_SIZE][BOARD_SIZE];
// this means you access index in [0, BOARD_SIZE].
for(int x = 0; x <= BOARD_SIZE; x++)
So, a good practice is to always use < when referring to the declared size of the array.

In java array indexes starts from zero.
for(int x = 0; x <= BOARD_SIZE; x++)
should be
for(int x = 0; x < BOARD_SIZE; x++)
{
for(int y = 0; y < BOARD_SIZE; y++)
{
board[x][y] = 0;
}
Your BOARD_SIZE is 8 .so array initialized for 8 elelements. So avaliable indexes are 0 to 7.
in loop
for(int x = 0; x <= BOARD_SIZE; x++)
when x=8 ArrayIndexOutOfBound Exception throws.
Check this point in all your arrays,where you are looping.

Related

How I can read how many mines are around each empty cell.Game minesweeper

The program below ask the user how many mines he wants to see on the field and then display the field with mines.
In next step I need to calculate how many mines are around each empty cell. And I know that I
need to check 8 cells if the cell is in the middle, 5 cells if the cell is in the side, and 3
cells if the cell is in the corner. If there are from 1 to 8 mines around the cell, I need to
output the number of mines instead of the symbol representing an empty cell.
import java.util.Scanner;
import java.util.Random;
public class Minesweeper {
char[][] minesweeper = new char[9][9];
Random randNum = new Random();
Scanner sc = new Scanner(System.in);
public Minesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
minesweeper[i][j] = '*';
}
}
}
public void printMinesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(minesweeper[i][j]);
}
System.out.println();
}
}
public void randomX() {
System.out.print("How many mines do you want on the field?: ");
int numberOfMines = sc.nextInt();
int i = 0;
while (i < numberOfMines) {
int x = randNum.nextInt(9);
int y = randNum.nextInt(9);
if (minesweeper[x][y] == '*') {
minesweeper[x][y] = 'X';
i++;
}
}
printMinesweeper();
}
}
You can do it like this:
import java.util.Random;
import java.util.Scanner;
public class Minesweeper {
public static void main(String[] args) {
Minesweeper minesweeper = new Minesweeper();
minesweeper.randomX();
minesweeper.printMinesweeper();
}
char[][] minesweeper = new char[9][9];
Random randNum = new Random();
Scanner sc = new Scanner(System.in);
public Minesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
minesweeper[i][j] = '*';
}
}
}
public void printMinesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(getCharAt(i, j));
}
System.out.println();
}
}
private String getCharAt(int i, int j) {
if (mineAt(i, j)) {
return "X";
}
int minesNear = countMinesNear(i, j);
return Integer.toString(minesNear);
}
private boolean mineAt(int i, int j) {
return minesweeper[i][j] == 'X';
}
private int countMinesNear(int i, int j) {
int mines = 0;
for (int x = -1; x <= 1; x++) {//near fields in x direction
for (int y = -1; y <= 1; y++) {//near fields in y direction
if (x + i >= 0 && x + i < minesweeper.length && y + j >= 0 && y + j < minesweeper.length) {//check whether the field exists
if (minesweeper[x+i][y+j] == 'X') {//check whether the field is a mine
mines++;
}
}
}
}
return mines;
}
public void randomX() {
System.out.print("How many mines do you want on the field?: ");
int numberOfMines = sc.nextInt();
int i = 0;
while (i < numberOfMines) {
int x = randNum.nextInt(9);
int y = randNum.nextInt(9);
if (minesweeper[x][y] == '*') {
minesweeper[x][y] = 'X';
i++;
}
}
printMinesweeper();
}
}
The countMinesNear(int, int) method check whether the field near exists (to prevent index errors on the edges) and counts the mines if the fields exist.

Sudoku Solver throwing ArrayIndexOutOfBoundsException [duplicate]

This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 3 years ago.
My sudoku solver replaces "-" with zeros, then solves the puzzle. It works for most puzzles that I've tried, but throws an ArrayIndexOutOfBoundsException for puzzles with a full row of dashes. I've tried tweeking different things to get it to work, but I'm a little lost.
This is what the puzzle looks like.
public static int[][] theArray = new int [9][9];
public static int SIZE = 9;
private static boolean isCompletePuzzle() {
// checks for 0 in rows/cols
for (int i = 0; i <= SIZE; i++) {
for (int j = 0; j <= SIZE; j++) {
if (theArray[i][j] != 0) {
return true;
}
}
}
return false;
}
private static boolean isValidPuzzle(int row, int col, int number) {
// checks rows
for (int i = 0; i < SIZE; i++) {
if (theArray[row][i] == number) {
return true;
}
}
// checks columns
for (int i = 0; i < SIZE; i++) {
if (theArray[i][col] == number) {
return true;
}
}
// checks 3x3
int r = row - row % 3;
int c = col - col % 3;
for (int i = r; i < r + 3; i++)
for (int j = c; j < c + 3; j++)
if (theArray[i][j] == number)
return true;
return false;
}
private static boolean isSolvedPuzzle(int row, int col, int number) {
if (isValidPuzzle(row, col, number) == true && isCompletePuzzle() == true) {
return true;
}
return false;
}
public static boolean solvePuzzle() {
for (int row = 0; row < SIZE; row++) {
for (int col = 0; col < SIZE; col++) {
if (theArray[row][col] == 0) {
for (int number = 1; number <= SIZE; number++) {
if (!isSolvedPuzzle(row, col, number)) {
theArray[row][col] = number;
if (solvePuzzle()) {
return true;
}
else {
theArray[row][col] = 0;
}
}
}
return false;
}
}
}
return true;
}
in ur isCompletePuzzle() function ur loop conditions i <= SIZE and j <= SIZE cause ArrayIndexOutOfBoundsException
when i is 9 the if (theArray[i][j] != 0) throw ArrayIndexOutOfBoundsException

Minesweeper Nearby Mine Counting

I'm trying to create a 10x10 Minesweeper-esque board made of _'s, with 10 mines randomly placed as *'s. No actual gameplay is involved, just the making of the board. I've been able to (somewhat) successfully place the mines randomly but I can't get the nearby mine counting aspect to work. I've tried many different things but this is what I've come up with so far.
import java.util.Random;
public class Mines {
public static final int BOARD_SIZE = 10;
enum Space {Empty, Mine, MineCount};
public static void main(String[] args) {
Random rand = new Random();
//Creates board
Space[][] board = new Space[BOARD_SIZE][BOARD_SIZE];
for (int y=0;y<board.length;y++)
{
for (int x=0;x<board.length;x++)
{
board[x][y] = Space.Empty;
}
}
System.out.println("Creating empty board");
//Draws the board
for(int y=0;y<board.length;y++)
{
for(int x=0;x<board.length;x++)
{
switch(board[y][x])
{
case Empty:
System.out.print("_");
break;
default:
System.out.println("?");
}
}
System.out.println();
}
System.out.println("Placing mines");
//Sets mines
for(int i=0;i<board.length;i++)
{
int mX = rand.nextInt(BOARD_SIZE);
int mY = rand.nextInt(BOARD_SIZE);
if(board[mX][mY] == Space.Empty)
{
board[mX][mY] = Space.Mine;
}
}
for(int y=0;y<board.length;y++)
{
for(int x=0;x<board.length;x++)
{
switch(board[y][x])
{
case Empty:
System.out.print("_");
break;
case Mine:
System.out.print("*");
break;
}
}
System.out.println();
}
//Count mines
System.out.println("Counting the mines");
//Prints board again
for(int y=0;y<board.length;y++)
{
for(int x=0;x<board.length;x++)
{
switch(board[y][x])
{
case Empty:
System.out.print("_");
break;
case Mine:
System.out.print("*");
break;
case MineCount:
int mineCount = 0;
if(board[x-1][y-1] == Space.Mine)
{
mineCount++;
board[y][x] = Space.MineCount;
System.out.print(mineCount);
}
}
}
System.out.println();
}
}
}
Try this code (Not an object oriented approach), but is easily understandable:
import java.util.Random;
public class Mines {
public static final int BOARD_SIZE = 5;
enum Space {
Empty, Mine
};
public static void main(String[] args) {
Random rand = new Random();
// Creates board
System.out.println("Empty board");
Space[][] board = new Space[BOARD_SIZE][BOARD_SIZE];
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board.length; x++) {
board[x][y] = Space.Empty;
System.out.print("_");
}
System.out.println();
}
// Sets mines
for (int i = 0; i < BOARD_SIZE; i++) {
int mX = rand.nextInt(BOARD_SIZE);
int mY = rand.nextInt(BOARD_SIZE);
// Condition if random number combination [mX, mY] generated previously. Guarantees BOARD_SIZE mines always.
if(Space.Mine.equals(board[mX][mY])) {
i--;
continue;
}
board[mX][mY] = Space.Mine;
}
System.out.println("\nPlacing mines");
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board.length; x++) {
switch (board[y][x]) {
case Empty :
System.out.print("_");
break;
case Mine :
System.out.print("*");
break;
}
}
System.out.println();
}
// Count mines
System.out.println("\nCounting mines");
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board.length; x++) {
if(Space.Mine.equals(board[y][x])) {
System.out.print("*");
} else {
System.out.print(findAdjCount(y, x, board));
}
}
System.out.println();
}
}
private static int findAdjCount(int row, int col, Space[][] board) {
int cnt = 0;
// Check 8 adjacent positions
for (int i = row - 1; i <= row + 1; i++) {
for (int j = col - 1; j <= col + 1; j++) {
if(i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE) {
if(Space.Mine.equals(board[i][j])) {
cnt++;
}
}
}
}
return cnt;
}
}

Sudoku - How to use HashSet or Set?

I'm trying to code a method which checks for duplicates on my Sudoku board. Currently, my method getFrontier() always returns true, and I've come to learn that it's because it's only checking for one value rather than an array or values. I use the method 3 times in squareCheck(), rowCheck() and columnCheck(). Is there any way to code the method so it would retain the previous value which was input and then check it against the new value?
My current code:
public class validCheck {
public boolean isSolved(int[][][] board)
{
for(int index = 0; index < board.length;index++)
{
for(int r = 0; r < board[0].length; r++)
{
for(int c = 0; c < board[0].length;c++)
{
if(board[index][r][c] == 0)
return false;
}
}
}
return true;
}
public boolean getFrontier(int value)
{
Set<Integer> reserve = new HashSet<>();
for(int n = 1; n < 10; n++)
{
if(value == n && reserve.contains(n))
return false;
else if(value == n) reserve.add(n);
}
return true;
}
public boolean squareCheck(int[][][] board, int index)
{
for(int r = 0; r < board[0].length; r++)
{
for(int c = 0; c < board[0].length; c++)
{
if(!getFrontier(board[index][r][c]))
{
System.out.println("Square error at ["+index + r + c +"]");
return false;
}
}
}
return true;
}
public boolean isValid(int[][][] board)
{
if(isSolved(board))
{
for(int i = 0; i < board.length; i++)
{
for(int r = 0; r < board[0].length;r++)
{
for(int c = 0; c < board[0].length;c++)
{
if(!rowCheck(board,i,r) || !columnCheck(board,i,c) || !squareCheck(board,i))
{
return false;
}
}
}
}
}
return true;
}
public boolean columnCheck(int[][][] board, int index, int col)
{
int target = 0;
if(index <=2)
{
target = index + 6;
}
else if(index > 2 && index < 6)
{
target = index +3;
index = index - 3;
}
else if (index > 5)
{
target = index;
index = index - 6;
}
while(index <= target)
{
for(int r = 0; r < board[0].length;r++)
{
if(!getFrontier(board[index][r][col]))
{
System.out.println("Column error at " + index + r + col);
return false;
}
}
index = index + 3;
}
return true;
}
public boolean rowCheck(int[][][] board, int index, int row)
{
int target = 0;
if(index <= 2)
{
index = 0;
target = 2;
}
else if (index <= 5)
{
index = 3;
target = 5;
}
else if(index <= 8)
{
index = 6;
target = 8;
}
while(index <= target)
{
for(int c = 0; c < board[0].length; c++)
{
if(!getFrontier(board[index][row][c]))
{
System.out.println("Row error at "+index+row+c);
return false;
}
}
index++;
}
return true;
}
}
Usage:
public static void main(String[] args) {
int[][][] solved = {{{5,3,4},{6,7,2},{1,9,8}},
{{6,7,8},{1,9,5},{3,4,2}},
{{9,1,2},{3,4,8},{5,6,7}},
{{8,5,9},{4,2,6},{7,1,3}},
{{7,6,1},{8,5,3},{9,2,4}},
{{4,2,3},{7,9,1},{8,5,6}},
{{9,6,1},{2,8,7},{3,4,5}},
{{5,3,7},{4,1,9},{2,8,6}},
{{2,8,4},{6,3,5},{1,7,9}}};
validCheck checker = new validCheck();
if(checker.isValid(solved))
System.out.println(true);
else System.out.println(false);
}
Any help will be greatly be appreciated!!!
Here is what I would do to find a valid board config in a 2D sudoku board. I would use a HashSet for a row and another for the column, as long as we never encounter repeats and the values contain 1 to the length of the array we know the board is valid.
int [][] board = {{1,2,3},
{2,3,1},
{3,1,2}
};
HashSet<Integer> rowDuplicates = new HashSet<>();
HashSet<Integer> colDuplicates = new HashSet<>();
boolean invalidBoard = false;
for(int i = 0 ; i < board.length; i++)
{
for(int j = 0; j < board[i].length; j++)
{
if(rowDuplicates.contains(board[i][j]) || colDuplicates.contains(board[j][i]))
{
//this board is not valid
invalidBoard = true;
}
else
{
rowDuplicates.add(board[i][j]);
colDuplicates.add(board[j][i]);
}
}
//now check they contain the correct numbers from 1 to the size of the array
if(colDuplicates.size() == rowDuplicates.size())
{
for(int index = 0; index < colDuplicates.size(); index++)
{
if(!(colDuplicates.contains(index + 1) && rowDuplicates.contains(index + 1)))
{
invalidBoard = true;
break;
}
}
}
else
{
invalidBoard = true;
}
colDuplicates.clear();
rowDuplicates.clear();
}
System.out.println("invalid board: " + invalidBoard);
You should be able to expand this to your 3D array but you can see how much easier it is to use HashSets to verify a valid 2D array Sudoku board.

Check scalable matrix diagonals for identical string

I am creating a scalable TicTacToe program, and I am running into an issue when trying to check the diagonals for a string.
I was able to check the rows by using this method:
public boolean checkRowsForWin(String b){
//Check all the rows for a winner
for(int y = 0; y < size; y++){
for (int x = 0; x < size; x++){
if (globalGrid[y][x].equals(b)){
inRow++;
if (inRow >= neededToWin){
return true;
}
}else{
inRow = 0;
}
}
inRow = 0;
}
inRow = 0;
return false;
}
I have tried a combination of for loops and if statements, and my last modification is this below. This worked if the diagonal included the top right corner only, when I need it to check even if the diagonal isn't in a corner.
public boolean checkDiagForWin(String b, int c, int d){
for (int x = c, y = d; x < size && y < size; x++, y++){
if (globalGrid[y][x].equals(b)){
inRow++;
if (inRow >= neededToWin){
return true;
}
}
else{
inRow = 0;
}
inRow = 0;
for (int x2 = size - 1, y2 = 0; x2 >=0 && y2 < size; x2--, y2++){
if (globalGrid[y2][x2].equals(b)){
inRow++;
if (inRow >= neededToWin){
return true;
}
}
else{
inRow = 0;
}
}
inRow = 0;
}
inRow = 0;
return false;
}
The amount in a row and the size of the board can change, so it isn't as simple as checking just two adjacent to the position.
You need to start the process starting at every possible position, one possible implementation could be:
A function to start the check process at every position:
public boolean checkDiagonals(String b) {
/* Check the diagonals starting in every position */
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (checkDiagonalForWin(b, i, j) || checkOtherDiagonalForWin(b, i, j)) {
return true;
}
}
}
return false;
}
There are the functions to check the diagonals starting in some position:
public boolean checkDiagonalForWin(String b, int row, int col){
for (int inRow = 0; row < size && col < size; row++, col++) {
//Check all the rows for a winner
if (globalGrid[row][col].equals(b)){
inRow++;
if (inRow >= neededToWin){
return true;
}
}else{
inRow = 0;
}
}
return false;
}
public boolean checkOtherDiagonalForWin(String b, int row, int col){
for (int inRow = 0; row < size && col >= 0; row++, col--) {
//Check all the rows for a winner
if (globalGrid[row][col].equals(b)){
inRow++;
if (inRow >= neededToWin){
return true;
}
}else{
inRow = 0;
}
}
return false;
}

Categories

Resources