I'm a coding beginner that's putting a project together for a game. To update the game board, I use this function:
Board = [0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
def boardupdate(self, move):
for index, val in enumerate(move):
try:
if val >= 15:
val -= 3
move[index] = val
except TypeError:
pass
try: self[move[0]] = 1
except Exception: None
try: self[move[1]] = 0
except Exception: None
try: self[move[2]] = 0
except Exception: None
return self
Where the first item of the list move
represents the location where a piece is being placed in a turn, the second item representing where the piece is being taken from (in this game, you can either place a new piece on the board or move a piece), and the third item represents where a piece is being completely removed from the game. A certain turn can involve any of or none of these actions, hence the try
and except
blocks (which I learned just today, so if I am using them incorrectly, help would be much appreciated).
The code works as intended inside the function, but for some reason after this function is called, Board
gets changed as if it was run through the function.
print(Board)
print(boardupdate(Board, [0, None]))
print(Board)
returns:
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
I've tried to solve this by copying Board
to a temporary variable like so:
def boardupdate(self, move):
tempboard = self
for index, val in enumerate(move):
try:
if val >= 15:
val -= 3
move[index] = val
except TypeError:
pass
try: tempboard[move[0]] = 1
except Exception: None
try: tempboard[move[1]] = 0
except Exception: None
try: tempboard[move[2]] = 0
except Exception: None
return tempboard
Returns the same output as before. How can I change the output of this function without messing around with the initial conditions of Board
? This is necessary in order for the rest of my code to run. Thanks!
CodePudding user response:
tempboard = board
doesn't copy board
, it just binds tempboard
to the same value as board
. If you do:
tempboard = board.copy()
it will actually copy board
.
Some other miscellaneous advice on this function:
- Don't call the board parameter
self
, since this isn't an instance method on the board itself. Just call it something likeboard
. - Don't catch all exceptions blindly; it makes errors very difficult to debug. If you have an error in your code, you want it to raise an exception so you can see exactly what went wrong right away, rather than spending hours trying to figure out why it's just not doing anything! I'd suggest adopting a convention that a move you aren't making is
None
, and then checking forNone
specifically, rather than just ignoring any attempted move that raises an exception. - Use named variables and/or comments to keep track of what the different
move
items represent.
def boardupdate(board, move):
board = board.copy()
# Subtract 3 from any move positions >= 15.
move = [p if p is None or p < 15 else p - 3 for p in move]
[moved_to, moved_from, removed] = move
if moved_to is not None:
board[moved_to] = 1
if moved_from is not None:
board[moved_from] = 0
if removed is not None:
board[removed] = 0
return board
CodePudding user response:
You are just pointing to Board
, not actually copying it. In python, iterables are not copied by default for efficiency reasons.
So for example:
x=[1,2,3]
y=x
y[1]=5
print(x)
[1,5,3]
To get over this, you should make a deep copy of Board
either inside the function:
tempboard = self.copy()
or when you are calling the function:
boardupdate(Board.copy())
This is not the same for immutable objects, like integers:
x=5
y=x
y =1
print(x)
5