11import 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
87164def 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
104183if __name__ == "__main__" :
105- main ()
184+ main ()
0 commit comments