1

I'm quite a newbie when it comes to programming, and in our programming excercise in school I'm making a minesweeper game in python using TKinter as GUI. The game works, except my "floodfill" algorithm, to clear any adjacent blank spaces. I have made the board, printed a previously created list, according to choices(height, width and amount of mines) chosen by the user, with labels, and hidden these labels behind buttons.

I can bind events to hide these buttons when clicked on, but what I also want is to be able to hide the buttons nearby, with the help of my floodfill algorithm. I feel like all I need anymore is the line of code that will hide the button according to x and y coordinates, and not just the one that's clicked upon. I think you've got the idea,

def initGame(field, height, width, mn):     
    play = tk.Toplevel()
    play.grid()
    title = ttk.Label(play, text= "MineSweeper")
    title.grid(row=0)
    playfield = tk.LabelFrame(play, text = None)
    playfield.grid(row = 1, rowspan = height+2, columnspan = width+2)       
    mine = tk.PhotoImage(file='mine.gif')
    for i in range(1, height+1):
        for j in range(1, width+1):             
            if  field[i][j] == '9':
                val = tk.Label(playfield, image = mine)
                val.image=mine
            else:
                val = tk.Label(playfield, text= "%s" %(field[i][j]))
            val.grid(row=i-1, column=j-1)
    blist = []
    for i in range(1, height+1):
        for j in range(1, width+1):
            btn = tk.Button(playfield, text = '   ')
            blist.append(btn)

            def handler(event, i=i, j=j):
                return floodfill(event, field, blist, j, i)
            btn.bind('<ButtonRelease-1>', handler)
            btn.bind('<Button-3>', iconToggle)
            btn.grid(row=i-1, column=j-1)

def floodfill(event, field, blist, x, y):
    edge = []
    edge.append((y,x))
    while len(edge) > 0:
        (y,x) = edge.pop()
        if field[y][x] != '9':
            #####################
        else:
            continue
        for i in [-1, 1]:
            for j in [-1, 1]:
                if y + i >= 1 and y + i < len(field)-1:       
                    edge.append((y + i, x))
                if x + j >= 1 and x + j < len(field[0])-1:
                    edge.append((y, x + j))

the long line of # is where I believe is all I need anymore to get this system to work, in something like "button.position(x, y). I attempted to save the button in the blist, and maybe I could get the correct button that needs to be hidden from it, with the help of x and y coordinates?

of course, if you have a better idea how to solve this problem, I'd love to hear it.

feil
  • 33
  • 5

1 Answers1

0

Save the buttons in a 2D array, so blist[x ,y] represents the button at x,y position. Getting the right button when you know the x,y position should be straight forward then.

Edit:

First create the 2D array.

blist = []
for i in range(1, height+1):
    tmpList = []
    for j in range(1, width+1):
        btn = tk.Button(playfield, text = '   ')
        tmpList.append(btn)

        def handler(event, i=i, j=j):
            return floodfill(event, field, blist, j, i)
        btn.bind('<ButtonRelease-1>', handler)
        btn.bind('<Button-3>', iconToggle)
        btn.grid(row=i-1, column=j-1)

    blist.append(tmpList)

Then use it to get the button objects in the flood function:

 if field[y][x] != '9':
        Button_To_Hide = blist[x-1][y-1] 
        Button_To_Hide.grid_forget()

Now you might have to switch x and y here. -1 since you have started your indexing with 1 in the coordinates for the field (i think).

M4rtini
  • 13,186
  • 4
  • 35
  • 42
  • Any chance you could provide with a short example how to add the coordinates to the list, and then the hiding of the button? is it like blist[x,y].grid_forget()? – feil Dec 08 '13 at 17:05
  • that should work in theory, the solution seems very elegant to me aswell. The game locks up when i try to run it, with memoryerror, caused by if y + i >= 1 and y + i < len(field)-1: edge.append((y + i, x)) – feil Dec 08 '13 at 17:29
  • Maybe you have to create the full list of buttons, before you start binding it to the handler. It might be trying to access indices in the array that wasn't defined when binding it. If this is the case it means that it will pass a copy of blist to each button handler, which is bad. Making the blist available without passing it direcly to the floodfill might work. – M4rtini Dec 08 '13 at 17:37
  • Yeah, figured out why the memory dump was exceeded. Thanks for your help with this. – feil Dec 08 '13 at 17:38