Trying to iterate over my array for a Minesweeper game, but the last elements are being ignored

Godot Version

4.3

Ok, so I’m learning Godot and wanted to make Minesweeper to teach myself tilemaps, but I’m stumbling at the first hurdle because my program isn’t iterating over the last elements in my arrays.

So I have an array of arrays called mine_map that I iterate over in a prior function to place mines, then it calls this function to iterate over the tiles and increase the value of each gridspace based on how many mines are near it. I’m sure there’s a much better way to do what I’m trying to, but this is what I’ve come up with so far:

func generate_tiles():
	for x in range(9):
		for y in range(9):
            #10 is a mine, ignore the space if there's a 10 here.
			if mine_map[x][y] != 10:
				#check 3 tiles above current tile
				if mine_map[x-1][y-1] == 10:
					mine_map[x][y] += 1	
				if mine_map[x][y-1] == 10:
					mine_map[x][y] += 1	
				if mine_map[x+1][y-1] == 10:
					mine_map[x][y] += 1	
				
				#check 2 tiles next to current
				if mine_map[x-1][y] == 10:
					mine_map[x][y] += 1	
				if mine_map[x+1][y] == 10:
					mine_map[x][y] += 1	
				
				#check 3 tiles below current
				if mine_map[x-1][y+1] == 10:
					mine_map[x][y] += 1	
				if mine_map[x][y+1] == 10:
					mine_map[x][y] += 1	
				if mine_map[x+1][y+1] == 10:
					mine_map[x][y] += 1

I have a bunch of prints to test out the system, but the problem is, the function seems to be ignoring the last element in each ‘x’ array, as well as the last ‘x’ array in it’s entirety, so I get output like this:

[1, 10, 1, 1, 10, 2, 1, 2, 10, 0]
[1, 1, 1, 1, 2, 10, 1, 2, 10, 0]
[0, 0, 0, 0, 1, 1, 1, 1, 1, 0]
[1, 1, 1, 0, 0, 0, 1, 1, 1, 0]
[1, 10, 2, 1, 1, 0, 1, 10, 1, 0]
[1, 1, 2, 10, 1, 0, 1, 1, 1, 0]
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0]
[1, 1, 0, 0, 0, 1, 10, 1, 0, 0]
[10, 1, 0, 0, 0, 1, 1, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Why won’t my for loop iterate over the last elements?

range(9) gives you values from 0 through 8. It works this way (I presume) so that you don’t have to do .size() - 1 when iterating over an array. So you’re off by one.

The range() is redundant here as well. You should be able to do:

func generate_tiles():
    for x in 10:
        for y in 10:
            if mine_map[x][y]...

Personally, I’d suggest using a single array, though. You can do something like:

const X_SIZE = 10
const Y_SIZE = 10

func generate_tiles():
    for y in Y_SIZE:
        for x in X_SIZE:
            if mine_map[x + (y * X_SIZE)]...

That lets you use a single array for the whole shebang; you just address it in a 2D manner.

I tried this, but when I run it I get the error “Invalid access of index ‘10’ on a base object of type: ‘Array’”

That’s because you’re looking at neigboring cells without checking the edges. You’re checking offsets of x-1 and x+1 (and the same for y), which walks off the ends of your arrays.

You either need padding around the array, or your tests need to be aware of whether they’re at the edges of the array.

1 Like

That was exactly the problem, thank you kind stranger!