Solved

How to undo a move played on a board game

Posted on 2011-09-26
8
74 Views
Last Modified: 2015-09-23
Hi Experts,

This is a kind of follow up question from my previous one(Q_27326449.html)...
I am writing a Connect-4, 6*7 board game.
Every time a player makes a move, I store that move in an instance of the GameStack class that I have written.
I want to be able to allow undo / redo operation by popping from stackA and pushing into stackB, (i.e for undo)  and popping from stackB for redo.

I am getting the following error messages:

[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
A      B      C      D      E      F      G      
player's color: Red
move#: 0
f([ O ]), please type your move:  
e
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ O ]      [ _ ]      [ _ ]       
A      B      C      D      E      F      G      
player's color: Blue
move#: 1
h([ X ]), please type your move:  
b
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]      [ _ ]       
[ _ ]      [ X ]      [ _ ]      [ _ ]      [ O ]      [ _ ]      [ _ ]       
A      B      C      D      E      F      G      
player's color: Red
move#: 2
f([ O ]), please type your move:  
u
Exception in thread "main" java.lang.NullPointerException
      at org.c4.code.GameStack.performPop(GameStack.java:20)
      at org.c4.code.GameModel.undo(GameModel.java:513)
      at org.c4.code.Main.placePieceOnBoard(Main.java:160)
      at org.c4.code.Main.startGame(Main.java:62)
      at org.c4.code.Main.main(Main.java:27)

Pointing at the line :
Point point = (Point) stack.pop;  in the GameStack class.
Is this a good way to approach this at all?
GameStack.java file has been uploaded in the previous mentioned post.
I am not sure if I should resubmit it with this post.
Thanks.
0
Comment
Question by:Smanyx
  • 6
  • 2
8 Comments
 
LVL 47

Accepted Solution

by:
for_yan earned 500 total points
ID: 36597585
Just be simpler - store all your moves in the ArrayList - and you'll be able to undo them one by one very easily
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36597611

What is the point to do it recursively like that?
Sure it will get nullpointer exception

	static Point performPop(Stack stack)
	{
		Point point = (Point)stack.pop();
		try
		{
			performPop(stack);
		}
		catch (EmptyStackException e)
		{
			
		}
		return point;
	}

Open in new window

0
 

Author Comment

by:Smanyx
ID: 36597665
>> Just be simpler - store all your moves in the ArrayList
Thanks, I keep it in mind and will try to do it.

But just for the sake of learning, how would I accomplish the same with stack data-structure?
I have never used a stack before but I thought it could be a good idea to use it here.
And obviously, I am clumsy using it, thus your remark:
>>  What is the point to do it recursively like that?
     Sure it will get nullpointer exception

It's only in trying to use it that I can understand the best way to work with it. Talking about Stack.
I projected that the question would allow me to understand lots, thus the 500pts assigned to it.
I realize  that I don't know and I want to learn...
Thanks.
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36597730


I'd thisn you do something like that:

if(!stack.empty()) stack.pop();
else
System.out.println("no more moves to undo!");

Although I'm not sure how would you do it with the stack.

If you have all your moves in ArrayList - you can esili gothrough this array list and draw your current position of elements.
You ca easily write such method.
So when you want to undo you remove las element and call this method to draw your positions again
Very simple and convenient



0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 47

Expert Comment

by:for_yan
ID: 36597890
You can also use LinkedList instead of ArrayList - this collection has even method removeLast()

0
 

Author Comment

by:Smanyx
ID: 36598595
Whether I use an ArrayList or a LinkedList, should I save the move as a point-coordinates, right!?
Because, I can do something like, arrayList.add(pRow, pCol) but when I want to use it ...

 >> If you have all your moves in ArrayList - you can esili gothrough this array list and draw your current position of elements.
I am a bit confused here, 'coz if I draw from the ArrayList, this structure only contains the moves made, I still need to draw the board with empty space where no move has been played...

Looking at my printBoard() method:

public static void printBoard()
      {
            int currentColumn = 1;
            
            for (int mRow = (GameModel.BOARD_HEIGHT); mRow > 0; mRow--)
            {
                  /*
                   * printing the leading row number
                   */
//                  if (mRow < (GameModel.BOARD_HEIGHT + 1))
//                  {
////                        System.out.print((mRow - 1) + ". ");
//                        System.out.print((mRow - 1));
//                  }

                  for (int mCol = 0; mCol < (GameModel.BOARD_WIDTH); mCol++)
                  {
                        int [][] board = game.getBoard();
                        
                        if (mRow != GameModel.BOARD_WIDTH)
                        {
                              System.out.print(convertBoard(board[mRow - 1][mCol]) + "\t");
                        }
                  }
                  System.out.println(" ");
            }
            
            // print each column name
            for (int i = 0; i < (GameModel.BOARD_WIDTH + 1); i++)
            {
                  switch(currentColumn)
                  {
                        case 1:
                              System.out.print('A' + "\t");
                              break;
                        case 2:
                              System.out.print('B' + "\t");
                              break;
                        case 3:
                              System.out.print('C' + "\t");
                              break;
                        case 4:
                              System.out.print('D' + "\t");
                              break;
                        case 5:
                              System.out.print('E' + "\t");
                              break;
                        case 6:
                              System.out.print('F' + "\t");
                              break;
                        case 7:
                              System.out.print('G' + "\t");
                              break;
                  }
                  currentColumn++;
            }
            System.out.println("");
            int x = game.getCurrentPlayer();
            //String playerColor = "";
            switch(x)
            {
                  case 0:
                        playerColor = "Red";
                        break;
                  case 1:
                        playerColor = "Blue";
                        break;
            
            }
            
            System.out.println("player's color: " + playerColor);
            System.out.println("move#: " + game.getMoveNumber());
          System.out.println(returnPlayerName() + "(" + convertBoard(game.getCurrentPlayer()) + ")" + ", please type your move:  ");
      }

Could you lead me to a better understanding of how to implement this all undo/redo thing? Especially how to redraw the screen after undo and/or redo? I am thinking of using two ArrayLists one for undo and the other for redo. Am I on the right track?
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36598991
No you don't need two arraylists.
Just one which will have all the moves in the order they were made. The empty screen is always drawn the same way - you don't need to keep any additional information to draw it. So you make a sepratae method - which will first draw empty table and then add aLl the moves, exactly as you did before when the play was happening with the difference that you don't need to stop and ask the user for the next move, but rather take the move from the ArrayList . Yuoi pro baby don't need to test if it was a win in between also.
Also keep in mind that you can't keep juist two strings as one element of arraylist - you should have one objeect as each element - say yoir Point obect would be OK. Your poicture is the function of a sequence of moves - so you don't need two arrayLists at leat for undo option. If you want to be able to do redo, then you may want to keep temporary list if tgose which you removed to pull them out of it for redo. Another option will be kust to maintain the instance variabe - thre number okf moves to draw. This number would be equaal to number of moves and to zise of your arraylist b y default , but when you make uindo - you'l reduce this number by one for each undo, when youmake redio - just increase this numb er by one. So once you hjave this numbeer as a oparrameter of the method which redraws youur picture - that would be fine. Then you can also have option redoAll - the you'll set this parameter to the size of oiur arraylist
0
 
LVL 47

Expert Comment

by:for_yan
ID: 36599331
If I were you, I'd rather make this the basic methid of your application. This method will take two parameters - arraylist which contains moves as they were entered by the user (arrayList of Strings as user entered them - you have one letter strings as I understand) and the integer value which normall would be less than equal to the size of the arraylist. And in the body of this method - you'll traverse the list up to the elemnt specified by the integer - and process the moves the way you process them now.
Given the fact that on the board 6 by 7 the speed is not essential - you can use this method even in your normal play operations - just add tghe each move of the user to the arraylist,incvrease the integer - in normal play the intger will be always equal to the arraylist size - and replay all moves. It will be a little bit slower, than to handle last move onlyu - but no one can notice it on the 6 by 7 board.
And when you need undo-redo - it will be just a matter of chjanging this controlling integer.
Well, any of these designswith arraylist  would be fine. Of course if you move to some huige tables and long winning rows then time will become a factor and you don't want to replay all the moves all the time.
 
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now