-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfive_in_a_row.py
122 lines (103 loc) · 3.94 KB
/
five_in_a_row.py
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
import tkinter as tk
root = tk.Tk()
root.title("Five in a Row / Caro Game")
WIDTH = root.winfo_screenwidth()
HEIGHT = root.winfo_screenheight()
CELL = 50
ROWS = HEIGHT // CELL
COLS = WIDTH // CELL
TURN = "X"
WINNING_CONDITION = 3 # Number of wins to end the game
# Board state
board = [[None for _ in range(COLS)] for _ in range(ROWS)]
# Winners state
winners = []
canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT)
canvas.pack()
def draw_board():
for i in range(COLS):
canvas.create_line(0, CELL * i, WIDTH, CELL * i, fill="black") # Horizontal lines
canvas.create_line(CELL * i, 0, CELL * i, HEIGHT, fill="black") # Vertical lines
def play(event):
global TURN, winners
col = event.x // CELL
row = event.y // CELL
x_center = col * CELL + CELL // 2
y_center = row * CELL + CELL // 2
if board[row][col] is not None:
return
board[row][col] = TURN
canvas.create_text(x_center, y_center, text=TURN, font=("Arial", 20))
TURN = "X" if TURN == "O" else "O"
# Check if there is a winner
winner = detect_winner()
if winner is not None:
TURN = "X" if winner == "O" else "O" # Switch turn based on last winner
winners.append(winner)
canvas.create_text(100, 100, text=f"{winner} wins!", font=("Arial", 50), anchor="w")
if winners.count(winner) == WINNING_CONDITION:
# End the game and display the result
x_wins = winners.count("X")
o_wins = winners.count("O")
canvas.create_text(
100, 200, text=f"{winner} wins the game!", font=("Arial", 50), anchor="w"
)
canvas.create_text(
100, 300, text=f"Score: {x_wins} - {o_wins}", font=("Arial", 30), anchor="w"
)
canvas.unbind("<Button-1>")
canvas.bind("<Button-1>", lambda _: root.quit())
return
canvas.unbind("<Button-1>")
canvas.bind("<Button-1>", restart)
return
# Helper function to check if the winner is blocked
def is_blocked(row, col, current) -> bool:
if row < 0 or row > ROWS or col < 0 or col > COLS:
return False
return board[row][col] is not None and board[row][col] != current
def detect_winner() -> str | None:
for row in range(ROWS):
for col in range(COLS):
current = board[row][col]
if current is None:
continue
# Check horizontal
if col + 4 < COLS and all(board[row][col + i] == current for i in range(5)):
if is_blocked(row, col - 1, current) and is_blocked(row, col + 5, current):
continue
return current
# Check vertical
if row + 4 < ROWS and all(board[row + i][col] == current for i in range(5)):
if is_blocked(row - 1, col, current) and is_blocked(row + 5, col, current):
continue
return current
# Check diagonal from left to right
if (
row + 4 < ROWS
and col + 4 < COLS
and all(board[row + i][col + i] == current for i in range(5))
):
if is_blocked(row - 1, col - 1, current) and is_blocked(row + 5, col + 5, current):
continue
return current
# Check diagonal from right to left
if (
row + 4 < ROWS
and col - 4 >= 0
and all(board[row + i][col - i] == current for i in range(5))
):
if is_blocked(row - 1, col + 1, current) and is_blocked(row + 5, col - 5, current):
continue
return current
return None
def restart(_event):
global board, TURN
board = [[None for _ in range(COLS)] for _ in range(ROWS)]
canvas.delete("all")
draw_board()
canvas.unbind("<Button-1>")
canvas.bind("<Button-1>", play)
draw_board()
canvas.bind("<Button-1>", play)
root.mainloop()