I need to replace all elements of the list camp by the respectives output values of a function "counterPosition" that acts on each position of the list
camp = [[True, False, False, False, False, True],
[False, False, False, False, False, True],
[True, True, False, True, False, True],
[True, False, False, False, False, False],
[False, False, True, False, False, False],
[False, False, False, False, False, False]]
def counterPosition(x, y):
bombs = 0
for i in range(x-1, x+2):
for j in range(y-1, y+2):
if i<0 or j<0: continue
elif camp[i][j] == True:
bombs += 1
return bombs
for x in range (len(camp)):
for y in range (len(camp[x])):
camp[x][y] = counterPosition(x,y)
print camp
Which gives:
IndexError: list index out of range
2 Answers 2
The problem is in your counterPosition function. In particular:
for i in range(x-1, x+2):
for j in range(y-1, y+2):
...
elif camp[i][j] == True:
You're passing this values of x ranging from 0 to len(camp)-1. Which means that i ranges from -1 to len(camp)-1+2. So, for example, when you get to the last row, x=5, i will range from -1 to 6. But camp[6] is out of bounds. So you get an IndexError.
You'll have the same problem with y and j, of course.
So, how do you fix that? Well, it depends on what you're trying to do. But, given this line:
if i<0 or j<0: continue
I think what you want is to add this:
elif i>=len(camp) or j>=len(camp[i]): continue
Although really, it would be simpler to eliminate these outside the loop—e.g., for i in range(max(x-1, 0), min(x+2, len(camp)):
Meanwhile, I'm not sure what your program is trying to do, but it looks likesomething kind of Minesweeper-related, yes? If so, I don't think it's going to do what you want even after you fix this. As you replace the True and False values with counts, camp[i][j] == True can never be true for i<=x and j<=y. So, the end result is:
[[2, 2, 2, 1, 3, 2],
[2, 2, 3, 2, 4, 2],
[3, 2, 1, 2, 1, 2],
[1, 3, 2, 3, 1, 2],
[1, 3, 1, 2, 1, 2],
[1, 3, 1, 3, 1, 2]]
When I think you may have wanted this:
[[1, 1, 0, 0, 2, 2],
[3, 3, 2, 1, 4, 3],
[3, 3, 2, 1, 3, 2],
[3, 4, 3, 2, 2, 1],
[1, 2, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0]]
That's the number of adjacent bombs at even given square. To get the latter, either iterate over or modify a copy of camp, instead of doing both to the same list. For example:
newcamp = copy.deepcopy(camp)
for x in range (len(camp)):
for y in range (len(camp[x])):
newcamp[x][y] = counterPosition(x,y)
print newcamp
Or just:
camp = [[counterPosition(x, y) for y in range(len(camp[x]))]
for x in range(len(camp))]
print camp
(Although really, I'd give them different names, like bombcamp and flagcamp or something...)
1 Comment
Another way to store this data is to use a set:
bombs = {
(i, j) for i, row in enumerate(camp)
for j, is_bomb in enumerate(row)
if is_bomb
}
And then, instead of camp[i][j] == True, do (i, j) in bombs
camp[i][j]whenican bex+1andjcan bey+1.campin place, which you are doing.listwhile iterating it, you just can't mutate the shape of the list itself, e.g. via inserting or deleting values). And it's certainly going to do something (e.g., the first row will end up as[2, 2, 2, 1, 3, 2]). The only question is whether that something is what the OP wants.