Skip to content

Commit 8e2221f

Browse files
committed
Add: Dots & Boxes AI game with web integration
1 parent 6e36a82 commit 8e2221f

3 files changed

Lines changed: 957 additions & 0 deletions

File tree

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
import random
2+
import time
3+
4+
# Colors
5+
RESET = "\033[0m"
6+
BLUE = "\033[94m"
7+
RED = "\033[91m"
8+
GREEN = "\033[92m"
9+
YELLOW = "\033[93m"
10+
CYAN = "\033[96m"
11+
MAGENTA = "\033[95m"
12+
BOLD = "\033[1m"
13+
14+
# Title
15+
print(BOLD + CYAN)
16+
print("=" * 70)
17+
print("🔲 DOTS & BOXES AI - ADVANCED VERSION 🔲")
18+
print("=" * 70)
19+
print(RESET)
20+
21+
print(YELLOW + "🎮 GAME MODES" + RESET)
22+
print("1. 👥 Player vs Player")
23+
print("2. 🤖 Player vs AI")
24+
25+
mode = input("\n🎯 Select mode (1 or 2): ")
26+
27+
if mode not in ['1', '2']:
28+
print(RED + "\n❌ Invalid mode selected!" + RESET)
29+
exit()
30+
31+
# AI difficulty
32+
ai_difficulty = "easy"
33+
34+
if mode == '2':
35+
print("\n🧠 AI LEVELS")
36+
print("1. 🟢 Easy")
37+
print("2. 🟡 Intermediate")
38+
print("3. 🔴 Hard")
39+
40+
diff = input("\n🎯 Select AI difficulty: ")
41+
42+
if diff == '1':
43+
ai_difficulty = 'easy'
44+
elif diff == '2':
45+
ai_difficulty = 'medium'
46+
elif diff == '3':
47+
ai_difficulty = 'hard'
48+
else:
49+
print(RED + "\n❌ Invalid difficulty!" + RESET)
50+
exit()
51+
52+
# Board size
53+
size = input("\n📏 Enter board size (2-8): ")
54+
55+
if not size.isdigit():
56+
print(RED + "\n❌ Invalid size!" + RESET)
57+
exit()
58+
59+
size = int(size)
60+
61+
if size < 2 or size > 8:
62+
print(RED + "\n❌ Size must be between 2 and 8!" + RESET)
63+
exit()
64+
65+
# Board data
66+
horizontal_lines = [[False for _ in range(size)] for _ in range(size + 1)]
67+
vertical_lines = [[False for _ in range(size + 1)] for _ in range(size)]
68+
boxes = [[' ' for _ in range(size)] for _ in range(size)]
69+
70+
player_score = 0
71+
computer_score = 0
72+
current_player = 1
73+
total_boxes = size * size
74+
75+
76+
def print_board():
77+
print("\n")
78+
for row in range(size):
79+
line = ""
80+
for col in range(size):
81+
line += "•"
82+
if horizontal_lines[row][col]:
83+
if boxes[row][col] == 'P':
84+
line += BLUE + "━━" + RESET
85+
elif boxes[row][col] == 'A':
86+
line += RED + "━━" + RESET
87+
else:
88+
line += "━━"
89+
else:
90+
line += " "
91+
line += "•"
92+
print(line)
93+
94+
line = ""
95+
for col in range(size):
96+
if vertical_lines[row][col]:
97+
if boxes[row][col] == 'P':
98+
line += BLUE + "┃" + RESET
99+
elif boxes[row][col] == 'A':
100+
line += RED + "┃" + RESET
101+
else:
102+
line += "┃"
103+
else:
104+
line += " "
105+
106+
if boxes[row][col] == 'P':
107+
line += BLUE + "■ " + RESET
108+
elif boxes[row][col] == 'A':
109+
line += RED + "■ " + RESET
110+
else:
111+
line += " "
112+
113+
if vertical_lines[row][size]:
114+
line += "┃"
115+
print(line)
116+
117+
line = ""
118+
for col in range(size):
119+
line += "•"
120+
line += "━━" if horizontal_lines[size][col] else " "
121+
line += "•"
122+
print(line)
123+
print("\n")
124+
125+
126+
def check_boxes(symbol):
127+
global player_score, computer_score
128+
completed = False
129+
for row in range(size):
130+
for col in range(size):
131+
if boxes[row][col] == ' ':
132+
top = horizontal_lines[row][col]
133+
bottom = horizontal_lines[row + 1][col]
134+
left = vertical_lines[row][col]
135+
right = vertical_lines[row][col + 1]
136+
if top and bottom and left and right:
137+
boxes[row][col] = symbol
138+
completed = True
139+
if symbol == 'P':
140+
player_score += 1
141+
else:
142+
computer_score += 1
143+
return completed
144+
145+
146+
def get_available_moves():
147+
moves = []
148+
for row in range(size + 1):
149+
for col in range(size):
150+
if not horizontal_lines[row][col]:
151+
moves.append(('h', row, col))
152+
for row in range(size):
153+
for col in range(size + 1):
154+
if not vertical_lines[row][col]:
155+
moves.append(('v', row, col))
156+
return moves
157+
158+
159+
def count_box_sides(row, col):
160+
count = 0
161+
if horizontal_lines[row][col]:
162+
count += 1
163+
if horizontal_lines[row + 1][col]:
164+
count += 1
165+
if vertical_lines[row][col]:
166+
count += 1
167+
if vertical_lines[row][col + 1]:
168+
count += 1
169+
return count
170+
171+
172+
def simulate_move(move):
173+
direction, row, col = move
174+
if direction == 'h':
175+
horizontal_lines[row][col] = True
176+
else:
177+
vertical_lines[row][col] = True
178+
179+
180+
def undo_move(move):
181+
direction, row, col = move
182+
if direction == 'h':
183+
horizontal_lines[row][col] = False
184+
else:
185+
vertical_lines[row][col] = False
186+
187+
188+
def completes_box(move):
189+
simulate_move(move)
190+
for row in range(size):
191+
for col in range(size):
192+
if count_box_sides(row, col) == 4:
193+
undo_move(move)
194+
return True
195+
undo_move(move)
196+
return False
197+
198+
199+
def creates_danger(move):
200+
simulate_move(move)
201+
for row in range(size):
202+
for col in range(size):
203+
if count_box_sides(row, col) == 3:
204+
undo_move(move)
205+
return True
206+
undo_move(move)
207+
return False
208+
209+
210+
def ai_move():
211+
available_moves = get_available_moves()
212+
213+
if ai_difficulty == 'easy':
214+
return random.choice(available_moves)
215+
216+
elif ai_difficulty == 'medium':
217+
for move in available_moves:
218+
if completes_box(move):
219+
return move
220+
safe_moves = [m for m in available_moves if not creates_danger(m)]
221+
return random.choice(safe_moves) if safe_moves else random.choice(available_moves)
222+
223+
else: # hard
224+
best_move = None
225+
best_score = -999
226+
for move in available_moves:
227+
score = 0
228+
if completes_box(move):
229+
score += 100
230+
if creates_danger(move):
231+
score -= 50
232+
simulate_move(move)
233+
for row in range(size):
234+
for col in range(size):
235+
sides = count_box_sides(row, col)
236+
if sides == 2:
237+
score += 2
238+
elif sides == 1:
239+
score += 1
240+
undo_move(move)
241+
if score > best_score:
242+
best_score = score
243+
best_move = move
244+
return best_move
245+
246+
247+
# Main game loop
248+
while player_score + computer_score < total_boxes:
249+
print_board()
250+
print(BOLD + "=" * 70 + RESET)
251+
print(BLUE + f"🔵 Player Score: {player_score}" + RESET)
252+
if mode == '2':
253+
print(RED + f"🤖 AI Score: {computer_score}" + RESET)
254+
else:
255+
print(RED + f"🔴 Player 2 Score: {computer_score}" + RESET)
256+
print(BOLD + "=" * 70 + RESET)
257+
258+
if current_player == 1 or mode == '1':
259+
if current_player == 1:
260+
print(BLUE + "\n🔵 Player 1 Turn" + RESET)
261+
else:
262+
print(RED + "\n🔴 Player 2 Turn" + RESET)
263+
264+
direction = input("➡️ Horizontal(h) or Vertical(v): ").lower()
265+
if direction not in ['h', 'v']:
266+
print(RED + "❌ Invalid direction!" + RESET)
267+
continue
268+
269+
row = input("📍 Enter row: ")
270+
col = input("📍 Enter column: ")
271+
272+
if not row.isdigit() or not col.isdigit():
273+
print(RED + "❌ Invalid position!" + RESET)
274+
continue
275+
276+
row, col = int(row), int(col)
277+
278+
try:
279+
if direction == 'h':
280+
if horizontal_lines[row][col]:
281+
print(YELLOW + "⚠️ Line already taken!" + RESET)
282+
continue
283+
horizontal_lines[row][col] = True
284+
else:
285+
if vertical_lines[row][col]:
286+
print(YELLOW + "⚠️ Line already taken!" + RESET)
287+
continue
288+
vertical_lines[row][col] = True
289+
except:
290+
print(RED + "❌ Position out of range!" + RESET)
291+
continue
292+
293+
symbol = 'P' if current_player == 1 else 'A'
294+
got_box = check_boxes(symbol)
295+
if not got_box:
296+
current_player = 2 if current_player == 1 else 1
297+
298+
else:
299+
print(RED + "\n🤖 AI is thinking..." + RESET)
300+
time.sleep(1)
301+
302+
move = ai_move()
303+
direction, row, col = move
304+
print(CYAN + f"🎯 AI selected: {direction} ({row}, {col})" + RESET)
305+
306+
if direction == 'h':
307+
horizontal_lines[row][col] = True
308+
else:
309+
vertical_lines[row][col] = True
310+
311+
got_box = check_boxes('A')
312+
if not got_box:
313+
current_player = 1
314+
315+
# Game over
316+
print_board()
317+
print(BOLD + GREEN)
318+
print("=" * 70)
319+
print("🏁 GAME OVER 🏁")
320+
print("=" * 70)
321+
print(RESET)
322+
323+
print(BLUE + f"🔵 Player Score: {player_score}" + RESET)
324+
if mode == '2':
325+
print(RED + f"🤖 AI Score: {computer_score}" + RESET)
326+
else:
327+
print(RED + f"🔴 Player 2 Score: {computer_score}" + RESET)
328+
329+
print()
330+
331+
if player_score > computer_score:
332+
print(GREEN + BOLD + "🎉 PLAYER 1 WINS!" + RESET)
333+
elif computer_score > player_score:
334+
if mode == '2':
335+
print(RED + BOLD + "🤖 AI WINS!" + RESET)
336+
else:
337+
print(RED + BOLD + "🎉 PLAYER 2 WINS!" + RESET)
338+
else:
339+
print(YELLOW + BOLD + "🤝 IT'S A DRAW!" + RESET)
340+
341+
print(CYAN + "\n👋 Thanks for playing Dots & Boxes!\n" + RESET)

web-app/index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ <h3>FLAMES Game</h3>
8080
<button class="btn-play">Play Now</button>
8181
</div>
8282

83+
<div class="project-card" data-category="games" data-project="dots-boxes">
84+
<div class="card-icon">🔲</div>
85+
<h3>Dots & Boxes AI</h3>
86+
<p>Challenge friends or AI in this strategy game!</p>
87+
<button class="btn-play">Play Now</button>
88+
</div>
89+
8390
<!-- Math Tools -->
8491
<div class="project-card" data-category="math" data-project="fibonacci">
8592
<div class="card-icon"></div>

0 commit comments

Comments
 (0)