1

I would like to access and change a single character in my 2D list of characters. However, when I change one, it changes the whole column. Why is this? What am I doing wrong? At line 31: I am modifying an element in my array and I get a result different than the one I want and expect.

Below is my code:

from random import *

class chessBoard:

    BOARD       = None
    BOARD_WIDTH = 8

    def __init__(self,W = 8):
       self.BOARD = []
       self.BOARD_WIDTH = W

       aRow = ['.'] * self.BOARD_WIDTH
       for curRow in range(self.BOARD_WIDTH):
           self.BOARD.append(aRow)


    def printBoard(self):
       for curRow in self.BOARD:
          print(curRow)


    def initialiseRandomQ(self,N):

       cords = []
       for ii in range(self.BOARD_WIDTH):
          for jj in range(self.BOARD_WIDTH):
              cords.append( [ii,jj] )

       shuffle(cords)

       self.BOARD[0][0] = '1'

       # for curQ in range(N):
       #     xx = cords[curQ][0]
       #     yy = cords[curQ][1]

       #     print(xx,yy)
       #     print(cords[curQ]) 

       #     self.BOARD[xx][yy] = 'Q'

#PROGRAM START#

N_QUEENS    = 2

myChessBoard = chessBoard()

myChessBoard.initialiseRandomQ(2)

myChessBoard.printBoard()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
keyserSoze
  • 137
  • 1
  • 9
  • Possible duplicate of [How to clone or copy a list?](https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list) – Patrick Artner Dec 09 '18 at 12:26
  • Your list contains the same reference to the inner list all over again - if you change the data through one , all other references still point to the same data. – Patrick Artner Dec 09 '18 at 12:27
  • Can you elaboarate please? I'm not trying to make clones, or copy lists. I'm trying to edit the array in place. Do you understand the output I am getting compared to the one that I expect? - i.e. A single element changed compared to an entire column – keyserSoze Dec 09 '18 at 12:29

1 Answers1

1

This:

class chessBoard:

    BOARD       = None
    BOARD_WIDTH = 8

    def __init__(self,W = 8):
       self.BOARD = []
       self.BOARD_WIDTH = W

       aRow = ['.'] * self.BOARD_WIDTH      # this is one list, it's a reference to data
       for curRow in range(self.BOARD_WIDTH):
           self.BOARD.append(aRow)          # adds the same reference 8 times

Your list contains the same reference 8 times, if you change data through one reference, the others (wich are the same) also reflect this. All references point to the same data.

Use

           self.BOARD.append(['.'] * self.BOARD_WIDTH) # add "unique" lists instead

You can check id()'s:

# your version ( self.BOARD.append(aRow) )
print(list(map(id,myChessBoard.BOARD))) 

[140415825494600, 140415825494600, 140415825494600, 140415825494600,
 140415825494600, 140415825494600, 140415825494600, 140415825494600]

# fixed version (self.BOARD.append(['.'] * self.BOARD_WIDTH))
[140560309994568, 140560309994440, 140560309994376, 140560309994312, 
 140560309994248, 140560309994184, 140560309994120, 140560309994696]

See What is the id( ) function used for?

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • 1
    Thank you very much indeed! I really didn't realise that this was the case. I will accept this answer, and I realise that it is a duplicate of the other question but it is slightly removed since here we are trying to edit in place solely. Thanks Patrick. – keyserSoze Dec 09 '18 at 12:33
  • 1
    Can I just say that this is an outstanding answer, and I've learnt an enormous amount from Patrick's answer. – keyserSoze Dec 09 '18 at 16:47
  • @keyserSoze Glad it helped. – Patrick Artner Dec 09 '18 at 16:52