Skip to content

Commit b0e2960

Browse files
authored
Merge branch 'steam-bell-92:main' into main
2 parents 74a0ce8 + aad0fe6 commit b0e2960

23 files changed

Lines changed: 4677 additions & 672 deletions

games/Dots-Boxes-AI/Dots-Boxes-AI.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# Title
1515
print(BOLD + CYAN)
1616
print("=" * 70)
17-
print("🔲 DOTS & BOXES AI - ADVANCED VERSION 🔲")
17+
print("🔲 DOTS & BOXES AI - ADVANCED VERSION 🔲")
1818
print("=" * 70)
1919
print(RESET)
2020

@@ -266,32 +266,33 @@ def ai_move():
266266
print(RED + "❌ Invalid direction!" + RESET)
267267
continue
268268

269-
row = input("📍 Enter row: ")
270-
col = input("📍 Enter column: ")
269+
row_in = input("📍 Enter row: ")
270+
col_in = input("📍 Enter column: ")
271271

272-
if not row.isdigit() or not col.isdigit():
273-
print(RED + "❌ Invalid position!" + RESET)
272+
# Check if empty, or starts with a negative sign, or isn't numeric
273+
if not row_in.strip() or not col_in.strip() or '-' in row_in or '-' in col_in or not row_in.isdigit() or not col_in.isdigit():
274+
print(RED + "❌ Invalid input! Rows and columns must be positive numbers." + RESET)
274275
continue
275276

276-
row, col = int(row), int(col)
277+
row, col = int(row_in), int(col_in)
277278

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 IndexError:
290-
print(RED + "❌ Position out of range!" + RESET)
291-
continue
292-
except ValueError:
293-
print(RED + "❌ Invalid input!" + RESET)
294-
continue
279+
# Explicit Boundaries Check Before Modifying Array
280+
if direction == 'h':
281+
if row < 0 or row >= (size + 1) or col < 0 or col >= size:
282+
print(RED + f"❌ Position out of range! For 'h', Row must be 0-{size} and Col must be 0-{size-1}." + RESET)
283+
continue
284+
if horizontal_lines[row][col]:
285+
print(YELLOW + "⚠️ Line already taken!" + RESET)
286+
continue
287+
horizontal_lines[row][col] = True
288+
else:
289+
if row < 0 or row >= size or col < 0 or col >= (size + 1):
290+
print(RED + f"❌ Position out of range! For 'v', Row must be 0-{size-1} and Col must be 0-{size}." + RESET)
291+
continue
292+
if vertical_lines[row][col]:
293+
print(YELLOW + "⚠️ Line already taken!" + RESET)
294+
continue
295+
vertical_lines[row][col] = True
295296

296297
symbol = 'P' if current_player == 1 else 'A'
297298
got_box = check_boxes(symbol)
Lines changed: 119 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,136 @@
11
import random
2+
from typing import Tuple, List
3+
4+
# Game constants
5+
MIN_NUMBER = 1
6+
MAX_NUMBER = 100
7+
8+
# Difficulty levels
9+
DIFFICULTY_LEVELS = {
10+
"1": {"level": "Easy", "attempts": 15},
11+
"2": {"level": "Medium", "attempts": 10},
12+
"3": {"level": "Hard", "attempts": 5},
13+
}
14+
DEFAULT_DIFFICULTY = "2"
15+
16+
# Proximity hint thresholds
17+
VERY_CLOSE_THRESHOLD = 3
18+
CLOSE_THRESHOLD = 10
19+
NOT_CLOSE_THRESHOLD = 20
20+
21+
22+
def validate_guess(guess_num: int) -> bool:
23+
"""Check if guess is within valid range."""
24+
return MIN_NUMBER <= guess_num <= MAX_NUMBER
25+
26+
27+
def get_proximity_hint(diff: int) -> str:
28+
"""Return a hint based on how close the guess is."""
29+
if diff <= VERY_CLOSE_THRESHOLD:
30+
return "Very close!"
31+
elif diff <= CLOSE_THRESHOLD:
32+
return "Close."
33+
elif diff <= NOT_CLOSE_THRESHOLD:
34+
return "Not very close."
35+
else:
36+
return "Far off."
37+
38+
39+
def choose_difficulty() -> int:
40+
"""Let the user choose a difficulty level."""
41+
print("Choose difficulty:")
42+
print(" 1) Easy - 15 attempts")
43+
print(" 2) Medium - 10 attempts")
44+
print(" 3) Hard - 5 attempts")
245

3-
4-
def choose_difficulty():
5-
print("🎯 Choose difficulty:")
6-
print(" 1) 🟢 Easy - 15 attempts")
7-
print(" 2) 🟡 Medium - 10 attempts")
8-
print(" 3) 🔴 Hard - 5 attempts")
946
while True:
10-
choice = input("Select 1, 2 or 3 (default 2): ").strip() or "2"
11-
if choice in ("1", "2", "3"):
12-
return {"1": 15, "2": 10, "3": 5}[choice]
13-
print("⚠️ Invalid selection. Please enter 1, 2 or 3.")
47+
choice = input("Select 1, 2 or 3 (default 2): ").strip() or DEFAULT_DIFFICULTY
48+
49+
if choice in DIFFICULTY_LEVELS:
50+
return DIFFICULTY_LEVELS[choice]["attempts"]
51+
52+
print("Invalid selection. Please enter 1, 2 or 3.")
53+
54+
55+
def get_guess_input(remaining: int) -> int | None:
56+
"""
57+
Get and validate user input.
58+
59+
Args:
60+
remaining: Attempts left
61+
62+
Returns:
63+
Valid guess number or None
64+
"""
65+
try:
66+
guess = input(f"Guess ({remaining} left): ").strip()
67+
68+
if not guess:
69+
print("Input cannot be empty.")
70+
return None
71+
72+
guess_num = int(guess)
73+
74+
if not validate_guess(guess_num):
75+
print(f"Enter a number between {MIN_NUMBER} and {MAX_NUMBER}.")
76+
return None
1477

78+
return guess_num
79+
80+
except ValueError:
81+
print("Invalid input. Please enter a whole number.")
82+
return None
83+
84+
85+
def play_round(max_attempts: int) -> Tuple[bool, int]:
86+
"""
87+
Run one round of the game.
1588
16-
def play_round(max_attempts: int):
17-
number = random.randint(1, 100)
89+
Args:
90+
max_attempts: Maximum guesses allowed
91+
92+
Returns:
93+
Tuple of (won, attempts_used)
94+
"""
95+
number = random.randint(MIN_NUMBER, MAX_NUMBER)
1896
attempts = 0
19-
print(f"I'm thinking of a number between 1 and 100. You have {max_attempts} attempts.")
20-
guess_history = []
97+
guess_history: List[int] = []
98+
99+
print(f"I'm thinking of a number between {MIN_NUMBER} and {MAX_NUMBER}.")
100+
print(f"You have {max_attempts} attempts.")
21101

22102
while attempts < max_attempts:
23103
remaining = max_attempts - attempts
24-
try:
25-
guess = input(f"Guess ({remaining} left): ").strip()
26-
guess_num = int(guess)
27-
except ValueError:
28-
print("⚠️ Invalid input — please enter an integer between 1 and 100.")
29-
continue
104+
guess_num = get_guess_input(remaining)
30105

31-
if not (1 <= guess_num <= 100):
32-
print("🚫 Out of range — enter a number between 1 and 100.")
106+
if guess_num is None:
33107
continue
34108

35109
attempts += 1
36110
guess_history.append(guess_num)
37111

38112
if guess_num == number:
39-
print("🏆 Correct! You guessed the number!")
40-
print(f"✨ number: {number} — attempts: {attempts}/{max_attempts}")
113+
print("Correct! You guessed the number.")
114+
print(f"Number: {number}")
115+
print(f"Attempts: {attempts}/{max_attempts}")
116+
print("Guesses:", ", ".join(map(str, guess_history)))
41117
return True, attempts
42118

43119
if guess_num > number:
44-
print("⬇️ High — try a smaller number.")
120+
print("Too high.")
45121
else:
46-
print("⬆️ Low — try a larger number.")
122+
print("Too low.")
47123

48-
# proximity hint
124+
# Show proximity hint
49125
diff = abs(guess_num - number)
50-
if diff <= 3:
51-
print("🔥 Very close!")
52-
elif diff <= 10:
53-
print("🙂 Close — you're getting there.")
54-
elif diff <= 20:
55-
print("🧭 Not very close yet.")
56-
else:
57-
print("❄️ Far off — try a different range.")
126+
print(get_proximity_hint(diff))
58127

59-
print("💥 Out of attempts — you lost this round.")
128+
print("Out of attempts.")
60129
print(f"The number was {number}.")
130+
61131
if guess_history:
62132
print("Your guesses:", ", ".join(map(str, guess_history)))
133+
63134
return False, attempts
64135

65136

@@ -71,21 +142,28 @@ def play_round_with_guesses(guesses, number, max_attempts: int):
71142
returns: (won: bool, attempts: int)
72143
"""
73144
attempts = 0
145+
74146
for g in guesses:
75147
if attempts >= max_attempts:
76148
break
149+
77150
if not isinstance(g, int):
78151
continue
79-
if not (1 <= g <= 100):
152+
153+
if not validate_guess(g):
80154
continue
155+
81156
attempts += 1
157+
82158
if g == number:
83159
return True, attempts
160+
84161
return False, attempts
85162

86163

87164
def main():
88-
print("🎮 Welcome to the Number Guessing Game! 🎮\n")
165+
print("Welcome to the Number Guessing Game!\n")
166+
89167
while True:
90168
max_attempts = choose_difficulty()
91169
won, tries = play_round(max_attempts)
@@ -96,10 +174,11 @@ def main():
96174
print(f"You used all {max_attempts} attempts.")
97175

98176
again = input("Play again? (y/n): ").strip().lower()
177+
99178
if again != "y":
100-
print("👋 Thanks for playing — goodbye!")
179+
print("Goodbye.")
101180
break
102181

103182

104183
if __name__ == "__main__":
105-
main()
184+
main()

games/Snake-Game/Snake-Game.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import turtle
22
import random
33
import time
4-
import pygame
5-
64
# ================= SOUND =================
5+
try:
6+
import pygame
7+
pygame.mixer.init()
8+
eat_sound = pygame.mixer.Sound("sounds/eat.wav")
9+
gameover_sound = pygame.mixer.Sound("sounds/gameover.wav")
10+
pygame_installed = True
11+
except ImportError:
12+
pygame_installed = False
13+
print("⚠️ Warning: pygame module not found. Game will run without sound effects.")
714

8-
pygame.mixer.init()
9-
eat_sound = pygame.mixer.Sound("sounds/eat.wav")
10-
gameover_sound = pygame.mixer.Sound("sounds/gameover.wav")
1115

1216
# ================= SCREEN SETUP =================
1317

@@ -196,7 +200,8 @@ def move():
196200
def reset_game():
197201
global score, level, speed
198202

199-
gameover_sound.play()
203+
if pygame_installed:
204+
gameover_sound.play()
200205

201206
time.sleep(1)
202207

@@ -234,7 +239,8 @@ def reset_game():
234239
# Food collision
235240
if head.distance(food) < GRID_SIZE:
236241

237-
eat_sound.play()
242+
if pygame_installed:
243+
eat_sound.play()
238244

239245
score += current_food["points"]
240246

games/Snake-Game/main.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import pygame
21
import turtle
32
import time
43
from constants import SCREEN_WIDTH, SCREEN_HEIGHT, COLLISION_DISTANCE, SLEEP_TIME
54
from snake import Snake
65
from food import Food
76
from scoreboard import Scoreboard
87

8+
try:
9+
import pygame
10+
pygame_installed = True
11+
except ImportError:
12+
pygame_installed = False
13+
print("⚠️ Warning: pygame module not found. Game will run without sound effects.")
914

1015
class SnakeGame:
1116
def __init__(self):
@@ -29,9 +34,15 @@ def __init__(self):
2934
self.scoreboard = Scoreboard()
3035

3136
# Sound setup
32-
pygame.mixer.init()
33-
self.eat_sound = pygame.mixer.Sound("sounds/Apple_Eating.mp3")
34-
self.gameover_sound = pygame.mixer.Sound("sounds/Game_over.mp3")
37+
self.pygame_installed = pygame_installed
38+
if self.pygame_installed:
39+
try:
40+
pygame.mixer.init()
41+
self.eat_sound = pygame.mixer.Sound("sounds/Apple_Eating.mp3")
42+
self.gameover_sound = pygame.mixer.Sound("sounds/Game_over.mp3")
43+
except Exception as e:
44+
print(f"⚠️ Warning: Could not initialize pygame mixer: {e}")
45+
self.pygame_installed = False
3546

3647
# Keyboard bindings
3748
self.screen.listen()
@@ -83,7 +94,8 @@ def run(self):
8394

8495
# Boundary collision
8596
if self.snake.check_boundary_collision():
86-
self.gameover_sound.play()
97+
if self.pygame_installed:
98+
self.gameover_sound.play()
8799
self.snake.reset()
88100
self.scoreboard.reset()
89101
self.delay = SLEEP_TIME
@@ -95,7 +107,8 @@ def run(self):
95107
self.snake.add_part()
96108

97109
self.scoreboard.increase()
98-
self.eat_sound.play()
110+
if self.pygame_installed:
111+
self.eat_sound.play()
99112

100113
# Level system
101114
if self.scoreboard.score % 5 == 0:
@@ -113,7 +126,8 @@ def run(self):
113126

114127
# Self collision
115128
if self.snake.check_self_collision():
116-
self.gameover_sound.play()
129+
if self.pygame_installed:
130+
self.gameover_sound.play()
117131
self.snake.reset()
118132
self.scoreboard.reset()
119133
self.delay = SLEEP_TIME

0 commit comments

Comments
 (0)