So, I'm making a mine sweeper as a school project and I struggle through setting a settings window.
My biggest problem right now is that I have a slider which allows the player to change the size of the terrain by changing the number of rows and columns to one same number to then multiply them and have a terrain which is the square of the number received from the slider.
However, the slider does not seem to work in the way it is intended as he keeps sending back the value "0", as if he was never updating the value when moving the slider.
So I end up with the error :
File "D:\MiniConda\lib\random.py", line 316, in randrange
raise ValueError("empty range for randrange() (%d, %d, %d)" % (istart, istop, width))
ValueError: empty range for randrange() (0, 0, 0)
Here is my entire code, I put a commentary at the line where I believe the problem comes from :
from tkinter import *
from tkinter import ttk as ttk
import random
#module permettant l'importation d'images
from PIL import Image, ImageTk
#module permettant la création de boutons avec plus de choix esthétiques
import customtkinter
#module permettant de fermer le programme
import sys
#Crée la fenêtre de prévention
def PreventionDemineur():
preventionfenetre = Tk()
#Assigne pour titre à la fenêtre "Paramètres du Jeu du Démineur"
preventionfenetre.title(" ATTENTION ")
#Affiche le texte de prévention avec ses caractéristiques
TextePrevention = Label(preventionfenetre, text="Détails à lire !", font=("helvetica", 25, "bold"))
#Gère la position du message de prévention
TextePrevention.place(relx=0.5, rely=0.1, anchor=CENTER)
#Affiche le texte de prévention avec ses caractéristiques
ContenuPrevention = Label(preventionfenetre, text="- Prenez le temps de changer les paramètres du jeu, sinon \n il démarrera avec ses paramètres par défaut.", font=("helvetica", 10))
#Gère la position du message de prévention
ContenuPrevention.place(relx=0.5, rely=0.3, anchor=CENTER)
#Change la taille afin que la fenêtre puisse tout afficher
preventionfenetre.minsize(400, 400)
preventionfenetre.maxsize(400, 400)
#Place la fenêtre au centre de l'écran
preventionfenetre.eval('tk::PlaceWindow . center')
# Attend que la fenêtre se ferme pour continuer le code
preventionfenetre.wait_window(preventionfenetre)
PreventionDemineur()
# Crée la fenêtre des paramètres du démineur
def parDemineur():
parfenetre = Tk()
#Assigne pour titre à la fenêtre "Paramètres du Jeu du Démineur"
parfenetre.title("Paramètres du Jeu du démineur")
#Image du démineur
Pardemineursource = ImageTk.PhotoImage(master=parfenetre, file='ParDemineur.png')
#Affiche l'image
Pardemineurimg = Label(parfenetre, image = Pardemineursource)
#Gère la position du message de prévention
Pardemineurimg.pack()
#Change la taille afin que la fenêtre puisse tout afficher
parfenetre.minsize(400, 900)
parfenetre.maxsize(400, 400)
# Gère la création de la fenêtre avec sa largeur, sa hauteur, son fond)
canvas = Canvas(parfenetre , width =750, height=500 , background='white')
canvas.pack()
#Place la fenêtre au centre de l'écran
parfenetre.eval('tk::PlaceWindow . center')
# Utilise CTkButton à la place du bouton de Tkinter, permettant plus de personnalisation. Le bouton une fois appuyé, permet de fermer la fenêtre des paramètres.
boutonstart = customtkinter.CTkButton(master=parfenetre, text="Commencer à jouer !", font=("helvetica", 20, "bold"), command=parfenetre.destroy)
#Situe le bouton dans la fenêtre ainsi que sa taille
boutonstart.place(relx=0.5, rely=0.9,relheight=0.125, relwidth=0.3, anchor=CENTER)
# Utilise CTkButton à la place du bouton de Tkinter, permettant plus de personnalisation. Le bouton une fois appuyé, permet de fermer la fenêtre des paramètres.
boutonfermer = customtkinter.CTkButton(parfenetre, text="Quitter",fg_color="red", font=("helvetica", 20, "bold"), command=sys.exit)
#Situe le bouton dans la fenêtre ainsi que sa taille
boutonfermer.place(relx=0.94, rely=0.08,relheight=0.05, relwidth=0.08, anchor=CENTER)
#Affiche le texte de prévention avec ses caractéristiques
ContenuPar = Label(parfenetre, text="Choix de la taille du terrain", font=("helvetica", 10, "bold"))
#Gère la position du message de difficulté
ContenuPar.place(x=650, y=350, anchor=CENTER)
#THE PROBLEM STARTS BELOW THIS---------------------------------------------------------
#Slider pour la taille du terrain
# slider valeur actuelle
valeur_actuelle = IntVar()
def obtenir_valeur_actuelle():
valeur = format(valeur_actuelle.get())
return format(valeur_actuelle.get())
def changement_slider(event):
valeur_label.configure(text=obtenir_valeur_actuelle())
# slider
slider = ttk.Scale(parfenetre,from_=2,to=10,orient='horizontal',command=changement_slider,variable=valeur_actuelle)
slider.place(x=650, y=375, anchor=CENTER)
# label du texte Valeur Actuelle
valeur_actuelle_label = ttk.Label(parfenetre,text='Valeur Actuelle:')
valeur_actuelle_label.place(x=650, y=425, anchor=CENTER)
# label de la valeur en elle même
valeur_label = ttk.Label(parfenetre,text=obtenir_valeur_actuelle())
valeur_label.place(x=700, y=425, anchor=CENTER)
valeur = int(obtenir_valeur_actuelle())
print(valeur)
#importation de l'image de défaite
imagePerdant=Image.open("Game_Over.png")
#importation de l'image de victoire
imageGagnant=Image.open("Victory.jpg")
#le terme miner veut dire creuser
terrainMines = []
nombre_colonne = valeur
nombre_ligne = valeur
Blocs_miner = 0
nombre_tnt = 5
Blocs_à_miner = nombre_colonne * nombre_ligne - nombre_tnt
nbr_col_ligne = nombre_colonne * nombre_ligne
#Force la fenêtre à être ouverte en pleine écran
parfenetre.attributes('-fullscreen', True)
# Attend que la fenêtre se ferme pour continuer le code
parfenetre.wait_window(parfenetre)
#création du terrain miné
# permet de creer une liste qui pour chaque bloc (rangée et colonne) entre des nombres aleatoires.
def CreeTerrainMine(nombre_colonne, nombre_ligne):
terrainMines = [[0 for colonne in range(nombre_colonne)]for ligne in range(nombre_ligne)]
TNT=[]
while len(TNT)<nombre_tnt:
# calcul un nombre aleatoire
n = random.randint(0,nbr_col_ligne-1)
if not n in TNT:
TNT.append(n)
ligne=n//nombre_ligne
colonne=n% nombre_colonne
# positionne la tnt
terrainMines[ligne][colonne]="TNT"
#permet de calculer les tnt voisines
for i in range (nombre_ligne):
for j in range (nombre_colonne):
#on regarde les 8 cases voisines et on ajoute 1 car il y a une tnt
if terrainMines[i][j]=="TNT":
for ii in range(i-1,i+2):
#on ajoute 2 car le 2 est exclus du cadre
for jj in range(j-1,j+2):
if 0<=ii<nombre_ligne and 0<jj<nombre_colonne and terrainMines[ii][jj]!="TNT":
terrainMines[ii][jj]=terrainMines[ii][jj]+1
for iii in terrainMines:
print(iii)
return terrainMines
#action du boutton + Affichage des blocs sur l'écran
def bouton(Cadre, terrainMines):
for nombre_Rangee in range(nombre_ligne):
for nombre_colonnes in range(nombre_colonne):
bloc = Button(Cadre, text=terrainMines[nombre_Rangee][nombre_colonnes], font=("Courier", 15),height=2, width=5, fg="#008737",bg="#008737", activebackground="#008737",activeforeground="#008737")
bloc.grid(row = nombre_Rangee, column = nombre_colonnes )
#permet de lier la fonction boutonClic au clic gauche de la souris
bloc.bind ("<Button-1>", Clic)
bloc.bind ("<Button-3>", Drapeau)
def Clic(event):
bouton = event.widget
Explosion(bouton)
def Drapeau(event):
bouton = event.widget
Pose_Drapeau(bouton)
def Pose_Drapeau(bouton):
bouton.configure(disabledforeground="#153D3A",bg='#153D3A')
if (bouton['state'] == "normal"):
bouton['state'] = "disabled"
else:
bouton['state'] = "normal"
bouton.configure(fg="#008737",bg='#008737')
# avec les valeurs des blocs, cela cherche si le jeu doit continuer ou s'il doit s'arrêter
def Explosion(bouton):
# permet de récupérer la valeur du bloc (le texte)
valeurBouton = bouton.cget("text")
#affiche la valeur du bloc et une tnt est repéré
if (valeurBouton == "TNT"):
#change la couleur du bloc en rouge
bouton.configure(fg="white",bg='#78020e')
# affichage de l'image de défaite
imagePerdant.show()
exit(1)
# aucune tnt n'est repéré
else:
#permet de récupérer la couleur du texte du bloc
couleurPolice = bouton.cget("fg")
# si la couleur reste la meme cela veut dire que le bloc n'a pas été miné
if (couleurPolice == '#008737'):
# l'instruction global informe que la variable qui est utilisée à l'intérieur de la fonction est la même que celle qui est définie à l'extérieur de la fonction
global Blocs_miner
# augmente le nombre de clic
Blocs_miner += 1
# change la couleur de la police afin de pouvoir voir le chiffre et change le fond du bloc pour montré que le bloc est miné
bouton.configure(foreground="white",bg='#66370E')
# tous les blocs sans tnt sont creusés
if (Blocs_miner == Blocs_à_miner):
# affiche l'image de victoire
imageGagnant.show()
exit(0)
def jouerDemineur():
fenetre = Tk()
fenetre.eval('tk::PlaceWindow . center')
#affiche un titre à la fenêtre
fenetre.title("Jeu du démineur")
#Force la fenêtre à être ouverte en pleine écran
fenetre.attributes('-fullscreen', True)
#le widget frame est utile pour le regrouppement et l'organisation d'autres widget
Cadre = Frame(fenetre, borderwidth=100, bg="#153D3A")
Cadre.pack(expand=1)
terrainMine = CreeTerrainMine(nombre_colonne, nombre_ligne)
bouton(Cadre,terrainMine)
Cadre.bind('<Button-3>', Drapeau)
# Utilise CTkButton à la place du bouton de Tkinter, permettant plus de personnalisation. Le bouton une fois appuyé, permet de fermer la fenêtre des paramètres.
boutonfermer2 = customtkinter.CTkButton(master=fenetre, text="Quitter",fg_color="red", font=("helvetica", 20, "bold"), command=fenetre.destroy)
#Gère la position du message de difficulté
boutonfermer2.place(relx=0.95, rely=0.05, anchor=CENTER)
jouerDemineur()
fenetre.mainloop()
parDemineur()
When I got the error I tried to use print(valeur)
to see what was wrong with it since this is the problematic value and that's when I saw that even when putting the slider at 10, it always returned me "0".
I tried searching in the code but I couldn't find anything.
I would be really grateful if someone could help me as I'm clearly no professionnal in python.
Aucun commentaire:
Enregistrer un commentaire