"""Module providing Random variable generators."""
import random
import json
import os
import time
from statistiques import Statistiques
[docs]
class Demineur:
"""Class representing a Deminer game"""
def __init__(self, fichier_sauvegarde='demineur.json', difficulte='moyen'):
"""
Initialize the game with a grid and place mines based on difficulty level.
:param difficulte: Difficulty level of the game ('facile', 'moyen', 'difficile').
:raises ValueError: If the difficulty level is not one of 'facile', 'moyen', or 'difficile'.
"""
if difficulte not in ['facile', 'moyen', 'difficile']:
raise ValueError("Le niveau de difficulté doit être 'facile', 'moyen' ou 'difficile'.")
if difficulte == 'facile':
self.taille = 8
self.nombre_mines = 10
elif difficulte == 'difficile':
self.taille = 16
self.nombre_mines = 40
else: # moyen
self.taille = 10
self.nombre_mines = 20
self.grille = [['■' for _ in range(self.taille)] for _ in range(self.taille)]
self.grille_visible = [['■' for _ in range(self.taille)] for _ in range(self.taille)]
self.statistiques = Statistiques()
self.fichier_sauvegarde = fichier_sauvegarde
self.marques = set()
self.__placer_mines()
self.__calculer_indices()
self.mouvements = 0
def __placer_mines(self):
mines_placees = 0
while mines_placees < self.nombre_mines:
x = random.randint(0, self.taille - 1)
y = random.randint(0, self.taille - 1)
if self.grille[y][x] != 'M':
self.grille[y][x] = 'M'
mines_placees += 1
def __calculer_indices(self):
for y in range(self.taille):
for x in range(self.taille):
if self.grille[y][x] == 'M':
continue
mines_autour = 0
for dx in range(y - 1, y + 2):
for dy in range(x - 1, x + 2):
nx, ny = x + dx, y + dy
if nx < 0 or ny < 0 or nx >= self.taille or ny >= self.taille:
continue
if self.grille[ny][nx] == 'M':
mines_autour += 1
self.grille[y][x] = str(mines_autour)
[docs]
def decouvrir_cases(self, x, y):
"""A Function to uncover a cell"""
# Vérifier si les coordonnées sont dans les limites de la grille
if not (0 <= x < self.taille and 0 <= y < self.taille):
return
if self.grille_visible[y][x] == 'F':
self.grille_visible[y][x] = self.grille[y][x]
if self.grille_visible[y][x] != '■':
return
self.grille_visible[y][x] = self.grille[y][x]
self.mouvements += 1
if self.grille[y][x] == '0':
self.decouvrir_cases(x - 1, y)
self.decouvrir_cases(x + 1, y)
self.decouvrir_cases(x, y - 1)
self.decouvrir_cases(x, y + 1)
[docs]
def afficher_grille(self):
"""A Function to show the game's board"""
print(" "+ " ".join([str(i) for i in range(self.taille)]))
for idx, ligne in enumerate(self.grille_visible):
print(f"{idx:2}| " + ' '.join(ligne) + " |")
mines_restantes = self.nombre_mines - sum(row.count('M') for row in self.grille_visible)
if self.statistiques.timer_start:
temps_ecoule = int(time.time() - self.statistiques.timer_start)
else:
temps_ecoule = 0
hours, remainder = divmod(temps_ecoule, 3600)
minutes, seconds = divmod(remainder, 60)
print(
f"\nMines restantes: {mines_restantes} | "
f"Mouvements: {self.mouvements} | "
f"Temps: {hours:02}:{minutes:02}:{seconds:02}"
)
[docs]
def charger_jeu(self):
"""
Load the game state from a JSON file.
"""
if os.path.exists(self.fichier_sauvegarde):
with open(self.fichier_sauvegarde, 'r', encoding='utf-8') as file:
data = json.load(file)
self.taille = data.get('taille', 10)
self.nombre_mines = data.get('nombre_mines', 10)
self.grille = data.get(
'grille', [['.' for _ in range(self.taille)] for _ in range(self.taille)]
)
self.grille_visible = data.get(
'grille_visible',
[['.' for _ in range(self.taille)] for _ in range(self.taille)]
)
[docs]
def marquer_case(self, x, y):
""" Mark or unmark a cell with a flag. """
if not (0 <= x < self.taille and 0 <= y < self.taille):
return
if self.grille_visible[y][x] == 'F':
self.grille_visible[y][x] = '.'
elif self.grille_visible[y][x] == '.':
self.grille_visible[y][x] = 'F'
else:
print("La case est déjà découverte et ne peut pas être marquée.")
[docs]
def sauvegarder_jeu(self):
"""
Save the current game state to a JSON file.
"""
data = {
'taille': self.taille,
'nombre_mines': self.nombre_mines,
'grille': self.grille,
'grille_visible': self.grille_visible,
}
with open(self.fichier_sauvegarde, 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=4)
print(f"Jeu sauvegardé dans {self.fichier_sauvegarde}.")
[docs]
def jouer(self):
"""A Function to launch the game."""
game_in_progress = True
self.statistiques.start_timer()
while game_in_progress:
print("\n [ Bienvenue au Démineur ! ] \n")
self.afficher_grille()
print("Tapez 'save' pour sauvegarder la partie ou entrez les coordonnées.")
choix = input(
"Entrez 'f x y' pour marquer/démarquer, 'x y' pour découvrir, "
"ou 'save' pour sauvegarder : "
).split()
if choix[0].lower() == 'save':
self.sauvegarder_jeu()
continue
try:
if len(choix) == 3 and choix[0] == 'f':
# Marquer/démarquer une case
x, y = map(int, choix[1:])
self.marquer_case(x, y)
continue
if len(choix) == 2:
# Découvrir une case
x, y = map(int, choix)
else:
print(
"Erreur : entrez 'f x y' pour marquer/démarquer, ou 'x y' pour découvrir."
)
continue
except ValueError:
print("Coordonnées invalides. Veuillez réessayer.")
continue
if self.grille[y][x] == 'M':
# Afficher la grille avec les mines visibles
self.decouvrir_cases(x, y)
self.afficher_grille()
print("Perdu !")
# Fin du jeu
game_in_progress = False
temps_ecoule = self.statistiques.stop_timer()
self.statistiques.record_loss()
break
self.decouvrir_cases(x, y)
if sum(row.count('■') for row in self.grille_visible) == self.nombre_mines:
print("Gagne !")
#End the game
game_in_progress = False
temps_ecoule = self.statistiques.stop_timer()
self.statistiques.record_victory()
break
print(f"Temps écoulé : {temps_ecoule:.2f} secondes")
self.statistiques.display_statistics()
# Demande si le joueur souhaite recommencer une partie
while True:
restart = input("Voulez-vous recommencer une partie ? (oui/non) : ").lower()
if restart == 'oui':
nouveau_jeu = Demineur(self.nombre_mines)
nouveau_jeu.jouer()
break
if restart == 'non':
print("Partie terminée !")
break
print("Réponse invalide, veuillez répondre par 'oui' ou 'non'.")
if __name__ == "__main__":
niveau_difficulte = input("Choisissez un niveau de difficulte (facile, moyen, difficile): ")
try:
jeu = Demineur(niveau_difficulte)
jeu.charger_jeu()
jeu.jouer()
except ValueError as e:
print(e)