Connect 4 right to left diagonal check - java
There's probably a very simple solution to this but I can't figure out where I'm doing something wrong. I'm making a small game with android studio that is connect 4. There is a 5x7 matrix of single cells, and 5 imageviews above that when clicked on put a fiche in the right place. Up to this point it's all working fine. When I however have to check if someone won, I thought I could break up the process in 4 main functions: one that check horizontally, one vertically, one diagonally left to right and one diagonally right to left. Now they all work perfectly except the right to left one. I'll post the code below:
private void checkRightLeftDiagonally() {
int winCondition = 0;
boolean goingRight = true;
int y = 1;
int i = 4;
int j = 0;
while (y < 6 && won == false) {
while (i > 0 && j < 7 && won == false) {
if (cells[j][i].getFull() == true && players[playerTurn].getFicheColor() == cells[j][i].getFicheColor()) {
winCondition++;
winningCells.add(cells[j][i]);
} else {
winCondition = 0;
winningCells.clear();
}
if (winCondition == 4) {
won = true;
for (int x = 0; x < 4; x++) {
winningCells.get(x).won();
}
}
i--;
j++;
}
if(goingRight == true)
{
if(y<=4)
{
i=4-y;
j=0;
y++;
}
else
{
goingRight = false;
y=0;
i=0;
j=0+y;
}
}
if(goingRight == false)
{
i=0;
j=0+y;
y++;
}
if(won == false)
{
winCondition = 0;
winningCells.clear();
}
}
if(won == false) {
winCondition = 0;
winningCells.clear();
}
}
And here is one of the arrow imageview code:
imgArrows[0].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(cells[0][0].getFull() == false && won == false)
{
int i = 0;
while(cells[i][0].getFull() == false)
{
i++;
if(i>6) break;
}
i--;
cells[i][0].ficheDown(players[playerTurn]);
checkVertically();
checkHorizantally();
checkLeftRightDiagonally();
checkRightLeftDiagonally();
playerTurn++;
if(playerTurn==2)
{
playerTurn = 0;
}
}
}
});
I've also made the cell class, which is here if it could help you
public class Cell {
private boolean full;
private Player.FicheColor ficheColor;
private ImageView fiche;
public Cell(Player currentPlayer, ImageView img)
{
full = false;
ficheColor = currentPlayer.getFicheColor();
fiche = img;
img.setAlpha(0f);
}
public void ficheDown(Player currentPlayer)
{
full = true;
ficheColor = currentPlayer.getFicheColor();
switch(ficheColor)
{
case red:
fiche.setImageResource(R.drawable.redfiche);
break;
case blue:
fiche.setImageResource(R.drawable.bluefiche);
break;
case green:
fiche.setImageResource(R.drawable.greenfiche);
break;
case white:
fiche.setImageResource(R.drawable.whitefiche);
break;
case black:
fiche.setImageResource(R.drawable.whitefiche);
break;
}
fiche.setAlpha(1f);
}
public Player.FicheColor getFicheColor()
{
return ficheColor;
}
public boolean getFull()
{
return full;
}
public void won(){
fiche.setColorFilter(Color.GREEN);
}
public void reset()
{
fiche.clearColorFilter();
}
}
Thank a lot, even just for reading
In the end the problem was that in the first paragraph of code the int i needed to be set to 4 and that solved it. Thanks to everyone that tried to help me
Related
Peg solitaire solution change destination
I wrote a program that solves a peg solitaire in java. My program gets a starting board and a destination board and try to finish the game. I have a sort of counter that count my turn because I have a destination with more the 1 peg rest and as assume that if I have to remove only 2 pegs so I can solve it in only 2 moves. I have an board class that I create: public class Board { private int board[][] = new int[7][7]; public Board(String place) { board[0][0]=2; board[1][0]=2; board[5][0]=2; board[6][0]=2; board[0][1]=2; board[1][1]=2; board[5][1]=2; board[6][1]=2; board[0][5]=2; board[1][5]=2; board[5][5]=2; board[6][5]=2; board[0][6]=2; board[1][6]=2; board[5][6]=2; board[6][6]=2; int loca=0;//location on the string of place for(int i=0;i<7;i++){ for(int j=0;j<7;j++){ if(board[i][j]!=2) { if (place.charAt(loca) == 'O') { loca++; board[i][j] = 1; } else if (place.charAt(loca) == '.') { loca++; board[i][j] = 0; } } System.out.print(board[i][j]);//print for test } System.out.println();//print for test } System.out.println(); } public Board(Board copy){ for(int i=0;i<7;i++) { for(int j=0;j<7;j++) { board[i][j]=copy.getValue(i,j); } } } public int getValue(int x, int y) { return board[x][y]; } public boolean isFinished(Board destination) { for(int i=0;i<7;i++) { for(int j=0;j<7;j++) { if(this.getValue(i,j)!=destination.getValue(i,j)) { return false; } } } return true; } public Board turn(Board board,String direction,int x,int y) { if(direction.equals("right")) { board.setValue(x,y,0); board.setValue(x+1,y,0); board.setValue(x+2,y,1); return board; } else if(direction.equals("left")) { board.setValue(x,y,0); board.setValue(x-1,y,0); board.setValue(x-2,y,1); return board; } else if(direction.equals("up")) { board.setValue(x,y,0); board.setValue(x,y-1,0); board.setValue(x,y-2,1); return board; } else if(direction.equals("down")) { board.setValue(x,y,0); board.setValue(x,y+1,0); board.setValue(x,y+2,1); return board; } else{ System.out.println("there is not such direction, method turn on board class"); return null;//just for caution } } public boolean isLegal(int x, int y){ if(board[x][y]==2) { return false; } else{ return true; } } public boolean canTurn(String direction,int x,int y){ if(direction.equals("right")) { if(x<5) { if (board[x][y] == 1 && board[x + 1][y] == 1 && board[x + 2][y] == 0) { return true; } } } else if(direction.equals("left")) { if(x>1) { if (board[x][y] == 1 && board[x - 1][y] == 1 && board[x - 2][y] == 0) { return true; } } } else if(direction.equals("up")) { if(y>1) { if (board[x][y] == 1 && board[x][y - 1] == 1 && board[x][y - 2] == 0) { return true; } } } else if(direction.equals("down")) { if(y<5) { if (board[x][y] == 1 && board[x][y + 1] == 1 && board[x][y + 2] == 0) { return true; } } } else{ System.out.println("there is not such direction, method canTurn on board class"); return false;//just for caution } return false; } public void setValue(int x, int y, int value) { board[x][y]=value; } } and I wrote my "solver" class. public class PegSolver { public int peg =1; Board destinationBoard = new Board("OOOOOOOOOOOOOOOOO..OOOOOOOOOOOOOO"); Board board = new Board("OOOOOOOOOOOOOOOO.OOOOOOOOOOOOOOOO"); public void start(){ solve(0,board); } public boolean solve(int turn, Board board){ Board temp = new Board(board); if(turn>peg) { return false; } else if(turn==peg){ //todo:check if solve if(temp.isFinished(destinationBoard)) { System.out.println("solution"); return true; } else { return false; } } else//lower then 8 { for(int i=0;i<7;i++){ for (int j=0;j<7;j++) { if(board.isLegal(i,j)) { if(board.canTurn("right",i,j) && solve(turn++, temp.turn(temp, "right", i, j))) { return true; } else if(board.canTurn("left",i,j) && solve(turn++, temp.turn(temp, "left", i, j))) { return true; } else if(board.canTurn("up",i,j) && solve(turn++, temp.turn(temp, "up", i, j))) { return true; } else if(board.canTurn("down",i,j) && solve(turn++, temp.turn(temp, "down", i, j))) { return true; } } } } } return false; } } When the program finds a solution, it needs to print "solution" but for some reason my program can't find a solution even when it's a basic destination with one move. Can someone help me please?
Please review the modified code. Many of the changes are related to indices and directions inconsistency across the code: where x represents horizontal index and y represents vertical index: array index should be board[y][x] (and not board[x][y]). Many "magic numbers" were changed to constants for better readability of the code. A toString method was added to the Boardclass to print out a board state. It uses special characters to make a nice printout : This is helpful when debugging. public class PegSolver { private final Board startBoard, destinationBoard; public PegSolver(Board startBoard, Board destinationBoard) { super(); this.startBoard = startBoard; this.destinationBoard = destinationBoard; } public void start(){ solve(0,startBoard); } private boolean solve(int turn, Board board){ //check if solve if(board.isFinished(destinationBoard)) { System.out.println("solved after "+ turn +" turns"); return true; } for(int x=0;x<board.boardSize();x++){ for (int y=0;y<board.boardSize();y++) { if(board.isLegal(x,y)) { if(board.canTurn("right",x,y) //turn++ changed to turn+1 so turn is incremented before invoking next solve //and avoid changing the value of turn && solve(turn+1, board.turn(new Board(board), "right", x, y))) return true; else if(board.canTurn("left",x,y) && solve(turn+1, board.turn(new Board(board), "left", x, y))) return true; else if(board.canTurn("up",x,y) && solve(turn+1, board.turn(new Board(board), "up", x, y))) return true; else if(board.canTurn("down",x,y) && solve(turn+1, board.turn(new Board(board), "down", x, y))) return true; } } } return false; } public static void main(String[] args) { Board[] destinationBoards = { //by order of number of turns new Board("OOOOOOOOOOOOOO..OOOOOOOOOOOOOOOOO"), //one right turn new Board("OOO.OOOO.OOOOO.OOOOOOOOOOOOOOOOOO"), //right, down new Board("OOO.OO..OOOOOO.OOOOOOOOOOOOOOOOOO"), //right, down,right new Board("OOO.OOO.OOOOO..OOOOO.OOOOOOOOOOOO"), //right, down,right,up new Board("OOOOOOO..OOOO...OOOO.OOOOOOOOOOOO"), //right, down,right,up,up new Board(".OO.OOO.OOOOO...OOOO.OOOOOOOOOOOO"), //right, down,right,up,up,down new Board(".OO.OOO.OOOOO...OOOOO..OOOOOOOOOO"), //right, down,right,up,up,down, left new Board(".OO.OOO.OOOOO...OOOOO.OOOOO.OO.OO"), //right, down,right,up,up,down,left,up new Board(".OO.OO..O.OOO...OOOOO.OOOOO.OO.OO"), //10 turns new Board("..O..O.O..OOO...OOOO..OOOOO..O..O"), //15 turns new Board(".........O................O......"), //30 turns new Board("...................O............."), //31 turns }; Board startBoard = new Board("OOOOOOOOOOOOOOOO.OOOOOOOOOOOOOOOO"); for(Board destinationBoard : destinationBoards ){ new PegSolver(startBoard, destinationBoard).start(); } } } class Board { //int representation of the three states of a board cell private final static int EMPTY = 0, PEG = 1, BORDER = 2; /*cahr representation of the three states of a board cell special chars are used to get nice printout todo: change board to char[][] to avoid the need for two representations (int and char) */ private final static char[] CHAR_REPRESENTATION = {9898,9899,10062}; private final static char ERROR = '?'; private final int BOARD_SIZE=7, CORNER_SIZE=2; private final int board[][] = new int[BOARD_SIZE][BOARD_SIZE]; public Board(String place) { int loca=0; for(int y=0;y<BOARD_SIZE;y++){ for(int x=0;x<BOARD_SIZE;x++){ if(isWithinBoard(x,y)) { if (place.charAt(loca) == 'O') { loca++; board[y][x] = PEG; } else if (place.charAt(loca) == '.') { loca++; board[y][x] = EMPTY; } }else{ board[y][x] = BORDER; } } } //for testing //System.out.println(this); } //copy constructor public Board(Board copy){ for(int x=0;x<BOARD_SIZE;x++) { for(int y=0;y<BOARD_SIZE;y++) { board[y][x]=copy.getValue(x,y); } } } public int getValue(int x, int y) { return board[y][x]; //and not return board[x][y]; } public boolean isFinished(Board destination) { for(int i=0;i<BOARD_SIZE;i++) { for(int j=0;j<BOARD_SIZE;j++) { if(this.getValue(i,j)!=destination.getValue(i,j)) return false; } } return true; } public Board turn(Board board,String direction,int x,int y) { if(direction.equals("right")) { board.setValue(x,y,EMPTY); board.setValue(x+1,y,EMPTY); board.setValue(x+2,y,PEG); return board; } else if(direction.equals("left")) { board.setValue(x,y,EMPTY); board.setValue(x-1,y,EMPTY); board.setValue(x-2,y,PEG); return board; } else if(direction.equals("up")) { board.setValue(x,y,EMPTY); board.setValue(x,y-1,EMPTY); board.setValue(x,y-2,PEG); return board; } else if(direction.equals("down")) { board.setValue(x,y,EMPTY); board.setValue(x,y+1,EMPTY); board.setValue(x,y+2,PEG); return board; } System.out.println("there is not such direction, method turn on startBoard class"); return null; } public boolean isLegal(int x, int y){ if(board[y][x]==BORDER) //and not if(board[x][y]==BORDER) return false; return true; } public boolean canTurn(String direction,int x,int y){ if(direction.equals("right") && x < BOARD_SIZE - 2) { if (board[y][x] == PEG && board[y][x + 1] == PEG && board[y][x + 2] == EMPTY) return true; } else if(direction.equals("left") && x > 1) { if (board[y][x] == PEG && board[y][x - 1] == PEG && board[y][x - 2] == EMPTY) return true; } else if(direction.equals("up") && y > 1) { if (board[y][x] == PEG && board[y - 1][x] == PEG && board[y - 2][x] == EMPTY) return true; } else if(direction.equals("down") && y < BOARD_SIZE - 2) { if (board[y][x] == PEG && board[y + 1][x] == PEG && board[y + 2][x] == EMPTY) return true; } return false; } public void setValue(int x, int y, int value) { board[y][x]=value; //and not board[x][y]=value; } //for square nxn board public int boardSize(){ return board.length; } public boolean isWithinBoard(int x, int y){ //check bounds if (x < 0 || y < 0 || x >= BOARD_SIZE || y >= BOARD_SIZE) return false; //left top corner if (x < CORNER_SIZE && y < CORNER_SIZE) return false; //right top corner if(x >= BOARD_SIZE - CORNER_SIZE && y < CORNER_SIZE) return false; //left bottom corner if(x < CORNER_SIZE && y >= BOARD_SIZE - CORNER_SIZE) return false; //right bottom corner if(x >= BOARD_SIZE - CORNER_SIZE && y >= BOARD_SIZE - CORNER_SIZE) return false; return true; } #Override public String toString() { StringBuilder sb = new StringBuilder(); for (int[] row : board) { for(int cell : row){ if(cell<CHAR_REPRESENTATION.length && cell >= 0) { sb.append(CHAR_REPRESENTATION[cell]); }else{ sb.append(ERROR); } } sb.append("\n"); //new line } return sb.toString(); } } Todo: The code is working but it needs further in-depth testing and debugging. If something is not clear, don't hesitate to ask.
Java maze won't print
I have to make a maze for a java assignment, and I was able to finish most of it. I was provided with an outline of the code that had all the methods. Can someone help me? My issue is that the maze wont print out, and I can't figure out why. package maze; public class Maze { private char direction; private int r; // x position of the mouse private int c; //y position of the mouse private boolean exitFound = false; public Maze(int[][] arrMaze) { this.r = arrMaze.length - 1; this.c = 0; } //Prints out the maze without solution public void displayMaze(int[][] arrMaze) { //display the maze putting blank spaces where there are 1's in the array and putting //another symbol where there are 0's to show the maze without the solution for(int i=0; i<arrMaze.length; i++){ System.out.println(" "); for(int j=0; j<arrMaze[i].length; j++){ if(arrMaze[i][j] == 0){ System.out.print("#"); } if(arrMaze[i][j] == 1) { System.out.print(" "); } if(arrMaze[i][j] == 2){ System.out.print("#"); } if(arrMaze[i][j] == 3){ System.out.println("~"); } } } } //displays the Maze with the path taken public void displayPath(int[][] arrMaze) { //show the user how far the mouse has gone since the start. //The path the mouse has gone will be filled in but the path ahead will not. for (int i = 0; i < arrMaze.length; i++) { System.out.println(" "); for (int j = 0; j < arrMaze[i].length; j++) { if (arrMaze[i][j] == 3) { System.out.print("#"); } else if (arrMaze[i][j] == 2) { System.out.print("~"); } else if (arrMaze[i][j] == 0) { System.out.print("#"); } else { } } } } public boolean takeStep(int[][] newMaze) { // moveNorth(newMaze) for (int i = 0; i < newMaze.length; i++) { System.out.println(" "); for (int j = 0; j < newMaze[i].length; j++) { if (newMaze[r][c] == 3) { moveNorth(newMaze); System.out.print("~"); } else if (newMaze[r][c] == 2) { System.out.print("#"); } else { } } } return isAnExit(newMaze); } public void moveNorth(int[][] arrMaze) { //complete the code here /*method will check for a 0 or a 1 in the position above the current position * and then if not a 0 will change the current position to the row above it, but in the same column. */ if (arrMaze[r][c - 1] != 0) { arrMaze[r][c - 1] = 3; arrMaze[r][c + 1] = 2; } else { moveSouth(arrMaze); } displayPath(arrMaze); } public void moveSouth(int[][] arrMaze) { //method will check for a 0 or a 1 in the position below the current position and then if not a 0 //it will change the current position to the row below it, but in the same column. if (arrMaze[r][c + 1] != 0) { arrMaze[r][c + 1] = 3; arrMaze[r][c + 1] = 2; } else { moveNorth(arrMaze); } displayPath(arrMaze); } public void moveEast(int[][] arrMaze) { //method will check for a 0 or a 1 in the position to the right of  the current position and then if //not a 0 will change the current position to the column to the right but the same row. if (arrMaze[r + 1][c] != 0) { arrMaze[r + 1][c] = 3; arrMaze[r - 1][c] = 2; } else { moveWest(arrMaze); } displayPath(arrMaze); } public void moveWest(int[][] arrMaze) { //method will check for a 0 or a 1 in the position to the left of  the current position and then if //not a 0 will change the current position to the column to the left but the same row. if (arrMaze[r - 1][c] != 0) { arrMaze[r - 1][c] = 3; arrMaze[r + 1][c] = 2; } else { } displayPath(arrMaze); } private boolean isAnExit(int[][] arrMaze) { //method will return true if the user arrives into the last column of the array because there is only one //location in the last column that is a 1, so if the user reaches the array[i].length then that means that it found an exit. if (arrMaze[r][c] > arrMaze.length) { exitFound = true; } else { exitFound = false; } return exitFound; } //finds the path without stopping at every step //method will show the complete path from start to finish of the maze and the suggested route to the end. public void findExit(int[][] arrMaze) { if (arrMaze[r][c] > arrMaze.length) { for (int i = 0; i < arrMaze.length; i++) { takeStep(arrMaze); } } } } This is the test code. I was provided the test code, and I haven't changed it. package maze; import java.util.Scanner; public class TestMaze { public static void main(String[] args) { int[][] mazeArray = { {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,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0}, {0,0,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,1}, {0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0}, {0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,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,1,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, {1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0}, {1,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}}; Maze myMaze = new Maze(mazeArray); boolean keepAsking = true; Scanner scan = new Scanner(System.in); String input = ""; myMaze.displayPath(mazeArray); System.out.println("Maze"); do { System.out.println("T = Take a step | S = Show path | Q = Quit"); System.out.print("Enter command: "); input = scan.nextLine(); input.trim(); input.toLowerCase(); if(input.equals("t")) { keepAsking = !myMaze.takeStep(mazeArray); System.out.println("Which direction would you like to go? N, S, E, W?"); String direction = scan.nextLine(); if(direction.equalsIgnoreCase("n")) myMaze.moveNorth(mazeArray); if(direction.equalsIgnoreCase("s")) myMaze.moveSouth(mazeArray); if(direction.equalsIgnoreCase("e")) myMaze.moveEast(mazeArray); if(direction.equalsIgnoreCase("w")) myMaze.moveWest(mazeArray); } else if(input.equals("s")) { myMaze.findExit(mazeArray); keepAsking = false; } else if(input.equals("q")) { keepAsking = false; } else { System.out.println("ERR: Invalid input"); } } while(keepAsking); System.out.println("Quitting program..."); scan.close(); } }
You need to call displayMaze() (in displayPath()) to print it. Currently, you're not calling the method, meaning that your code will never print the maze as it's no being instructed to. Also, where are you assigning values to r and c? I think you meant to use i and j in your displayPath() method ([i][j] instead of [r][c]).
I imagine you're throwing an error somewhere because your r and c values are undefined everywhere they are used. Try adding code to initialize and update these values, then you should see your maze print.
Array of Characters not updated properly java
I am trying to make pong in a terminal on windows in java. I have an array of characters (called board) and the paddle positions are updated by the following code public void movePaddles() { int inp = 0; try { inp = System.in.read(); } catch(Exception e) { return; } int olr = rtop; int oll = ltop; switch(inp) { case 'w': ltop -=1; break; case 's': ltop += 1; break; case 'i': rtop -= 1; break; case 'k': rtop += 1; break; } updatePaddle('L',oll); updatePaddle('R',olr); } public void updatePaddle(char side,int oldtop) { int edge = 0; int top = 0; // Leave 1 char of space if (side == 'L') { edge = 1; top = ltop; } else if (side == 'R') { edge = y-2; top = rtop; } for (int i = oldtop;i < paddleSize+1;i++) { board[i][edge] = ' '; } for (int i = top;i < paddleSize+2;i++) { board[i][edge] = paddleChar; } } What ends up happening is that the paddles disappear when moving down, making the game unplayable. What am I doing wrong? (full code on github at https://github.com/Tookmund/Text-Pong)
I did try debugging my program before I posted my question but not properly it appears. Basically I needed to add the value of the current location (top/oldtop) so that the loop would not exit prematurely because i was initially bigger that the paddleSize.
java.lang.reflect.InvocationTargetException error
I am working on a robot maze where the robot finds the target without bumping into walls. As a "backtrack" method, I need the robot to go in the opposite direction as it did when it first came across a junction. This is my code: import uk.ac.warwick.dcs.maze.logic.IRobot; import java.util.ArrayList; import java.util.*; import java.util.Iterator; public class Explorer { private int pollRun = 0; // Incremented after each pass. private RobotData robotData; // Data store for junctions. private ArrayList<Integer> nonWallDirections; private ArrayList<Integer> passageDirections; private ArrayList<Integer> beenbeforeDirections; private Random random = new Random(); int [] directions = {IRobot.AHEAD, IRobot.LEFT, IRobot.RIGHT, IRobot.BEHIND}; public void controlRobot (IRobot robot) { // On the first move of the first run of a new maze. if ((robot.getRuns() == 0) && (pollRun ==0)) robotData = new RobotData(); pollRun++; /* Increment poll run so that the data is not reset each time the robot moves. */ int exits = nonwallExits(robot); int direction; nonWallDirections = new ArrayList<Integer>(); passageDirections = new ArrayList<Integer>(); beenbeforeDirections = new ArrayList<Integer>(); // Adding each direction to the appropriate state ArrayList. for(int item : directions) { if(robot.look(item) != IRobot.WALL) { nonWallDirections.add(item); } } for(int item : directions) { if(robot.look(item) == IRobot.PASSAGE) { passageDirections.add(item); } } for(int item : directions) { if(robot.look(item) == IRobot.BEENBEFORE) { beenbeforeDirections.add(item); } } // Calling the appropriate method depending on the number of exits. if (exits < 2) { direction = deadEnd(robot); } else if (exits == 2) { direction = corridor(robot); } else { direction = junction(robot); robotData.addJunction(robot); robotData.printJunction(robot); } robot.face(direction); } /* The specification advised to have to seperate controls: Explorer and Backtrack and a variable explorerMode to switch between them. Instead, whenever needed I shall call this backtrack method. If at a junction, the robot will head back the junction as to when it first approached it. When at a deadend or corridor, it will follow the beenbefore squares until it reaches an unexplored path. */ public int backtrack (IRobot robot) { if (nonwallExits(robot) > 2) { return robotData.reverseHeading(robot); } else { do { return nonWallDirections.get(0); } while (nonwallExits(robot) == 1); } } // Deadend method makes the robot follow the only nonwall exit. public int deadEnd (IRobot robot) { return backtrack(robot); } /* Corridor method will make the robot follow the one and only passage. The exception is at the start. Sometimes, the robot will start with two passages available to it in which case it will choose one randomly. If there is no passage, it will follow the beenbefore squares until it reaches an unexplored path.*/ public int corridor (IRobot robot) { if (passageExits(robot) == 1) { return passageDirections.get(0); } else if (passageExits(robot) == 2) { int randomPassage = random.nextInt(passageDirections.size()); return passageDirections.get(randomPassage); } else { return backtrack(robot); } } /* Junction method states if there is more than one passage, it will randomly select one. This applies to crossroads as well as essentially they are the same. If there is no passage, it will follow the beenbefore squares until it reaches an unexplored path. */ public int junction(IRobot robot) { if (passageExits(robot) == 1) { return passageDirections.get(0); } else if (passageExits(robot) > 1) { int randomPassage = random.nextInt(passageDirections.size()); return passageDirections.get(randomPassage); } else { return backtrack(robot); } } // Calculates number of exits. private int nonwallExits (IRobot robot) { int nonwallExits = 0; for(int item : directions) { if(robot.look(item) != IRobot.WALL) { nonwallExits++; } } return nonwallExits; } // Calculates number of passages. private int passageExits (IRobot robot) { int passageExits = 0; for(int item : directions) { if(robot.look(item) == IRobot.PASSAGE) { passageExits++; } } return passageExits; } // Calculates number of beenbefores. private int beenbeforeExits (IRobot robot) { int beenbeforeExits = 0; for(int item : directions) { if(robot.look(item) == IRobot.PASSAGE) { beenbeforeExits++; } } return beenbeforeExits; } // Resets Junction Counter in RobotData class. public int reset() { return robotData.resetJunctionCounter(); } } class RobotData { /* It was advised in the specification to include the variable: private static int maxJunctions = 10000; However, as I am not using arrays, but ArrayLists, I do not need this. */ private static int junctionCounter = 0; private ArrayList<Junction> junctionList = new ArrayList<Junction>(); private Iterator<Junction> junctionIterator = junctionList.iterator(); // Resets the Junction counter. public int resetJunctionCounter() { return junctionCounter = 0; } // Adds the current junction to the list of arrays. public void addJunction(IRobot robot) { Junction newJunction = new Junction(robot.getLocation().x, robot.getLocation().y, robot.getHeading()); junctionList.add(newJunction); junctionCounter++; } // Gets the junction counter for Junction info method in Junction class. public int getJunctionCounter (IRobot robot) { return junctionCounter; } // Prints Junction info. public void printJunction(IRobot robot) { String course = ""; switch (robot.getHeading()) { case IRobot.NORTH: course = "NORTH"; break; case IRobot.EAST: course = "EAST"; break; case IRobot.SOUTH: course = "SOUTH"; break; case IRobot.WEST: course = "WEST"; break; } System.out.println("Junction " + junctionCounter + " (x=" + robot.getLocation().x + ", y=" + robot.getLocation().y +") heading " + course); } /* Iterates through the junction arrayList to find the heading of the robot when it first approached the junction. */ public int searchJunction(IRobot robot) { Junction currentJunction = junctionIterator.next(); while (junctionIterator.hasNext()) { if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y))) break; } return currentJunction.arrived; } // Returns the reverse of the heading the robot had when first approaching the junction. public int reverseHeading(IRobot robot) { int firstHeading = searchJunction(robot); int reverseHeading = 1; // Random integer to Iniitalise variable. switch (firstHeading) { case IRobot.NORTH: if (robot.getHeading() == IRobot.NORTH) reverseHeading = IRobot.BEHIND; else if (robot.getHeading() == IRobot.EAST) reverseHeading = IRobot.RIGHT; else if (robot.getHeading() == IRobot.SOUTH) reverseHeading = IRobot.AHEAD; else reverseHeading = IRobot.LEFT; break; case IRobot.EAST: if (robot.getHeading() == IRobot.NORTH) reverseHeading = IRobot.LEFT; else if (robot.getHeading() == IRobot.EAST) reverseHeading = IRobot.BEHIND; else if (robot.getHeading() == IRobot.SOUTH) reverseHeading = IRobot.RIGHT; else reverseHeading = IRobot.AHEAD; break; case IRobot.SOUTH: if (robot.getHeading() == IRobot.NORTH) reverseHeading = IRobot.AHEAD; else if (robot.getHeading() == IRobot.EAST) reverseHeading = IRobot.LEFT; else if (robot.getHeading() == IRobot.SOUTH) reverseHeading = IRobot.BEHIND; else reverseHeading = IRobot.RIGHT; break; case IRobot.WEST: if (robot.getHeading() == IRobot.NORTH) reverseHeading = IRobot.RIGHT; else if (robot.getHeading() == IRobot.EAST) reverseHeading = IRobot.AHEAD; else if (robot.getHeading() == IRobot.SOUTH) reverseHeading = IRobot.LEFT; else reverseHeading = IRobot.BEHIND; break; } return reverseHeading; } } class Junction { int x; int y; int arrived; public Junction(int xcoord, int ycoord, int course) { x = xcoord; y = ycoord; arrived = course; } } Whenever it is backtracking and reaches a junction it has already visited, it freezes and this comes up. `java.lang.reflect.InvocationTargetException at sun.reflect.GeneratedMethodAccessor41.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at uk.ac.warwick.dcs.maze.controllers.PolledControllerWrapper.start(PolledControllerWrapper.java:70) at uk.ac.warwick.dcs.maze.logic.ControllerThread.run(ControllerThread.java:46) Caused by: java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) at RobotData.searchJunction(Explorer.java:242) at RobotData.reverseHeading(Explorer.java:255) at Explorer.backtrack(Explorer.java:74) at Explorer.junction(Explorer.java:122) at Explorer.controlRobot(Explorer.java:56) ... 5 more`
I don't think your searchJunction() is right or safe, the ConcurrentModificationException might be thrown due to the incorrect iterator through junctionList . The problem should be more about the iterator rather than reflection. You might try: private Iterator<Junction> junctionIterator = junctionList.iterator(); doesn't make much sense since the list is empty when initialize a RobotData object. Try to move it into searchJunction() Check hasNext() first then invoke next() public int searchJunction(IRobot robot) { Iterator<Junction> junctionIterator = junctionList.iterator(); while (junctionIterator.hasNext()) { Junction currentJunction = junctionIterator.next(); if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y))) break; } return currentJunction.arrived; }
It looks like that issue is in following code - `public int searchJunction(IRobot robot) { Junction currentJunction = junctionIterator.next(); while (junctionIterator.hasNext()) { if ((((currentJunction.x)==(robot.getLocation().x))) && ((currentJunction.y)==(robot.getLocation().y))) break; } return currentJunction.arrived; } You are calling junctionIterator.next() before calling junctionIterator.hasNext(). Iterator specification says that you should call next() only after calling hasNext()
Why do I get "Cannot be Resolved" errors in this code?
I'm trying to check if a move is legal for the game Othello. I'm using a for each loop and once (only once) when I use the variable that it's checking for, it gives me a 'cannot be resolved error'. I have bolded where this occurs. Can anyone help? (Yes I know that the code isn't finished yet, I'm trying to get rid of this error first.) public boolean isLegal(Location loc1) { String currentColor = currentPlayer.getColor(); boolean isLegal = false; int row = loc1.getRow(); int col = loc1.getCol(); if(board.isValid(loc1)) { if(board.get(loc1) == null) { for(Location tempLoc : board.getValidAdjacentLocations(loc1)) { if(!board.get(tempLoc).equals(currentColor)) { int tempRow = tempLoc.getRow(); if((row != tempLoc.getRow()) && (col == tempLoc.getCol())) { //count up column if(**tempLoc.getRow()** < row) { for(int i = row; i > 1;) { Location tempLoc2 = new Location(i-2, col); if(!board.get(tempLoc2).equals(currentColor)) { i--; } else { i=-1; isLegal = true; } } } //count down column else { for(int i = row; i < 6;) { Location tempLoc2 = new Location(i+2, lcol); if(!board.get(tempLoc2).equals(currentColor)) { i++; } else i=9; isLegal = true; } } } else if(col != tempLoc.getCol() && row == tempLoc.getRow()) { //count left/right row if(col > tempLoc.getCol()) { } else } else { //count up/right & down/left diag if(1!=0) { } //count up/left & down/right diag else } } } } } return isLegal; }
The "else" statements without a body at the bottom of your code are confusing the compiler about what counts as inside the loops. If you fix that error, the other one will go away.