class Board:
def __init__(self):
self.board = self.createBoard()
def createBoard(self):
line = []
for i in range(7):
line.append(' ')
board = []
for i in range(7):
board.append(line)
return board
def showBoard(self):
line = "| "
for x in range(len(self.board)):
for y in range(len(self.board)):
line += self.board[x][y] + " | "
print("-" * 29)
print(line)
line = "| "
print("-" * 29)
if __name__ == '__main__':
board = Board()
board.showBoard()
board.board[1][1] = "O"
board.showBoard()
I was working on a connect-4 python console demo/game when I got stuck on this really weird issue.
The output of the code above is as follows:
-----------------------------
| | O | | | | | |
-----------------------------
| | O | | | | | |
-----------------------------
| | O | | | | | |
-----------------------------
| | O | | | | | |
-----------------------------
| | O | | | | | |
-----------------------------
| | O | | | | | |
-----------------------------
| | O | | | | | |
-----------------------------
The weird thing is, I never assigned O
to all those positions, I only assigned it to the position [1][1].
I had expected the output to be:
-----------------------------
| | | | | | | |
-----------------------------
| | O | | | | | |
-----------------------------
| | | | | | | |
-----------------------------
| | | | | | | |
-----------------------------
| | | | | | | |
-----------------------------
| | | | | | | |
-----------------------------
| | | | | | | |
-----------------------------
It is extremely likely that I'm missing something obvious and small but I've been looking and trying for over an hour and I really can't find the problem.
It's not like my board.board list is any more odd than any other two-dimensional list.
[[' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' ']]
(It's what I get when I print(board.board)
)
Copying and pasting that into IDLE I get the following:
>>> a = [[' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' ']]
>>> a[1][1] = "O"
[[' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', 'O', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ', ' ', ' ', ' ']]
Which gets me the proper board value.
What is so obviously wrong in my code that I'm missing it? I'm pretty sure that when any of you find an answer that I'll shake my head in shame, it's likely that bad.
Enough self-shaming, so why does my code board.board[1][1] = "O"
assign the value "O" to the every single row in board.board
?
Changing the first 1 to any other number from 0-6 doesn't change anything either. It's all the same.
Python provides many ways to create 2-dimensional lists/arrays. However one must know the differences between these ways because they can create complications in code that can be very difficult to trace out.
You can transpose a two-dimensional list using the built-in function zip() . zip() is a function that returns an iterator that summarizes the multiple iterables ( list , tuple , etc.).
This is explained in the FAQ, under How do I create a multidimensional list?
The problem is in this part of the code:
board = []
for i in range(7):
board.append(line)
You're creating a list with 7 references to the same list, line
. So, when you modify one, the others all change, because they're the same list.
The solution is to create 7 separate lists, like this:
def createBoard(self):
board = []
for i in range(7):
line = []
for i in range(7):
line.append(' ')
board.append(line)
return board
Or, more simply, make separate copies of the original list:
def createBoard(self):
line = []
for i in range(7):
line.append(' ')
board = []
for i in range(7):
board.append(line[:])
return board
While we're at it, you could simplify this tremendously by using list comprehensions:
def createBoard(self):
return [[' ' for j in range(7)] for i in range(7)]
Or, as the FAQ suggests, you might do better to use a smarter multidimensional array object, like the ones numpy or pandas provide:
def createBoard(self):
return np.tile(' ', (7, 7))
The disadvantage is that you will need to install numpy, because there's nothing in the standard library that works like this. But the advantage is that you have powerful tools for dealing with arrays—a[1, 1]
isn't much simpler than a[1][1]
, but a[:,1]
to access the second column is a lot simpler than [row[1] for row in a]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With