2

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
4
  • 1
    What is the traceback? Commented Feb 27, 2013 at 23:55
  • You try to access camp[i][j] when i can be x+1 and j can be y+1. Commented Feb 27, 2013 at 23:58
  • This will not work well for you if you modify camp in place, which you are doing. Commented Feb 28, 2013 at 0:02
  • @Eric: I'm not sure what you mean. It's not going to cause an error (you can mutate the values of a list while 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. Commented Feb 28, 2013 at 0:09

2 Answers 2

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…)

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much, it's exactly that!
0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.