0

I am in an intro to java class and have we have to create a Mine Sweeper game. I have the game complete for the most part. But I have having 1 issue where my program goes into a crazy infinite loop.

When the user Guesses wrong and hits a "bomb", the game correctly ends. But when they guess correctly and do not hit a bomb, the program enters a infinite loop for some reason and I have to terminate it.

I use 2 2dArrays, one that displays to the player as all '?', and the other that has actual bombs placed on it, that I compare guesses to and update the player board. I feel like the problem is in my GetGuess method. Not sure why this infinite loop only happens the the user makes a correct guess.

The first guess prompt works fine, and if it hits a bomb, the game ends. If the guess is good, the program should ask for another guess, but instead The infinte loop prints:

Enter row number: 
null

over and over again until I terminate. Can anyone help me figure out where this is coming from?

Here is my main and Game class.

public class MineSweeper {

public static void main(String[] args) {

    Game test = new Game();
    test.loadBombs(test.bombBoard);
    test.loadArray(test.board);
    test.loadNumber(test.bombBoard);
    test.displayBoard(test.board);
    test.displayBoard(test.bombBoard);

    while(test.gameOver==false)//Continue to get user guess until win or lose
    {
    test.getGuess(test.board, test.bombBoard);
    test.displayBoard(test.board);
    }

}


public class Game {

int arrayDimension = 9;
char[][] board = new char[arrayDimension][arrayDimension];
char[][] bombBoard = new char[arrayDimension][arrayDimension];
static boolean gameOver;

public static void getGuess(char[][] boardArray,char[][]bombBoard)
{


    int rowGuess = 0, colGuess=0;
    Scanner reader = new Scanner(System.in);

      //Prompt user guess
       boolean valid = false;//Check if guess is valid
       while(valid == false)
       {
      try{
       System.out.println("Enter row number: ");
       rowGuess= reader.nextInt();

       System.out.println("Enter column number: ");
       colGuess = reader.nextInt();

       if((rowGuess<0||rowGuess>8) && (colGuess<0||colGuess>8))//Check if guess is valid
       {
           throw new IndexOutOfBoundsException("This row and column is out of bounds!");
       }
       else if(rowGuess<0 || rowGuess >8)
       {
           throw new InputMismatchException("Invalid Row Choice!");
       }
       else if(colGuess<0 || colGuess >8)
       {
           throw new InputMismatchException("Invalid Column Choice!");
       }
       else{}
       }
       catch(Exception e)
      { System.out.println(e.getMessage());
      }
        if(rowGuess >= 0 && rowGuess<=8) //Guess was valid, place * at location
        {
            if(colGuess >=0 && colGuess<=8)
            {
                boardArray[rowGuess][colGuess]= '*';               
                reader.close();
                valid = true;
            }
        }
       }
       char answer = bombBoard[rowGuess][colGuess];//check bomb board with user guess
       if(answer == '#')//Bomb, you lose
       {
           boardArray[rowGuess][colGuess]= answer;
           System.out.println("You hit a bomb, game over!");
          gameOver = true;       
       }
       else//correct guess, Place number of bombs around guess, continue guessing.
       {
           boardArray[rowGuess][colGuess]= answer;
          gameOver = false;
       }

}
Reeggiie
  • 782
  • 7
  • 16
  • 36

3 Answers3

0

In this part of your code

else//correct guess, Place number of bombs around guess, continue guessing.
   {
     boardArray[rowGuess][colGuess]= answer;
     gameOver = false;
   }

You want something that will set gameOver to be true when the user has found all of the empty spaces. You should use a variable to keep track of the number of correct guesses the player has made, and if this number plus the number of bombs equals the number of tiles on the board then you want game over to be true. This will exit the outer loop in your test runner class.

nmore
  • 2,474
  • 1
  • 14
  • 21
0

Additional to the other answers, I'd like to warn you about this code:

if(colGuess >=0 && colGuess<=8) {
    boardArray[rowGuess][colGuess]= '*';               
    reader.close(); // this line is dangerous
    valid = true;
}

Here you're closing the current InputStream of System.in. The problem with this is, that it cannot be re-opend by simply calling Scanner reader = new Scanner(System.in); on the next getGuess method call. That means you're unable to retrieve more user input and furthermore a method call on reader can cause a NoSuchElementException.

To fix this, move the Scanner reader variable to the class fields:

public class Game {
    // ... other fields
    Scanner reader = new Scanner(System.in);

and create a new method that will close this resource if the game is over:

public void finishGame() {
    // do other stuff to close the game
    reader.close();
}

You can call this method like this:

while(test.gameOver==false)//Continue to get user guess until win or lose
{
    test.getGuess(test.board, test.bombBoard);
    test.displayBoard(test.board);
}
test.finishGame(); // Game is over, close all resources
Tom
  • 16,842
  • 17
  • 45
  • 54
  • Your exactly right. I used this implementation for scanner and it works now. I did not know scanner could not be reopened like I was doing. – Reeggiie Nov 10 '14 at 01:14
  • @Reeggiie It depends on the used resource. A file can be reopend, but not the standard system input, that uses the console. You could try to create a new `InputStream` and set it to `System.in` using `System.setIn(inputStream)`, but it is much easier to avoid closing it too early :D. – Tom Nov 10 '14 at 04:41
0

Infinite loops mostly happen if you try to read a closed scanner. I would also suggest you keep a refence of it as an object variable or at least in your main function:

Scanner reader = new Scanner(System.in);
Game test = new Game();
test.loadBombs(test.bombBoard);
test.loadArray(test.board);
test.loadNumber(test.bombBoard);
test.displayBoard(test.board);
test.displayBoard(test.bombBoard);

Hope it helps.

lenhuy2106
  • 313
  • 3
  • 8