There is no way to figure out how to reassign an item in a list of lists in this Python code.

I understand that access to items in a list of lists usually works. I know that if you have a list L = [['a', 'b'], ['c', d'],['e', 'f']] , you can access' a' using L[0][0] . However, I'm not sure why the same doesn't work in the following game codec:

 from random import randint from random import choice # make a 5x5 board board = [] row = ['O']*5 for x in range(5): board.append(row) def print_board(): for item in board: print ' '.join(item) #check if input falls within 5x5 grid def check_valid(guess_row, guess_column): return guess_row in range(5) and guess_column in range(5) #return True- is valid choice, return False- not valid choice #check that the input hasn't been guessed previously def check_repeat(guess_row, guess_column): return board[guess_row][guess_column] != 'O' #return True- repeat, reurn False- new #check if input is a correct answer def check_correct(guess_row, guess_column): return (guess_row, guess_column) == (row1, col1) or (guess_row, guess_column) == (row2, col2) #return True- is correct, return False- is not correct #place a 2-position ship while True: #pick random place to start row1 = randint(0,4) col1 = randint(0,4) #choose adjacent second position move_direction = choice(['north', 'south', 'east', 'west']) if move_direction == 'north': row2 = row1 - 1 col2 = col1 elif move_direction == 'south': row2 = row1 + 1 col2 = col1 elif move_direction == 'east': row2 = row1 col2 = col1 + 1 else: # must be west row2 = row1 col2 = col1 - 1 #check that the second position is valid, else pick new values if row2 in range(5) and col2 in range(5): break positions_left = 2 #how many points player needs to hit #you now have a ship at coordinates (row1, col1), (row2, col2) turns = 5 #the gameflow itself: print 'let\ play battleship!' while turns > 0: print 'You have %i turns remaining.' % turns print_board() guess_row = int(raw_input('Guess a row: ')) - 1 #-1 to account for python 0-indexing guess_column = int(raw_input('Guess a column: ')) - 1 if check_valid(guess_row, guess_column) == False: print 'Sorry, those aren\'t valid coordinates' else: #continue game if valid turns -= 1 if check_repeat(guess_row, guess_column): #old guess print 'You seem to have guessed that already.' turns += 1 #don't count this turn elif check_correct(guess_row, guess_column): print 'Hit!' board[guess_row][guess_column] = '!' positions_left -= 1 if positions_left == 0: 'You sunk the battleship!' turns = 0 #stops game else: print 'You can sink this ship in %i more hits!' % positions_left else: board[guess_row][guess_column] = 'X' print 'Sorry, you missed!' 

The problem arises where, after evaluating the player, I try to reassign "O" to "!". (indicating a hit) or "X" (indicating a miss). This should happen when:

  elif check_correct(guess_row, guess_column): print 'Hit!' board[guess_row][guess_column] = '!' 

and at:

  else: board[guess_row][guess_column] = 'X' print 'Sorry, you missed!' 

Instead, what happens is that the entire column ends up being reassigned to that value. Therefore, when a player guesses row 1, column 1, this assumption is interpreted as guess_row = 0, guess_column = 0 . I expect the new board value to turn into:

 [['X', 'O', 'O', 'O', 'O'], ['O', 'O', 'O', 'O', 'O'],['O', 'O', 'O', 'O', 'O'],['O', 'O', 'O', 'O', 'O'],['O', 'O', 'O', 'O', 'O']] 

Instead, it becomes:

 [['X', 'O', 'O', 'O', 'O'],['X', 'O', 'O', 'O', 'O'],['X', 'O', 'O', 'O', 'O'],['X', 'O', 'O', 'O', 'O'],['X', 'O', 'O', 'O', 'O']] 

This is really strange because when I pull out small pieces of code and try to do just that, it works fine, but I don’t see what I am missing when I try to do this as part of the whole code.

+5
source share
2 answers

The problem is that you add the same row variable at each iteration to your board. You should add a new line as follows:

 board = [] for _ in range(5): board.append(['O'] * 5) 
+2
source

Your problem is here:

 row = ['O']*5 for x in range(5): board.append(row) 

As a result, the above board will contain 5 links per line, i.e. the same list. So change one creature, change the whole file. You need to make copies of the string, for example.

 for x in range(5): board.append(row[:]) 

Hope this helps.

+1
source

All Articles