Finished the homework

This commit is contained in:
2025-11-21 13:54:08 +01:00
parent dc852987b7
commit 6a4934969b
2 changed files with 117 additions and 84 deletions

View File

@@ -1,46 +0,0 @@
import time as tm
import turtle as tl
import board as bd
screen = tl.Screen()
screen.setup(width=800, height=600)
screen.tracer(0, 0)
def draw_board(board: bd.Grid):
tl.clear() # instead of resetscreen()
tl.hideturtle()
tl.penup()
if not board:
screen.update()
return
cell_size = 60
rows = len(board)
cols = max(len(line) for line in board)
origin_x = -cols * cell_size / 2
origin_y = rows * cell_size / 2
for i, line in enumerate(board):
for j, cell in enumerate(line):
x = origin_x + j * cell_size
y = origin_y - i * cell_size
tl.goto(x, y)
tl.pendown()
for _ in range(4):
tl.forward(cell_size)
tl.right(90)
tl.penup()
tl.goto(x + cell_size / 2, y - 0.8 * cell_size)
tl.write(
cell, align="center", font=("Courier", int(cell_size / 2), "normal")
)
screen.update()
tm.sleep(100)

View File

@@ -1,72 +1,151 @@
import board as bd import board as bd
import drawer as dw
# 4.8.1.1 : création de la grille
def creerGrille(N, M, v=0): def creerGrille(N, M, v=0):
"""Crée une grille N x M initialisée à la valeur v."""
return bd.gen_grid(N, M, v) return bd.gen_grid(N, M, v)
def placerMine(grid, X): # 4.8.1.2 : placement des mines
def placerMines(grid, X):
"""Place X mines (valeur 1) dans la grille à des positions aléatoires."""
bd.place_mine(grid, X) bd.place_mine(grid, X)
def TestMine(grid, i, j): # 4.8.2.1 : test d'une mine
def testMine(grid, i, j):
"""Renvoie True s'il y a une mine à la case (i, j)."""
return bd.test_mine(grid, (i, j)) return bd.test_mine(grid, (i, j))
# 4.8.2.2 : compte des mines voisines
def compteMinesVoisines(positionsMines, i, j): def compteMinesVoisines(positionsMines, i, j):
return bd.get_neighbours((i, j), positionsMines) """Renvoie le nombre de mines voisines de la case (i, j)."""
return bd.count_near_mines(positionsMines, (i, j))
# 4.8.3.1 : affichage de la solution
def afficheSolution(positionsMines): def afficheSolution(positionsMines):
"""Affiche la grille solution : '-' pour vide, '*' pour mine."""
bd.display_mines(positionsMines) bd.display_mines(positionsMines)
# 4.8.3.2 : affichage du jeu
def afficheJeu(positionsMines, casesDevoilees): def afficheJeu(positionsMines, casesDevoilees):
"""
Affiche la grille telle que vue par le joueur :
'?' pour inconnue, '*' pour mine découverte,
nombre de mines voisines autrement.
"""
bd.display_known(positionsMines, casesDevoilees) bd.display_known(positionsMines, casesDevoilees)
def getCoords(known_grid, N, M): # 4.8.4.1 : lecture filtrée du nombre de mines
return bd.get_coords(known_grid) def getNbMines(N, M):
"""
Lit et renvoie un nombre de mines X tel que 1 <= X <= N*M - 1.
Évite le cas où le placement serait impossible.
"""
max_mines = N * M - 1
nb = 0
while not (1 <= nb <= max_mines):
try:
nb = int(input(f"Nombre de mines (entre 1 et {max_mines}) ? "))
except ValueError:
nb = 0
return nb
def main2(): # 4.8.4.2 : lecture filtrée des coordonnées
grid = creerGrille(8, 8) def getCoords(casesDevoilees, N, M):
placerMine(grid, 10) """
dw.draw_board(grid) Demande à l'utilisateur des coordonnées (ligne, colonne) :
- dans les bornes,
- sur une case non encore dévoilée.
Ne redemande que la coordonnée incorrecte.
Renvoie (i, j) correctes.
"""
max_i = N - 1
max_j = M - 1
i = -1
j = -1
while True:
# Lecture de la ligne
while not (0 <= i <= max_i):
try:
if i == -1:
i = int(input("Ligne? "))
else:
i = int(input(f"Ligne < {N} svp ? "))
except ValueError:
i = -1
while not (0 <= j <= max_j):
try:
if j == -1:
j = int(input("Colonne? "))
else:
j = int(input(f"Colonne < {M} svp ? "))
except ValueError:
j = -1
if not casesDevoilees[i][j]:
return i, j
print("Case deja devoilee, recommence")
i = -1
j = -1
def main() -> None: def main():
"""
Programme principal :
- initialise une grille,
- demande le nombre de mines,
- lance la boucle de jeu,
- s'arrête quand le joueur perd ou gagne.
"""
N, M = 8, 8 N, M = 8, 8
grid = creerGrille(N, M) grid = creerGrille(N, M)
mines_number = 0 nb_mines = getNbMines(N, M)
while not (0 < mines_number <= N * M - 1): placerMines(grid, nb_mines)
mines_number = int(
input(f"Please input a number of mines between 0-{N * M - 1}: ") # Grille des cases dévoilées : N lignes, M colonnes
) casesDevoilees = [[False for _ in range(M)] for _ in range(N)]
# In theory we should put the line below after the first pick on the board or else the user could loose on their first attempt
placerMine(grid, mines_number) nb_coups = 0
known_grid = [[False for _ in range(N)] for _ in range(M)] en_cours = True
going = True
while going: while en_cours:
afficheJeu(grid, known_grid) nb_coups += 1
y, x = getCoords(known_grid, N, M) print(f"Coup numero {nb_coups}")
known_grid[y][x] = True afficheJeu(grid, casesDevoilees)
# If the user lost: print("A toi de jouer !")
if TestMine(grid, y, x):
print("You lost") i, j = getCoords(casesDevoilees, N, M)
afficheJeu(grid, known_grid) casesDevoilees[i][j] = True
print("Here is the solution: ")
# Mine touchée -> perdu
if testMine(grid, i, j):
print("Perdu, touche une mine !")
afficheJeu(grid, casesDevoilees)
print("La solution etait :")
afficheSolution(grid) afficheSolution(grid)
going = False en_cours = False
# If he won
elif bd.is_end(known_grid, grid):
print("Congrats ! You've just won")
going = False
else: else:
linked = bd.linked_cells(grid, known_grid, (y, x)) # Expansion façon démineur (bonus, pas demandé mais utile)
for coord in linked: linked = bd.linked_cells(grid, casesDevoilees, (i, j))
known_grid[coord[1]][coord[0]] = True for cy, cx in linked:
casesDevoilees[cy][cx] = True
# Fin de partie
if bd.is_end(casesDevoilees, grid):
afficheJeu(grid, casesDevoilees)
print(f"Tu as gagne en {nb_coups} coups, bravo !")
en_cours = False
main2() if __name__ == "__main__":
main()