I have been trying to make a Lines of Action board with recursive. I have already done the multidimensional array (8x8). Now, the only problem I have is how to put the pieces in their correct place (especially the black ones). What's my problem? when I'm trying to print the first row of the pieces it prints something like this: "-b-b-b-b-b--", instead of "-bbbbbb-". This is also true for the last row.
public static void im (int[][]m, int r, int c){//Matriz
if (r==m.length-1 && c==m[0].length-1) {
System.out.print("-");
} else {
if(r==0 && c>0 && c<m[0].length-1){
System.out.print("b");
}
if(c==0 && r>0 && r<m.length-1){
System.out.print("w");
}
if (c==m[0].length-1) {
if(r>0){
System.out.print("w");
System.out.println("");
im(m,r+1,0);
}else{
System.out.print("-");
System.out.println("");
im(m,r+1,0);
}
} else {
System.out.print("-");
im(m,r,c+1);
}
}
}
The logic in your if-statements is flawed, you could try again and comment in every block what you know upto now. Like this:
if (a) {
// I know that a == true
if (b) {
// I know that a == true && b == true
} else {
// I know that a == true && b == false
}
}
This way you can easily spot the mistakes yourself, if this doesn't help just comment and I'll reply the correct code.
EDIT: Here is the correct code:
if (r == 0 || r == m[0].length - 1) {
// top or bottom row
if (c == 0 || c == m.length - 1) {
// top or bottom row and leftmost column or rightmost column
System.out.print("-");
} else {
// top or bottom row and not leftmost column or rightmost column
System.out.print("b");
}
} else {
// not top or bottom row
if (c == 0 || c == m.length - 1) {
// not top or bottom row and leftmost column or rightmost column
System.out.print("w");
} else {
// not top or bottom row and not leftmost column or rightmost column
System.out.print("-");
}
}
I don't really know how to fix your original code since it doesn't really make sense to me, so I just completely rewrote it, a good thing to remember is that you want every function call to output only 1 character so at least try to gaurantee that it can only reach one of the print statements at a time.
EDIT2:
public static void im(int[][] m, int r, int c) {
if (r == 0 || r == m.length - 1) {
// top or bottom row
if (c == 0 || c == m[0].length - 1) {
// top or bottom row and leftmost column or rightmost column
System.out.print("-");
} else {
// top or bottom row and not leftmost column or rightmost column
System.out.print("b");
}
} else {
// not top or bottom row
if (c == 0 || c == m[0].length - 1) {
// not top or bottom row and leftmost column or rightmost column
System.out.print("w");
} else {
// not top or bottom row and not leftmost column or rightmost column
System.out.print("-");
}
}
if (c == m[0].length - 1) {
// rightmost column
System.out.println();
if (r != m.length - 1) {
// not bottom row
im(m, r + 1, 0);
}
} else {
// not rightmost column
im(m, r, c + 1);
}
}
Related
I am creating a simple Connect Four program in Kotlin using a 2D array to print the board. Everything works fine except for my horizontal win-checker function. Because of the logic I am using, I get (index out of bounds) errors when trying to put your piece on the first column, because it is trying to check the next column in the array, but there is none. Is there a better way to handle checking for a winner? This is my function:
fun checkWinsHorizontal() {
for(row in 0 until gameBoard.size) {
for(col in 0 until gameBoard.size){
// if this spot is taken up by an "X", and the horizontally adjacent spaces are the same, declare winner
if (gameBoard[row][col] == "X" && (gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]) ){
printBoard()
println("YOU WIN")
winner = true
return
}
// same thing as above but for a "computer" opponent
else if (gameBoard[row][col] == "O" && gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]){
printBoard()
println("COMPUTER WINS")
winner = true
return
}
}
}
}
The comments above explain why you're getting the index out of bounds (you have hard coded values like gameBoard[row][col - 1] but col might be 0). I suggest a few fixes:
First, there's no need to check every cell on the board after each move. The only way a player can win is if the piece they just placed completes a row, column, or diagonal. So I suggest you check only potential wins involving that cell.
To do that for a row you could have something like:
fun completesRow(row: Int, col: Int) : Boolean {
var count: Int = 1
val symbol = gameBoard[row][col]
// First move left - now we check that the symbols (X or O) match
// AND that we're within bounds.
var curCol = col - 1
while (curCol >= 0 && gameBoard[row][curCol] == symbol) {
++count
if (count == 4) {
return true
}
--curCol
}
// same thing to the right; numColumns is assumed to be the number of
// columns in the board.
curCol = col + 1
while (curCol < numColumns && gameBoard[row][curCol] == symbol) {
++count
if (count == 4) {
return true
}
++curCol
}
// if you got here there weren't 4 in a row
return false
}
Note: the above is untested - I doubt it even compiles, but hopefully it's instructive.
You can also further generalize this if you want. Instead of having different functions that move left/right, up/down, and diagonally you could create Iterator instances for those movements and then have a single function that takes 2 iterators (one moving left and one right for example) and it can do the checks using that. That way you can use the same exact method to check a horizontal, vertical, or diagonal win.
I am creating a boardgame which has two different coloured pieces, black and red.
If a player surrounds the opponents pieces with his own, either horizontally or vertically, the pieces are removed. Here are some pictures to demonstrate this:
My board is a simple 2d integer array, with values of 0, 1 or 2 depending on whether the space is empty, has a red piece or a black piece.
This is the code I have come up with so far, however I am getting issues with out of bounds errors and it also does not account for capturing more than one piece.
static final int EMPTY = 0, BLACK = 1, RED = 2, ROW = 9, COLUMN = 9;
board = new int[ROW][COLUMN];
public void captureRedPieces() {
for(int i = 0; i < ROW; i++) {
for(int j = 0; j < COLUMN; j++) {
if(i <= ROW - 2) {
if(board[i][j] == 1 && board[i + 1][j] == 2 && board[i + 2][j] == 1) {
board[i + 1][j] = EMPTY;
}
}
if(i <= COLUMN - 2) {
if(board[i][j] == 1 && board[i][j + 1] == 2 && board[i][j + 2] == 1) {
board[i][j + 1] = EMPTY;
}
}
}
}
}
Could anyone help me come up with a better solution for capturing pieces?
You are testing whether i <= ROW - 2, but then you are using i+2 as an index for your check. This means that if i is 7, which is equal to ROW - 2 and passes your if test, then i+2 will be 9, which is out of bounds because the array only goes 0 to 8.
So you should correct this to i < ROW - 2 rather than <=.
Also, you have this code:
if(i <= COLUMN - 2) {
if(board[i][j] == 1 && board[i][j + 1] == 2 && board[i][j + 2] == 1) {
board[i][j + 1] = EMPTY;
}
}
This should be a condition on j, not on i - and it has to be fixed in the same way I told you about i - < instead of <=.
Note: since your rules state that a "surrounding" state is a capture only after the surrounding color makes a move, perhaps you should change your approach: you should only check the position where black made a move, to match with positions around it. Of course, you'll still have to make sure you don't go out of bounds. Your current approach might mark places that are "surrounded" since previous moves, and that would be wrong per the rules.
So your method should be declared like so:
public void captureRedPieces(int blackMoveRow, int blackMoveCol )
Probably you have to replace i <= COLUMN - 2 with j <= COLUMN - 2. Seems that capturing occurs after the new move. If you know the exact position of the new piece, then no need to iterate over the whole board. You just need to check nearby pieces in the same row and in the same column where the new piece was placed.
public boolean findSolution() {
boolean finish = false; //finish should become true when a solution is found or it is determined that there is no solution
boolean success = false; //success should become true when a solution is found
//The following can be used to compute each of 8 directions
//one can move from their current position (row,column).
int[][] offset ={
{1,0}, //Down
{1,-1}, //DownLeft
{0,-1}, //Left
{-1,-1}, //UpLeft
{-1,0}, //Up
{-1,1}, //UpRight
{0,1}, //Right
{1,1} //DownRight
};
//Push information onto the stack indicating the first choice
//is the position of row 0 and column 9. The last value is face, put -1 as default
Position nextPosition = new Position(0, 9, -1);
stackSoln.push(nextPosition);
while (finish == false && stackSoln.isEmpty( ) == false) {
//check the last position
int currentRow = stackSoln.peek().getRow();
int currentCol = stackSoln.peek().getColumn();
System.out.println("Trying the position of row "
+ currentRow
+ " and column "
+ currentCol);
int newRow = -1;
int newColumn=-1;
for (int k = 0; k < 8; k++)
{
newRow = currentRow + offset[k][0];
newColumn = currentCol + offset[k][1];
//get a new position and push it
nextPosition = new Position(newRow, newColumn, -1);
stackSoln.push(nextPosition);
if (newRow < 9 && newColumn < 9 && newRow > 0 &&
newColumn > 0 && (maze[newRow][newColumn] == 'x' &&
maze[newRow][newColumn] == '.' ||
maze[newRow][newColumn] == '<' || maze[newRow][newColumn] ==
'>'))
{
if (maze[newRow][newColumn] == '<') //end of the maze
{
nextPosition.setFace(k);
success = true;
finish = true;
}
else if (maze[newRow][newColumn] == '.') //able to move
{
maze[newRow][newColumn] = 'x';
nextPosition.setFace(k);
break;
}
else
{
maze[newRow][newColumn] = 'O'; //unable to move, therefore pop the position.
stackSoln.pop();
}
if (stackSoln.isEmpty() == true)
{
success = false;
finish = true;
}
}
}
} //end of while loop
return success;
}//end of findSolution method
Given input like this: http://i.imgur.com/16KTaox.png
It is supposed to return:
Trying the position of row 0 and column 9
Trying the position of row 1 and column 8
Trying the position of row 2 and column 7
Trying the position of row 3 and column 7
Trying the position of row 4 and column 7
Trying the position of row 4 and column 6
Trying the position of row 5 and column 5
Trying the position of row 4 and column 4
Trying the position of row 5 and column 3
Trying the position of row 6 and column 3
Trying the position of row 7 and column 3
Trying the position of row 8 and column 3
Trying the position of row 9 and column 2
Trying the position of row 9 and column 1
But instead, my code does something like:
Trying the position of row 59834 and column 59843
Trying the position of row 59835 and column 59844
Trying the position of row 59836 and column 59845...etc
For some reason if I change the main if statement in the for loop to ors instead of ands, it gets the right values up to the last one where it then gets an index out of bounds error. I have no idea why though because ors shouldn't be used in this situation...
The problem is that you're pushing new positions onto the stack before checking that the row and column are valid.
Look at these lines in your code:
//get a new position and push it
nextPosition = new Position(newRow, newColumn, -1);
stackSoln.push(nextPosition);
Instead of pushing nextPosition onto the stack immediately, wait until you've validated the position.
You probably want to push the position onto the stack inside the block guarded by this if statement:
if (newRow <= 9 && newColumn <= 9 && newRow > 0 &&
newColumn > 0 && (maze[newRow][newColumn] == 'x' &&
maze[newRow][newColumn] == '.' ||
maze[newRow][newColumn] == '<' || maze[newRow][newColumn] ==
'>'))
However, there are some problems with the conditional expression. You should accept zero values for newRow and newColumn. Also, the part where you check the character in the maze is complicated and incorrect because you're mixing && with || and because you're not accounting for the O characters that you're putting into the maze.
I suggest that you use this expression instead:
if (newRow >= 0 && newRow < mazeSize &&
newColumn >= 0 && newColumn < mazeSize &&
maze[newRow][newColumn] != '#')
Note that it's better to use the class attribute mazeSize instead of a hard-coded value. This allows the expression to work for different maze sizes.
There are further problems in your code that fall outside the scope of this question.
public Action getMove(CritterInfo info) {
count++;
Direction d = info.getDirection();
if (count < 100) {
if (info.getFront() == Neighbor.OTHER) {
return Action.INFECT;
} else {
return Action.RIGHT;
}
}
if (count >= 100) {
if (info.getFront() == Neighbor.OTHER) {
return Action.INFECT;
} else if (count / 100.0 < 2.0 && count / 100.0 >= 1.0 && !(d == Direction.EAST)) {
return Action.LEFT;
} else if (count / 100.0 < 3.0 && count / 100.0 >= 2.0 && !(d == Direction.WEST)) {
return Action.RIGHT;
} else {
return Action.HOP;
}
}
return Action.INFECT;
}
Right now I have this code that is part of my critter and i'm having problems are the if (count >= 100) part of the code. I can't get my go east and go west code to repeat itself because when I divide count by 100.0, it only works up until 299 then it just stays going west running into the wall. I've tried to set an else if statement after my go west code stating
} else if (count == 299) {
count = 0;
}
but this didn't solve my problem either. Any ideas? I just want my critter to sweep east and west over and over again.
Just use variables instead of your numbers, and change them each time their numbers are reached.Then you can create a method that changes the direction each time the number reaches 100+(100*n).
So, if you reach 200, it will check that the condition I set above is true and will therefore change directions for the next 100 numbers.
Was this what you were looking for , or did I misunderstand what you wanted?
You can use some kind of "cyclic" function like modulo (%) instead of the absolute value of count. E.g.
public Action getMove(CritterInfo info) {
count++;
Direction d = info.getDirection();
if (count < 100) {
if (info.getFront() == Neighbor.OTHER) {
return Action.INFECT;
} else {
return Action.RIGHT;
}
}
else {
int choiceOfAction = (count - 100)%200;
if (0 <= choiceOfDir && choiceOfDir < 100 && !(d == Direction.EAST)) {
return Action.LEFT;
} else if (100 <= choiceOfDir && choiceOfDir < 200 && !(d == Direction.WEST)) {
return Action.RIGHT;
} else {
return Action.HOP;
}
}
}
The line int choiceOfAction = (count - 100)%200; will yield a value of choiceOfAction with:
if count is in [100, 200[ : choiceOfAction is in [0, 100[
if count is in [200, 300[ : choiceOfAction is in [100, 200[
if count is in [300, 400[ : choiceOfAction is in [0, 100[
etc.
Note that I removed the last return in your method that was never reached, and also, that in the case above you will HOP only when you reach the limit and change direction.
I'm trying to solve a problem which uses a 2D array, the problem of a rat in a maze.
While checking the conditions trying to compile, it finds an Array index out of bounds exception... how can I check the values so it doesn't go out of the array bounds?
static void solveMaze(){
int nSteps = 0; // Number of steps.
int x = 0; int y = 0; // Starting point.
boolean mazeCompleted = false;
while (!mazeCompleted){
if(x == maze.mazeMatrix.length && y == maze.mazeMatrix.length)
mazeCompleted = true;
else if(maze.mazeMatrix[x+1][y] == 0){ // Move right.
maze.mazeMatrix[x+1][y] = 2;
x++; nSteps++;
}
else if(maze.mazeMatrix[x-1][y] == 0){ // Move left.
maze.mazeMatrix[x-1][y] = 2;
x--; nSteps++;
}
else if(maze.mazeMatrix[x][y+1] == 0){ // Move down.
maze.mazeMatrix[x][y+1] = 2;
y++; nSteps++;
}
else if(maze.mazeMatrix[x][y-1] == 0){ // Move up.
maze.mazeMatrix[x][y-1] = 2;
y--; nSteps++;
}
}
maze.printMatrix();
System.out.println("Maze COMPLETE! - With a total of " + nSteps + " steps.");
}
Tried before with two "for" loops to prevent the out of bounds but I just can't go diagonal in this problem.
You have a pretty crucial bug in your program. You will never reach the end of the maze!
if(x == maze.mazeMatrix.length && y == maze.mazeMatrix.length)
references indices that are out of bounds! It should be
if(x == maze.mazeMatrix.length - 1 && y == maze.mazeMatrix.length - 1)
You also need to check to see whether you can & should move before you try to move there. I.E. :
while (!mazeCompleted){
boolean moveRight = (x + 1 < mazeMatrix.length && maze.mazeMatrix[x+1][y] == 0 ? true : false);
boolean moveLeft = (x - 1 >= 0 && maze.mazeMatrix[x-1][y] == 0 ? true : false);
boolean moveUp = (y + 1 < mazeMatrix[x].length && maze.mazeMatrix[x][y+1] == 0 ? true : false);
boolean moveDown = (y - 1 >= 0 && maze.mazeMatrix[x][y-1] == 0 ? true : false);
And:
else if(moveRight) { // Move right.
maze.mazeMatrix[x+1][y] = 2;
x++; nSteps++;
}
etc. Although it does seem like this is something that should be solved recursively, as if there are any loops in the maze you will end up getting stuck and infinite looping.