Je crée un jeu de dragueur de mines en python 2.7. J'ai rencontré plusieurs problèmes en essayant de créer l'interface graphique. J'ai utilisé une bibliothèque appelée easyGUI (trouvée ici: http://easygui.sourceforge.net/) pour certaines des fenêtres de configuration de base, mais ce n'est pas mon problème. Le problème est avec la fenêtre de dragueur de mines lui-même. Je ne suis pas sûr de savoir comment mettre un drapeau lorsque vous cliquez avec le bouton droit de la souris ou que vous exécutez ma fonction récursive 'location_reveal' lorsque vous cliquez sur un espace. L'autre problème est de savoir comment modifier le texte sur le bouton pour indiquer le nombre de mines en bordure et où les indicateurs sont chaque fois que l'utilisateur prend une décision. Je me suis heurté à un énorme problème parce que je pensais que je pouvais simplement détruire la fenêtre et la recréer avec les mises à jour à chaque fois, mais cela ne fonctionnait pas non plus. Toute aide serait grandement appréciée.Python Démineur jeu avec GUI en utilisant Tkinter Comment afficher sur les boutons correctement?
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.\n\n' % fieldNames[i])
elif not fieldValues[i].strip().isdigit:
errmsg += ('"%s" must be an integer.\n\n' % fieldNames[i])
elif i == 0 and not 3 <= int(fieldValues[i]) <= 30:
errmsg += ('Width must be between 3 and 30 mines.\n\n')
elif i == 1 and not 3 <= int(fieldValues[i]) <= 20:
errmsg += ('Height must be between 3 and 20 mines.\n\n')
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) + '\n\n')
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()
Merci pour la réponse. J'essayé d'utiliser configure, mais tous mes boutons ont le même nom: field_hid = Tkinter.Tk() pour x dans la plage (largeur): pour y dans la plage (hauteur): s = str (x) + " : "+ str (y) t = montrant [x + 1] [y + 1] b = Tkinter.Button (champ_hid, texte = t, commande = lambda s = s: location_chosen (s)) #b. bind ('', field_hid.destroy()) b.pack() b.grid (ligne = x, colonne = y) Tkinter.mainloop() –
@Nick Delbin: vous pouvez réutiliser la même variable locale, mais chaque widget est toujours une entité distincte. Vous avez juste besoin de sauvegarder une référence. Je recommande un dictionnaire, avec un deux-tuple comme une clé. Par exemple, 'self.button [(ligne, colonne)] = Tkinter.Button (...)'. Cependant, avec le design que vous avez, vous n'en avez pas vraiment besoin car vous pouvez simplement passer la référence au widget en tant que paramètre du callback (par exemple: 'b = Tkinter.button (...); b.configure (commande = lambda button = b: ...) ') –
Je ne suis pas sûr de ce que vous entendez par là, y a-t-il un moyen d'être plus spécifique? Je comprends en utilisant configure, mais comment détermine-t-il le bouton sur lequel je souhaite changer le texte? –