Reputation: 33
I'm trying to make a chess game in Java that can be played on the console. For each move, the game asks the player for a piece, (for example 12 for the piece in the second row, third column) and a final location (for example 32 for the fourth row, third column). Everything is working perfectly, including tests to see if the move is illegal and if a given player is in check, but my gameOver boolean seems to be changing the value of my board array before the first move is asked for.
Here is the relevant code. From my main method:
public static void main(String[] args) {
int[][] board = { {12, 13, 14, 15, 16, 14, 13, 12},
{11, 11, 11, 11, 11, 11, 11, 11},
{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},
{21, 21, 21, 21, 21, 21, 21, 21},
{22, 23, 24, 25, 26, 24, 23, 22}
};
Scanner scan = new Scanner(System.in);
boolean oneTurn = true;
while(!(gameOver(oneTurn, board))) {
printBoard(board);
System.out.println(((oneTurn) ? "1's" : "2's") + " turn");
System.out.print("What piece? ");
int origin = scan.nextInt();
The gameOver boolean, which tests to see if there are any moves the current player can make that are legal and won't put the player in check:
public static boolean gameOver(boolean oneTurn, int[][] board) {
for (int a = 0; a<8; a++) {
for(int b = 0; b<8; b++) {
for (int c = 0; c<8; c++) {
for(int d = 0; d<8; d++) {
if(board[a][b] / 10 == (oneTurn ? 1 : 2) && !(illegal(oneTurn, 10*a+b, 10*c+d, board)) && !(illegalCheck(oneTurn, 10*a+b, 10*c+d, board))) return false;
}
}
}
}
return true;
}
The check method, which tries to find a legal move the other player can do that will eliminate the king:
public static boolean check(boolean oneTurn, int[][] board) {
int king = kingNum(oneTurn, board);
for (int a = 0; a<8; a++) {
for(int b = 0; b<8; b++) {
if(board[a][b] / 10 == (oneTurn ? 2 : 1) && !(illegal(!oneTurn, 10*a+b, king, board))) return true;
}
}
return false;
}
The illegalCheck method, which tests to see if a move will put the player in check. I think this is where the problem lies. I tried to make a separate newBoard so that the original board wouldn't change, but it still creates the problem.
public static boolean illegalCheck(boolean oneTurn, int origin, int dest, int[][] board) {
int[][] newBoard = board;
newBoard[dest / 10][dest % 10] = board[origin / 10][origin % 10];
newBoard[origin / 10][origin % 10] = 0;
if(check(oneTurn, newBoard)) return true;
else return false;
}
When I run the program for the first time, the first output I get is this:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
_____________________________________________
0 | 1R | | 1B | 1Q | 1K | 1B | 1N | 1R |
_____________________________________________
1 | 1P | 1P | 1P | 1P | 1P | 1P | 1P | 1P |
_____________________________________________
2 | | | | | | | | |
_____________________________________________
3 | | | | | | | | |
_____________________________________________
4 | | | | | | | | |
_____________________________________________
5 | | | | | | | | |
_____________________________________________
6 | 2P | 2P | 2P | 2P | 2P | 2P | 2P | 2P |
_____________________________________________
7 | 2R | 2N | 2B | 2Q | 2K | 2B | 2N | 2R |
_____________________________________________
1's turn
What piece?
The first legal move found by gameOver is the knight moving, so I think that's why the knight isn't showing up on the first board. When I put the printBoard method before the boolean test, the board prints perfectly.
I just began learning to program recently, so I would appreciate any advice about why this would be happening. It could be something blatantly obvious that I'm missing. Let me know if there are other details I can provide. Thank you!
Upvotes: 3
Views: 1539
Reputation: 13653
When you write
int[][] newBoard = board;
newBoard[dest / 10][dest % 10] = board[origin / 10][origin % 10];
newBoard[origin / 10][origin % 10] = 0;
you're creating newBoard
as a new reference to the same array object as board
, and then proceeding to modify the array. You can copy it instead like this:
int[][] newBoard = new int[8][];
for (int i = 0; i < newBoard.length; ++i)
newBoard[i] = board[i].clone();
Java's multidimensional arrays are arrays of references to other arrays (because arrays are objects), so first we create a new top-level array, then assign copies of the subsidiary arrays into it. (There are a bunch of rules about Object.clone()
and Cloneable
, but all you have to know here is that cloning an array makes a new array with the same values. For multidimensional arrays this is a shallow copy (the copy refers to the same subsidiary arrays), so we can't just call board.clone()
and be done with it.)
Upvotes: 1
Reputation: 1120
I would recommend using a debugger and setting some breakpoints so you can see what exactly is going on, that way you won't be guessing.
More info on debugging sessions with java: http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jdb.html
Upvotes: 0
Reputation: 1171
If you believe it is due to the copy of the array, try System.arraycopy
in illegalCheck.
Upvotes: 1