-1

I have this program trying to add up the number of grid spaces around it of a certain value, and it keep giving the error "IndexError: list out of range". I've tried setting it to start on column and row late and end one column and row early to the same effect. The error points at [x+1][y+1] specifically.

for l in range(loops):
    for x in range(self.width):
        for y in range(self.height):
            neighbors = 0

            if tiles_copy[x-1][y-1] == 1:
                neighbors += 1
            if tiles_copy[x][y-1] == 1:
                neighbors += 1
            if tiles_copy[x+1][y-1] == 1:
                neighbors += 1
            if tiles_copy[x+1][y] == 1:
                neighbors += 1
            if tiles_copy[x+1][y+1] == 1:
                neighbors += 1
            if tiles_copy[x][y+1] == 1:
                neighbors += 1
            if tiles_copy[x-1][y+1] == 1:
                neighbors += 1
            if tiles_copy[x-1][y] == 1:
                neighbors += 1
  • Suppose `x` is at the largest value in `range(self.width)` and you add 1 to that - you've gone over the size of the list. You have this problem on all of the edges of the grid. For instance, when x is zero, `x - 1` is `-1` which in the python world is the item at the very end of the list. What is your edge policy? – tdelaney Apr 13 '20 at 05:39
  • I had it set to start on row and column 1 and end on on from the width/height and it had the same problem – Mac French Apr 13 '20 at 05:41
  • 1
    Like `for x in range(1, self.width-1)` ? If so, `tiles_copy` might not be the size you think it is. I'm assuming that its a `self.width` length list with `self.height` length sublists? From their names it may be opposite. You could check that `len(tiles_copy)` is `self.width` and that each sublist is the other size. – tdelaney Apr 13 '20 at 05:47

2 Answers2

0

Not an answer

Can you change the start of your loop to

print(self.width, len(tiles_copy))
for x in range(1, self.width):
    print(self.height, len(tiles_copy[x-1]), len(tiles_copy[x]), len(tiles_copy[x+1]))
    for y in range(1, self.height):

len(tiles_copy) should be equal to self.width and the 3 values in the loop should be equal to self.height. At a guess, some of the values are less.

cup
  • 7,589
  • 4
  • 19
  • 42
0

You have to prevent non existing indexes like -1 and self.width, self.width + 1 etc...

I think it's easier to make a function that does the check for the 8 point around each x y combination

# =========================================
def count_neighbors(self, x , y):

    if self.width < 3 or self.height < 3:
        return 0

    neighbors = 0
    x_range = []
    y_range = []

    # get only the valid x and y indexes ------------
    if x > 0:
        if x < self.width - 1:
            x_range = range(x - 1, x + 1 + 1)   # x-1, x, x+1
        else:
            x_range = range(x - 1, x + 1)  # x-1, x
    else:
        # x == 0
        x_range = range(x, x + 1 + 1)   # x, x+1

    if y > 0:
        if y < self.width - 1:
            y_range = range(y - 1, y + 1 + 1)  # y-1, y, y+1
        else:
            y_range = range(y - 1, y + 1)    # y-1, y
    else:
        # y == 0
        y_range = range(y, y + 1 + 1)   #  y, y+1


    for x_index in x_range:
        for y_index in y_range:

            if x_range == x and y_index == y:
                # don't compare with itself
                continue

            if tiles_copy[x_index][y_index] == 1:
                neighbors += 1

    return neighbors


# ============================================
neighbors = 0
for l in range(loops):
    for x in range(self.width):
        for y in range(self.height):
            neighbors += count_neighbors(x, y)

It's a bit tricky You have to test and debug this yourself.

Mace
  • 1,355
  • 8
  • 13