Making an undo function for a 7x7 board in Python

2019-08-19 02:36发布

I am currently trying to program a game called Pah Tum. The game involves a board that is 7x7. For the board I just created a list with 7 lists containing 7 elements each, basically I just made each row into a list and merged them into a big list:

board = [[0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0]]

The game should have an undo function, which enables the player to go back one step. I thought I could just append the whole board into a seperate list and use that to go back a step.

        if input == 'u' or input == 'U':
            board = board_list[-1]
            del board_list[-1]

until here it works, but for some reason the board_list (the list I'm appending the current board to) always updates as a whole, meaning each element changes and becomes the new board.

eg. if I have

#board = [[0, 'B'], [0, 0]]
board_list.append(board)
.
.
.
#board = [[0, 'B'], [0, 'B']]
board_list.append(board)

after the first append I'd get

board_list = [[[0, 'B'], [0, 0]]]

and the second one leaves me with

board_list = [[[0, 'B'], [0, 'B']], [[0, 'B'], [0, 'B']]]

I have no idea why this happens. I searched for similar questions but I only see undo functions for canvases and I'm not sure if I can use them for this scenario.

2条回答
戒情不戒烟
2楼-- · 2019-08-19 03:23

When you append board to board_list you're adding a reference to the original board. Perhaps a better option would be to add the previous state for the changed cell when you make a move:

moves.append([x, y, board[x][y]])

And then when you undo you reapply that state:

undo_move = moves[-1]
board[undo_move[0]][undo_move[1]] = undo_move[2]
del moves[-1]

Or more pythonically:

x, y, board[x][y] = moves.pop()

Alternatively, you could make a copy of the entire board and store that in the list instead.

查看更多
等我变得足够好
3楼-- · 2019-08-19 03:23

In order to create a list of board copies you need to implement a deep copying method for your board class. Otherwise, all you're doing is copying the same pointer over and over. Python passes by reference and that's the source of your problem. Implement a new method which creates a new board with the same fields as your current board and return a pointer to that board from that method. I'd recommend reading some about shallow and deep copies. You can find more details here.

查看更多
登录 后发表回答