我正在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]