用户界面-Python扫雷游戏的GUI使用Tkinter如何正确显示在按钮上



我正在python 2.7中创建一个扫雷游戏。我在尝试创建GUI时遇到了一些问题。我使用了一个名为easyGUI的库(可在此处找到:http://easygui.sourceforge.net/)对于一些基本的设置窗口,但这不是我的问题。问题在于实际的扫雷舰窗口本身。我不确定右键单击时如何放置标志,或者左键单击空间时如何运行递归的"location_reveal"函数。另一个问题是如何更改按钮上的文本,以表示有多少边界地雷,以及每次用户做出决定时标志在哪里。我遇到了一个巨大的问题,因为我想我可以销毁窗口,每次都用更新来重新创建它,但这也不起作用。如有任何帮助,我们将不胜感激。

from easygui import *
import random
import os
import Tkinter
def game_new():
    n = enterbox(msg='Enter your name.', title='Welcome new user!', strip=True)
    while n.strip() == "":
        n = enterbox(msg='Oops you forgot to enter a name!', title='Welcome new user!', strip=True)
    a = buttonbox(msg='Choose a game difficulty', title='Configuration', choices = ['Beginner','Intermediate','Expert','Custom'])
    if a[0] == 'B':
        return n, 9, 9, 10
    elif a[0] == 'I':
        return n, 16, 16, 40
    elif a[0] == 'E':
        return n, 30, 16, 99
    else:
        a,b,c = customconfigure()
        return n,a,b,c
def customconfigure():
    msg = "Minesweeper configuration:"
    title = "Settings"
    fieldNames = ["Width in mines (max 30):","Height in mines (max 20):","Mines:"]
    fieldValues = []  # we start with blanks for the values
    fieldValues = multenterbox(msg,title, fieldNames)
    while 1:
        if fieldValues == None: break
        errmsg = ""
        for i in range(len(fieldNames)):
            if fieldValues[i].strip() == "":
                errmsg += ('"%s" was left blank.nn' % fieldNames[i])
            elif not fieldValues[i].strip().isdigit:
                errmsg += ('"%s" must be an integer.nn' % fieldNames[i])
            elif i == 0 and not 3 <= int(fieldValues[i]) <= 30:
                errmsg += ('Width must be between 3 and 30 mines.nn')
            elif i == 1 and not 3 <= int(fieldValues[i]) <= 20:
                errmsg += ('Height must be between 3 and 20 mines.nn')
            elif i == 2 and not 1 <= int(fieldValues[i]) <= (int(fieldValues[0]) * int(fieldValues[1]) - 1):
                errmsg += ('Mines must be between 1 and ' + str(int(fieldValues[0]) * int(fieldValues[1]) - 1) + 'nn')                
        if errmsg == "":
            break # no problems found
        fieldValues = multenterbox(errmsg, title, fieldNames, fieldValues)
    return int(fieldValues[0]),int(fieldValues[1]),int(fieldValues[2])
def inchk(s,m):
    if not s.isdigit:
        return False
    if 1 <= int(s) <= m:
        return True
    else:
        return False    
def move_get():
    user_x = raw_input("Enter the 'x' of the point you want to preform an action on: ")
    while not inchk(user_x,width):
        user_x = raw_input("Invalid selection. Enter a value for 'x': ")
    user_y = raw_input("Enter the 'y' of the point you want to preform an action on: ")
    while not inchk(user_y,height):
        user_y = raw_input("Invalid selection. Enter a value for 'y': ")
    return int(user_x), int(user_y)

def location_reveal(x,y):
    global field
    global showing    
    global symbol_mine
    if field[x][y] == symbol_mine:
        game_over()
    else:
        showing[x][y] = " " + str(field[x][y]) + " "
        if showing[x-1][y] == "     " and field[x-1][y] != symbol_mine:
            location_reveal(x-1,y)
        if showing[x+1][y] == "     " and field[x+1][y] != symbol_mine:
            location_reveal(x+1,y)        
        if showing[x][y+1] == "     " and field[x][y+1] != symbol_mine:
            location_reveal(x,y+1)
        if showing[x][y-1] == "     " and field[x][y-1] != symbol_mine:
            location_reveal(x,y-1)
    playing()
def location_chosen(s):
    global field
    global showing
    x = int(s[:s.index(":")]) + 1
    y = int(s[s.index(":")+1:]) + 1
    msg = "Choose an action to "
    choices = ["Reveal","Flag","Back"]
    reply = buttonbox(msg,choices=choices)
    field_hid.destroy
    if reply == "Back":
        playing()
    elif reply == "Flag":
        showing[x][y] = " F "
        playing()
    else:
        location_reveal(x,y)
def playing():
    global field
    global showing
    global width
    global height
    global symbol_mine
    win = False
    def k():
        field_hid.destroy()
    count_mine = 0
    count_flag = 0
    for x in field:
        count_mine += x.count(symbol_mine)
    for x in showing:
        count_flag += x.count(' F ')
    for x in range(1, width):
        for y in range(1, height):
            if field[x][y] == symbol_mine and showing[x][y] == ' F ':
                if count_mine == count_flag:
                    win = True                 
                else:
                    win = False
                    break               

    field_hid = Tkinter.Tk()    
    for x in range(width):
        for y in range(height):
            s = str(x) + ":" + str(y)
            t = showing[x+1][y+1]
            b = Tkinter.Button(field_hid, text = t, command = lambda s=s: location_chosen(s))
            #b.bind('<Button-1>', field_hid.destroy())
            b.pack()
            b.grid(row=x, column=y)
    Tkinter.mainloop()  
def main():
    global width
    global height
    global field
    global showing
    global symbol_mine
    user_name, width, height, mines = game_new()
    symbol_empty = ' '
    symbol_mine = 'M' 
    play = True
    #Creates field with empty spaces
    field = [[symbol_empty for h in range(width+2)] for w in range(height+2)]    #
    showing = [["     " for h in range(width+2)] for w in range(height+2)]
    # Randomly places mines on the field
    mines_placed = 0
    while mines_placed < mines:
        y = random.randint(1,width)#
        x = random.randint(1,height)#
        if field[x][y] == symbol_empty:
            field[x][y] = symbol_mine
            mines_placed += 1
    # Checks How many mines border each square
    for x in range(1,height+1):
        for y in range(1, width+1):
            if field[x][y] != symbol_mine:
                mines_touching = 0
                for x2 in range(x-1,x+2):
                    for y2 in range(y-1,y+2):
                        if field[x2][y2] == symbol_mine:
                            mines_touching += 1
                if mines_touching > 0:
                    field[x][y] = str(mines_touching)
    #Creates the playing field
    playing()
main()

您可以使用按钮的configure方法更改按钮上的文本(例如:b1.configure(text="whatever"))。您不需要每次更新都重新创建整个窗口。只需创建一次按钮,然后根据需要更改文本或图像。

例如,将按钮定义更改为如下所示:

b = Tkinter.Button(field_hid, text = t)
b.configure(command = lambda s=s, button=b: location_chosen(s,button))

然后,将location_chosen的参数更改为如下:

def location_chosen(s,button):
    ...

完成此操作后,方法location_chosen将作为对所单击按钮的引用传递。然后,您可以通过执行button.configure(...) 将该按钮重新配置为具有您想要的任何标签或图像

当然,另一种方法是将引用存储在数组或字典中。例如,您可以添加:

self.button[s] = b

这样,当您需要通过x,y(例如:self.button["1:2"].configure(...)

引用特定按钮时,您可以引用button[s]

相关内容

  • 没有找到相关文章

最新更新