1

I've been trying to make a terminal-based Minesweeper clone in Python. Here is my function for generating the minefield:

BOMB = '#' # The symbol for the bomb
def generateField(width, height, bombs):
    field = [[0] * height] * width # Make the empty array grid
    for bomb in range(0, bombs):
        x, y = random.randint(0, width - 1), random.randint(0, height - 1)
        print((x, y)) # For debugging, remove later
        field[x][y] = BOMB #
    return field

It's not complete yet. However, when I called generateField(12, 12, 12) for a board of width 12, height 12, width 12 bombs, it gives me something like this:

[
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'],
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#'], 
    [0, '#', 0, 0, 0, '#', '#', '#', 0, '#', '#', '#']
]

Could someone give me an explanation for what is happening, or what is wrong?

Astrid Yu
  • 337
  • 3
  • 11
  • possible duplicate of [Python list of lists, changes reflected across sublists unexpectedly](http://stackoverflow.com/questions/240178/python-list-of-lists-changes-reflected-across-sublists-unexpectedly) – vaultah Sep 14 '14 at 17:35
  • http://nedbatchelder.com/blog/201308/names_and_values_making_a_game_board.html – Ned Batchelder Sep 14 '14 at 17:35

1 Answers1

2

This part is causing the trouble:

field = [[0] * height] * width

Try this instead:

field = [[0] * height for _ in xrange(width)]

Explanation: you're copying the same reference to a single sublist across the list, so any changes made to one element will be reflected on the "others" - because in truth, there's only a single sublist that got referenced several times.

My proposed solution takes care of creating different sublists each time (using a list comprehension), so no sublist references will be shared. This is a rather common gotcha in Python, take a look at this post for additional details.

Community
  • 1
  • 1
Óscar López
  • 232,561
  • 37
  • 312
  • 386