2

So I have a working game of checkers (or draughts if you prefer), and i am trying to implement a simple undo feature. I store my board in a 2D array and i am trying to use a stack to store the board before the player moves and if undo is selected the board is simply popped from the stack and redrawn.

here's my undo class

class Undo
{
    Stack<string[,]> prevMoves = new Stack<string[,]>();

    public Stack<string[,]> PrevMoves
    {
        get
        {
            return prevMoves;
        }
        set
        {
            prevMoves = value;
        }
    }

    public void AddCurrentBoardState(string[,] boardArray)
    {
        PrevMoves.Push(boardArray);
    }

    public string UndoMessage()
    {
        string choice;
        Console.WriteLine(" Press Enter to End your Turn or Press U to Undo");
        return choice = Console.ReadLine().ToUpper();
    }

    public string[,] UndoMove()
    {
        return PrevMoves.Pop();
    }

before i do anything for the players turn i push the current array to the stack

Undo.AddCurrentBoardState(BoardArray);

then i move the player and draw the updated board

playerOne.Move(BoardArray, piece, move, playerOne);
PlayerOneMoveCount.countmoves();
Board.DrawBoard(BoardArray, PlayerOneMoveCount, PlayerTwoMoveCount);

I now try to implement my undo

string choice = Undo.UndoMessage();

if (choice == "U")
{
    BoardArray= Undo.UndoMove();
    Board.DrawBoard(BoardArray, PlayerOneMoveCount, PlayerTwoMoveCount);
}

When the bit above runs it prints the updated board after the player has moved not the original board that was pushed to the stack before the player move.

I have tried pulling the original board into a new 2D array but it still pulls the new updated board

if (choice == "U")
{
    string[,] originalBoard= new string[8, 10];
                originalBoard = Undo.UndoMove();
                Board.DrawBoard(originalBoard, PlayerOneMoveCount, PlayerTwoMoveCount);
}

Why does the new updated board keep getting printed?

PS I am not looking for someone to code a solution, this is coursework and I am just trying to understand the logic of why the same original board keeps getting printed instead of the one i pushed to the stack, its starting to give me a headache

sfa20
  • 63
  • 1
  • 8

2 Answers2

2

This line is most likely your problem: Undo.AddCurrentBoardState(BoardArray);.

Think about what you are passing as argument here. Are you really passing the board state... or are you actually just passing a reference to your board state?

Read about reference types here. Basically, you are currently saying, push the adress "x" of my state array to the stack. So unless you copy your array before calling this function, you will just be pushing "x" over and over, so Undo.UndoMove() will return x.

When you try to mitigate your code here, you are doing some additional weird assignement stuff. I kind of see what you are trying to do, but my comments show what actually happens

// Create new array on adress y, store adress y in originalBoard
string[,] originalBoard= new string[8, 10]; 
// replace y inoriginalBoard with x from my stack, y is now lost forever
originalBoard = Undo.UndoMove(); 

To save your state, do something like this (untested)

// Create array on adress y
var currentState = new string[8, 10];
// Copy all contents of array on adress x to array on adress y
Array.Copy(BoardArray, currentState, 8 * 10)
// Save adress y on your undo stack
Undo.AddCurrentBoardState(currentState);
Tewr
  • 3,713
  • 1
  • 29
  • 43
2

If anyone else is interested, with Tewr's suggestion I managed to fix it by adding string[,] currentState = boardArray.Clone() as string[,];

Need to use Clone as copy doesn't work with 2d array's (well not as standard)

public void AddCurrentBoardState(string[,] boardArray)
    {
        string[,] currentState = boardArray.Clone() as string[,];
        PrevMoves.Push(currentState);
    }
sfa20
  • 63
  • 1
  • 8