I have to create a game of Sokoban in Python and I have defined methods in my Sokoban class to find_player() , complete() , get_steps() and move() . I need to create a restart() method and an undo() method but I don't know how to do that. I can't find a way to store the original board or previous boards. I tried making defining another board in the __init__
but it just updates with self.__board
instead of saving the initial board. I've also tried making a list in the __init__
and tried appending each move's "board" to the list but it changes every board in the list. I've attached my code if anyone can help.
class Sokoban:
"""Your code here"""
def __init__(self, board):
self.__board = board
self.__original_board = board
self.__steps = 0
self.__last_step = []
self.__position = (0, 0)
def find_player(self):
for row in range(len(self.__board)):
for column in range(len(self.__board[row])):
if self.__board[row][column] == "P":
self.__position = (row, column)
return self.__position
def complete(self):
for row in self.__board:
for column in row:
if column == "o":
return False
return True
def get_steps(self):
return self.__steps
def restart(self):
first_board = self.__original[0]
new_board = []
for i in range(len(first_board)):
new_board.append(first_board[i])
print(self.__original)
return Sokoban(self.__original_board)
def undo(self):
return
def move(self, direction):
row, column = self.find_player()[0], self.find_player()[1]
if direction == "w":
if self.__board[row - 1][column] == "#" and self.__board[row - 2][column] == "o":
self.__board[row][column] = " "
self.__board[row - 1][column] = "P"
self.__board[row - 2][column] = " "
elif self.__board[row - 1][column] != "o" and self.__board[row - 1][column] != "*":
if self.__board[row - 1][column] == "#" and self.__board[row - 2][column] != "o" and self.__board[row - 2][column] != "*":
self.__board[row][column] = " "
self.__board[row - 1][column] = "P"
self.__board[row - 2][column] = "#"
else:
self.__board[row][column] = " "
self.__board[row - 1][column] = "P"
else:
return self.__board
self.__last_step.append("w")
if direction == "a":
if self.__board[row][column - 1] == "#" and self.__board[row][column - 2] == "o":
self.__board[row][column] = " "
self.__board[row][column - 1] = "P"
self.__board[row][column - 2] = " "
elif self.__board[row][column - 1] != "o" and self.__board[row][column - 1] != "*":
if self.__board[row][column - 1] == "#" and self.__board[row][column - 2] != "o" and self.__board[row][column - 2] != "*":
self.__board[row][column] = " "
self.__board[row][column - 1] = "P"
self.__board[row][column - 2] = "#"
else:
self.__board[row][column] = " "
self.__board[row][column - 1] = "P"
else:
return self.__board
self.__last_step.append("a")
if direction == "s":
if self.__board[row 1][column] == "#" and self.__board[row 2][column] == "o":
self.__board[row][column] = " "
self.__board[row 1][column] = "P"
self.__board[row 2][column] = " "
elif self.__board[row 1][column] != "o" and self.__board[row 1][column] != "*":
if self.__board[row 1][column] == "#" and self.__board[row 2][column] != "o" and self.__board[row 2][column] != "*":
self.__board[row][column] = " "
self.__board[row 1][column] = "P"
self.__board[row 2][column] = "#"
else:
self.__board[row][column] = " "
self.__board[row 1][column] = "P"
else:
return self.__board
self.__last_step.append("s")
if direction == "d":
if self.__board[row][column 1] == "#" and self.__board[row][column 2] == "o":
self.__board[row][column] = " "
self.__board[row][column 1] = "P"
self.__board[row][column 2] = " "
elif self.__board[row][column 1] != "o" and self.__board[row][column 1] != "*":
if self.__board[row][column 1] == "#" and self.__board[row][column 2] != "o" and self.__board[row][column 2] != "*":
self.__board[row][column] = " "
self.__board[row][column 1] = "P"
self.__board[row][column 2] = "#"
else:
self.__board[row][column] = " "
self.__board[row][column 1] = "P"
else:
return self.__board
self.__last_step.append("d")
progress = self.__board
self.__steps = 1
return self.__board
def __str__(self):
output = ""
for items in self.__board:
for i in items:
output = i
output = "\n"
return output
def main(board):
game = Sokoban(board)
message = 'Press w/a/s/d to move, r to restart, or u to undo'
print(message)
while not game.complete():
print(game)
move = input('Move: ').lower()
while move not in ('w', 'a', 's', 'd', 'r', 'u'):
print('Invalid move.', message)
move = input('Move: ').lower()
if move == 'r':
game.restart()
elif move == 'u':
game.undo()
else:
game.move(move)
print(game)
print(f'Game won in {game.get_steps()} steps!')
test_board = [
['*', '*', '*', '*', '*', '*', '*', '*'],
['*', ' ', ' ', ' ', ' ', ' ', ' ', '*'],
['*', 'P', ' ', '#', ' ', ' ', ' ', '*'],
['*', '*', '*', '*', '*', ' ', '#', '*'],
['*', 'o', ' ', ' ', ' ', ' ', ' ', '*'],
['*', ' ', ' ', ' ', ' ', ' ', 'o', '*'],
['*', '*', '*', '*', '*', '*', '*', '*']
]
main(test_board)
CodePudding user response:
You'll need to (deep) copy the board list-of-lists if you don't want the same value (all the way up to test_board
) to get changed.
import copy
# ...
def __init__(self, board):
self.__board = copy.deepcopy(board)
self.__original_board = copy.deepcopy(board)
Beyond that, maybe .restart()
should just reset the game object's state, not return a new object?
def __init__(self, board):
self.__original_board = copy.deepcopy(board)
self.restart()
# ...
def restart(self):
self.__steps = 0
self.__last_step = []
self.__position = (0, 0)
self.__board = copy.deepcopy(self.__original_board)
That way, a simple game.restart()
call will do.
CodePudding user response:
May be you can use in-memory databases for store your data for testing.