1

So I have a chess game. I'm trying to implement a method where the user can undo their last move.

enter image description here

I created the appropriate action listener for the menu option. The action listener sets the game's undo boolean to true.

pseudocode for my game loop:

while (!game end)
{
    if (undo)
    {
        undo the last move
        continue;
    }

    prompt user to input next move

    user inputs move into console

    model, view are updated

}

This logic doesn't work. The only time the game loop will handle undo is after a user has inputted their next move. So.. basically it just undoes the move they just put in. I need it to be so that any time a user clicks undo move on the GUI, the game loop does the stuff in the if statement.

I have a feeling there is a smarter way to handle this.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Collin
  • 1,777
  • 4
  • 26
  • 42
  • 1
    1) For better help sooner, post a [MCTaRE](http://stackoverflow.com/help/mcve) (Minimal Complete Tested and Readable Example). 2) One way to get image(s) for an example is to hot-link to the images seen in [this answer](http://stackoverflow.com/a/19209651/418556). 3) In fact, you might base the MCTaRE on the [Robust, resizable Chess GUI](http://stackoverflow.com/q/21142686/418556). It uses the chess image seen in the 'hot link images' Q&A. – Andrew Thompson Feb 20 '14 at 02:14

5 Answers5

3

It sounds like this stage is blocking your while loops execution

prompt user to input next move

user inputs move into console

I think you need to look into threading, specifically creating separate threads for move input, draw and undo. Or find a way for users to enter their input without it blocking the while loops execution.

Here's a good tutorial on Concurrency http://docs.oracle.com/javase/tutorial/essential/concurrency/

jeff_kile
  • 1,805
  • 16
  • 21
  • I'm thinking just run the game loop in the main thread. then spawn another thread which constantly blocks on `if(undo)`... – Collin Feb 20 '14 at 01:51
2

Without much to go on, I would suggest that you should update the model and view after you undo the last move but before you prompt for the next input...

while (!game end)
{
    if (undo)
    {
        undo the last move
        // Update the mode, view and update to the screen before moving on
        model, view are updated
        continue;
    }

    prompt user to input next move

    user inputs move into console

    model, view are updated

}

Having said that, I agree with jeff_kile, it sounds like you're blocking the Event Dispatching Thread so where...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
2

I think that the simplest solution is to move the undo code out of the game loop. This should be possible as long as you store the game state outside of the game loop itself. (The game loop would be responsible for updating the game state). By moving the undo code out of the game loop, the game loop can be blocked (waiting for next move) but undo will still function when it is called by the menu action handler.

Your code might look something like this:

class RunGame
{
  GameState state;

  void undoButtonPressed() 
  {
    undo the last move in state
  }

  void main() 
  {
    while(!game end)
    {
      prompt user to input next move

      user inputs move into console

      model(state), view are updated
    }
  }
}
mkasberg
  • 16,022
  • 3
  • 42
  • 46
2
while (!game end)

I think the entire problem starts with that line of pseudo-code. The game should be held in a model, the state of the model determines whether it is in mode:

  • USER_PLAY - all movable pieces enabled, once one is selected, possible 'move to' places are enabled.
  • UNDO - all places disabled, game animate in reverse under programmatic control.
  • OPPONENT_MOVE - all places disabled, game controlled by computer or remote user.

In USER_PLAY the GUI would wait for an event on one of the user's pieces and set a MOVE_FROM_CHOSEN in the model, it would then trigger a GUI refresh that would highlight possible moves for the piece. On second event, on one of the possible move to place being selected, it would move the piece, possibly remove a taken piece, and set the state to OPPONENT_PLAY.

At any time a check box (or whatever) can be selected to produce the controls that determine how much of the game to undo. Once those parameters are determined, the model state would be set to UNDO and the parameters (number of moves to unwind) acted on, using a Swing Timer for the animation.

OPPONENT_MOVE might produce a JProgressBar for opponent 'thinking..' then flip to an animated move in the same fashion as the UNDO state.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
1

Basically what's on your todo list:

  1. convert game to be in such a state where you can take a snapshot of the current snapshot of the game and have the ability to change the state of the game to a snapshot
  2. create a stack which you shift an snapshot of the current game state onto, every time a turn is taken. this snapshot is is the exact state of the game at this current time.
  3. to undo a turn, unshift the last snapshot off of the stack and then update the games current state to the first snapshot in the stack (which was the previous turn's state).

If you wanted to you could unshift the turns onto another stack, that way you could add re-do.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Michael Crook
  • 1,520
  • 2
  • 14
  • 37