0

I'm writing a console Boggle game and the gameLoop logic isn't quite what I think it should be.

My basic game loop method is:

    public void gameStart() {
        timer.schedule(new BoggleTimerTask(1),0);
        gameActive = true;
        System.out.println(boggle.getBoggleTrayAsString());
        while (gameActive) {
            String word = scanner.next();
            boggle.addGuess(word);
        }
        scanner.close();
        timer.cancel();
        postGame();
    }

My timer task class run method looks like this:

    public void run() {
        if (minutesRemaining == 4 || minutesRemaining == 3 || 
                minutesRemaining == 2)
            minutesRemaining--;
        else if (minutesRemaining == 1 || minutesRemaining == .5)
            minutesRemaining -= .5;
        if (minutesRemaining == 3) {
            System.out.println("3 minutes remaining.");
            timer.schedule(new BoggleTimerTask(minutesRemaining),60000);
        }
        else if (minutesRemaining == 2) {
            System.out.println("2 minutes remaining.");
            timer.schedule(new BoggleTimerTask(minutesRemaining),60000);
        }
        else if (minutesRemaining == 1) {
            System.out.println("1 minute remaining.");
            timer.schedule(new BoggleTimerTask(minutesRemaining),
                    30000);
        }
        else if (minutesRemaining == .5) {
            System.out.println("30 seconds remaining.");
            timer.schedule(new BoggleTimerTask(minutesRemaining),
                    30000);
        }
        else {
            System.out.println("Time's Up!");
            gameActive = false;
        }

The timer counts down exactly as I think it should. "Time's Up!" prints out as well, however postGame() is never called. I initially thought that the issue was the main thread waiting on scanner.next() so I found a solution using the Robot class and calling a key press and key release with VK_ENTER and that did not work.

I then tried adding a check on word in the gameLoop. I added the check if (word.compareTo("quit") == 0) gameActive = false. That does call postGame() both when I personally enter quit as a word or when I spell out quit and enter with the Robot.

So I've surmised this much: the gameLoop does terminate and send the program to postGame() when gameActive = false and "Time's Up!" is printing so the last else block is catching appropriately in the timer. Why those two don't work in conjunction to execute properly (or at least how I think it SHOULD execute) I don't know.

Any help someone could provide would be greatly appreciated. Thanks in advance.

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
Jeff D
  • 1
  • 3

1 Answers1

0

I think you need to have two threads running to do something like this (better than robot).

public static void main(String[] args) {
    new Thread() {
        public void run() {
            while(true) {
                String input = new Scanner(System.in).nextLine();
                doSomethingWithInput(input);
            }
        }
    }.start();
    new Thread() {
        public void run() {
            int time = 4;
            while(time > 0) {
                System.out.println(time + " seconds left.");
                printGameBoard();
                time--;
                Thread.sleep(1000);                    
            }
            printScore();
            System.exit(0);
        }
    }.start();
}

Just define the functions and you have your game.

Logan Murphy
  • 6,120
  • 3
  • 24
  • 42
  • Thanks for the advice Logan. I'll try your method and see if I can get it to work. – Jeff D Aug 01 '13 at 14:45
  • The program will essentially give the user 4 one second sleeps (In other words 4 seconds to complete the game). It is much less demanding than constantly running the program and testing if a second passed by. – Logan Murphy Aug 01 '13 at 14:47
  • Sorry for the silly question about thread sleeping. I see now that is obviously how you're replicating the timer. Thank you very much for your suggestion Logan. I worked on it this morning and got it to work with your method (dual thread) and after messing around with your method got it to work my original way (thread and timer). Thanks a lot for your help Logan! – Jeff D Aug 01 '13 at 15:55
  • Logan if you, or anyone else, are still checking this question, could you please tell me why my original code wasn't working? I've had some difficulties in multi-threading and it must be because there is something happening I'm unaware of or something to it I don't fully understand. – Jeff D Aug 02 '13 at 18:51
  • So I actually figured out what I had done wrong Logan. You're right. Without any Robot use even when gameActive is set to false it will wait for user input before checking the while condition again. I had actually waited on gameActive in an empty while loop in my main thread, had a separate timer thread, and spawned a third thread to read user input. I found out the hard way that any empty while loop (such as I had in my main thread) will NOT recheck its while condition. – Jeff D Aug 05 '13 at 19:16
  • I made it unnecessarily difficult, mostly on purpose, because I wanted to make sure I understood what was going on with multithreading. The 3 threaded approach I just described wasn't the code I posted which you helped me solve...that was the 2 thread approach. In any event, due in large to your help, I was able to understand both the 2 and 3 threaded approaches and got them working correctly. – Jeff D Aug 05 '13 at 19:22
  • In fact, as far as 2 threads, I got a version working which you suggested in which the timer thread forcibly ended the entire program and also got a version working in which the timer thread used Robot to make the main thread exit the gameLoop and go to postGame(). That method allows for further processing of input (such as play again? y/n). Thanks a bunch for the great help you gave me Logan. – Jeff D Aug 05 '13 at 19:22
  • Excellent, anytime :) – Logan Murphy Aug 06 '13 at 03:43