File size: 4,970 Bytes
f216aac c82ad6c f216aac 0cadddf 3cc6861 0cadddf 3cc6861 0cadddf f216aac c82ad6c f216aac 3cc6861 f216aac 3cc6861 c82ad6c 0cadddf c82ad6c 0cadddf 3cc6861 f216aac 3cc6861 0cadddf 3cc6861 0cadddf 3cc6861 0cadddf f216aac 0cadddf 3cc6861 0cadddf 3cc6861 f216aac 3cc6861 c82ad6c 0cadddf 3cc6861 0cadddf 3cc6861 0cadddf 3cc6861 f216aac 3cc6861 f216aac 3cc6861 0cadddf 3cc6861 0cadddf 3cc6861 0cadddf 3cc6861 0cadddf 3cc6861 0cadddf c82ad6c 0cadddf 3cc6861 0cadddf 3cc6861 0cadddf 3cc6861 c82ad6c 3cc6861 c82ad6c 0cadddf c82ad6c f216aac c82ad6c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import random
import gradio as gr
FILES = "abcdefgh"
RANKS = "12345678"
# Pièces Unicode
PIECES = {
("W", "p"): "♙", ("B", "p"): "♟",
("W", "t"): "♖", ("B", "t"): "♜",
("W", "c"): "♘", ("B", "c"): "♞",
("W", "f"): "♗", ("B", "f"): "♝",
("W", "R"): "♕", ("B", "R"): "♛",
("W", "k"): "♔", ("B", "k"): "♚",
}
def in_bounds(x, y):
return 0 <= x < 8 and 0 <= y < 8
def initial_board():
b = [[None for _ in range(8)] for _ in range(8)]
white_row = ['t', 'c', 'f', 'R', 'k', 'f', 'c', 't']
for x, p in enumerate(white_row):
b[x][0] = ('W', p)
b[x][1] = ('W', 'p')
black_row = ['t', 'c', 'f', 'R', 'k', 'f', 'c', 't']
for x, p in enumerate(black_row):
b[x][7] = ('B', p)
b[x][6] = ('B', 'p')
return b
def sq_to_coords(sq):
sq = sq.lower()
return FILES.index(sq[0]), RANKS.index(sq[1])
def coords_to_sq(x, y):
return FILES[x] + RANKS[y]
def generate_mines(board, density=0.15):
empty = [(x, y) for x in range(8) for y in range(8) if board[x][y] is None]
n = max(1, int(len(empty) * density))
mines = set(random.sample(empty, n))
return mines, set(), set()
def count_adjacent_mines(x, y, mines):
return sum((nx, ny) in mines for nx in range(x-1, x+2) for ny in range(y-1, y+2)
if (nx, ny) != (x, y) and in_bounds(nx, ny))
def render_board(board, mines, revealed, exploded, hints):
grid = []
for y in range(7, -1, -1):
row = []
for x in range(8):
if (x, y) in exploded:
cell = "💥"
elif board[x][y]:
cell = PIECES[board[x][y]]
elif (x, y) in revealed:
cell = str(hints.get((x, y), 0)) if hints.get((x, y), 0) > 0 else "·"
else:
cell = "⬜" if (x + y) % 2 else "⬛"
row.append(cell)
grid.append(row)
return "\n".join(" ".join(row) for row in grid)
def apply_move(board, mines, revealed, exploded, hints, move, turn):
from_sq, to_sq = move
fx, fy = sq_to_coords(from_sq)
tx, ty = sq_to_coords(to_sq)
piece = board[fx][fy]
if not piece or piece[0] != turn:
return board, "Coup invalide"
if not in_bounds(tx, ty):
return board, "Coup hors du plateau"
# Déplacement
board[fx][fy] = None
if (tx, ty) in mines:
exploded.add((tx, ty))
text = f"💥 {from_sq}->{to_sq} : Mine ! Pièce détruite."
else:
board[tx][ty] = piece
revealed.add((tx, ty))
count = count_adjacent_mines(tx, ty, mines)
hints[(tx, ty)] = count
text = f"{from_sq}->{to_sq} (zone sûre, {count} mines autour)"
return board, text
def new_game(density):
board = initial_board()
mines, revealed, exploded = generate_mines(board, density)
hints = {}
state = dict(board=board, mines=mines, revealed=revealed,
exploded=exploded, hints=hints, turn="W", log=["Nouvelle partie"])
return render_board(board, mines, revealed, exploded, hints), "\n".join(state["log"]), state
def play_move(move_input, state):
if not state:
return "Pas de partie", "Commence une nouvelle partie", None
move_input = move_input.strip().lower()
if len(move_input) != 4:
return render_board(**state), "Format invalide (ex: e2e4)", state
from_sq, to_sq = move_input[:2], move_input[2:]
board, text = apply_move(state["board"], state["mines"], state["revealed"],
state["exploded"], state["hints"], (from_sq, to_sq), state["turn"])
state["board"] = board
state["log"].append(text)
state["turn"] = "B" if state["turn"] == "W" else "W"
return render_board(board, state["mines"], state["revealed"], state["exploded"], state["hints"]), "\n".join(state["log"]), state
with gr.Blocks() as demo:
gr.Markdown("# ♟️ ChessMine — Échecs + 💣 Démineur")
gr.Markdown("Deux joueurs alternent leurs coups. Si une pièce marche sur une mine 💥 elle explose, sinon la case révèle le nombre de mines autour 🔢.")
density = gr.Slider(0.05, 0.4, value=0.15, label="Densité de mines")
start = gr.Button("Nouvelle partie")
board_box = gr.Textbox(label="Plateau", lines=10, interactive=False)
move_in = gr.Textbox(label="Coup (ex: e2e4)")
play = gr.Button("Jouer")
log_box = gr.Textbox(label="Journal", lines=8, interactive=False)
state = gr.State()
start.click(new_game, inputs=[density], outputs=[board_box, log_box, state])
play.click(play_move, inputs=[move_in, state], outputs=[board_box, log_box, state])
gr.Markdown("**Règles :**\n- Entrez vos coups en format `e2e4`.\n- Si la case cible contient une 💣 → explosion !\n- Sinon, un nombre indique combien de mines se trouvent autour.\n- Les pièces utilisent les symboles Unicode standards ♙♟♖♜♘♞♗♝♕♛♔♚.")
if __name__ == "__main__":
demo.launch()
|