mirror of
https://github.com/Fare-spec/cours.git
synced 2025-12-07 10:50:36 +00:00
Finished the homework
This commit is contained in:
@@ -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)
|
|
||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user