Skip to content
Advertisement

Numpy 2D-array sets the value of a cell when it is not needed

I’m trying to write minesweeper in python. A bomb is a cell with a value less than 0. The values of cells that differ from the position of the bomb cell by one column and one row in all directions should increase by 1. But the values of cells that are far from the bomb often increase. Please help me

import numpy as np
from random import randint


#Settings
rows = 10
columns = 10
bombs = 10


def createfield(rows=rows, columns=columns, bombs=bombs):
    minefield = np.full((rows, columns), 0)
    def createbomb():
        bombcount = 0
        random_cell = ((randint(0,rows-1), randint(0,columns-1)))
        minefield[random_cell] = -9
        for item in minefield.flat:
            if item < 0:
                bombcount +=1
        if bombcount < bombs:
            createbomb()
    createbomb()
    return minefield

def setnumbers(array=createfield()):
    for item in (tuple(zip(*(np.nonzero(array < 0))))):
        row, column = item
        print(row, column)
        try:
            array[row-1, column-1] += 1
        except IndexError:
            pass
        try:
            array[row-1, column] += 1
        except IndexError:
            pass
        try:
            array[row-1, column+1] += 1
        except IndexError:
            pass
        try:
            array[row, column-1] += 1
        except IndexError:
            pass
        try:
            array[row, column+1] += 1
        except IndexError:
            pass
        try:
            array[row+1, column-1] += 1
        except IndexError:
            pass
        try:
            array[row+1, column] += 1
        except IndexError:
            pass
        try:
            array[row+1, column+1] += 1
        except IndexError:
            pass

    return array
field = setnumbers()
print(field)

enter image description here

Replacing np.full with np.zeros, changes in the replacement algorithm do not help

New setnumbers function:

def setnumbers(array=createfield()):
    for row in range(rows-1):
        for column in range(columns-1):
            if array[row,column] < 0:
                print(row, column)
                for rs in range(-1, 2):
                    for cs in range(-1, 2):
                        try:
                             array[row-rs, column-cs] += 1
                        except IndexError:
                            pass
    return array

13

Advertisement

Answer

The problem is: since indexing negative positions in numpy arrays returns actual elements of the structure (e.g. a[-1] returns the last element), you are adding more than what is necessary because the except IndexError: doesn’t catch any error (-1 is a valid index).

def setnumbers(array=createfield()):
for item in (tuple(zip(*(np.nonzero(array < 0))))):
    row, column = item
    print(row, column)
    if row-1 >= 0 and column-1 >= 0:
        array[row-1, column-1] += 1
    if row-1 >= 0:
        array[row-1, column] += 1
    try:
        if row-1 >= 0:
            array[row-1, column+1] += 1
    except IndexError:
        pass
    if column - 1 >= 0:
        array[row, column-1] += 1
    try:
        array[row, column+1] += 1
    except IndexError:
        pass
    try:
        if column-1 >= 0:
            array[row+1, column-1] += 1
    except IndexError:
        pass
    try:
        array[row+1, column] += 1
    except IndexError:
        pass
    try:
        array[row+1, column+1] += 1
    except IndexError:
        pass

return array

I removed the unnecessary except. There are much more pythonic and efficent ways of checking index overflow (e.g. compare it with array.shape).

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement