Reputation: 3317
Using Python, and classes, I'm trying to make a game like battleship, mostly for practice. So I made a game Board object, and you "see" it, and "change" it. (I'll merge "create" in with init later)
But something weird is happening where my "Change" is applying to every row...here is the code:
class Board:
'Game Board'
topMarkers = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
sideMarkers = list(range(0, 26))
def __init__(self,h,w): #Makes the map
self.height = h
self.width = w
def create(self): #Makes a map for displaying
wave = '~'
self.row = []
self.column = []
#self.column = wave * self.width # If width is 4, column is now '~~~~'
for c in range(self.width):
self.column.append(wave)
raw_input(self.column)
for r in range(self.height): #
self.row.append(self.column)
raw_input(self.row)
def showGrid(self):
print self.row
def changeRow(self, y, x):
self.row[1][2] = "Test"
yourShipsMap = Board(4,3)
theirShipsMap = Board(4,7)
theirShipsMap.create()
theirShipsMap.changeRow(2,2)
theirShipsMap.showGrid()
When I run this, it's writing "Test" in not just the first list, second index, but in every list, second index. Any idea why it's doing that??
I hate when I stop programming all together for like a month and forget everything.
Upvotes: 0
Views: 138
Reputation: 1123400
You create only one column, then append it to your rows. Appending a list to another list does not make a new copy, but re-uses the same list over and over.
Append a copy instead by using the [:]
slice syntax or a list()
call:
for r in range(self.height): #
self.row.append(self.column[:])
Here is an example of what happens for you:
>>> column = [1, 2]
>>> row = []
>>> row.append(column)
>>> row.append(column)
>>> column[0] = 'foobar'
>>> row
[['foobar', 2], ['foobar', 2]]
If we use a copy on the other hand, the copies do not change when we alter the original:
>>> row = []
>>> row.append(list(column))
>>> row.append(column[:])
>>> row
[['foobar', 2], ['foobar', 2]]
>>> column[0] = 1
>>> row
[['foobar', 2], ['foobar', 2]]
I used both methods of creating a (shallow) copy of the original columns list in the above example. If you need to create a deep copy (a list containing other mutable items such as lists or dicts), use the copy.deepcopy
utility instead.
Upvotes: 3
Reputation: 213005
for r in range(self.height): #
self.row.append(self.column)
you keep appending the same list object, which will be seen in each row if updated in one.
Try this:
self.row = [['~'] * self.width for r in xrange(self.height)]
This will create a list of lists with all elements independent from each other.
Upvotes: 2