Bagels
A deductive logic game. You must guess a secret three-digit number based on clues. You have ten guesses. The game offers following hints based on your guesses.
- Pico
Correct digit in the wrong place
- Fermi
Correct digit in the correct place
- Bagels
No correct digits
>>> 123
Pico
Guess #2:
>>> 456
Bagels
Guess #3:
>>> 178
Pico Pico
--snip--
Guess #7:
>>> 791
Fermi Fermi
Guess #8:
>>> 701
You got it!
Do you want to play again? (yes or no)
>>> no
Thanks for playing!
bagels.py
1"""Bagels, by Al Sweigart al@inventwithpython.com
2A deductive logic game where you must guess a number based on clues.
3View this code at https://nostarch.com/big-book-small-python-projects
4A version of this game is featured in the book "Invent Your Own
5Computer Games with Python" https://nostarch.com/inventwithpython
6Tags: short, game, puzzle"""
7
8import random
9
10NUM_DIGITS = 3 # (!) Try setting this to 1 or 10.
11MAX_GUESSES = 10 # (!) Try setting this to 1 or 100.
12
13
14def main():
15 print('''Bagels, a deductive logic game.
16By Al Sweigart al@inventwithpython.com
17
18I am thinking of a {}-digit number with no repeated digits.
19Try to guess what it is. Here are some clues:
20When I say: That means:
21Pico One digit is correct but in the wrong position.
22Fermi One digit is correct and in the right position.
23Bagels No digit is correct.
24
25For example, if the secret number was 248 and your guess was 843, the
26clues would be Fermi Pico.'''.format(NUM_DIGITS))
27
28 while True: # Main game loop.
29 # This stores the secret number the player needs to guess:
30 secretNum = getSecretNum()
31 print('I have thought up a number.')
32 print(' You have {} guesses to get it.'.format(MAX_GUESSES))
33
34 numGuesses = 1
35 while numGuesses <= MAX_GUESSES:
36 guess = ''
37 # Keep looping until they enter a valid guess:
38 while len(guess) != NUM_DIGITS or not guess.isdecimal():
39 print('Guess #{}: '.format(numGuesses))
40 guess = input('> ')
41
42 clues = getClues(guess, secretNum)
43 print(clues)
44 numGuesses += 1
45
46 if guess == secretNum:
47 break # They're correct, so break out of this loop.
48 if numGuesses > MAX_GUESSES:
49 print('You ran out of guesses.')
50 print('The answer was {}.'.format(secretNum))
51
52 # Ask player if they want to play again.
53 print('Do you want to play again? (yes or no)')
54 if not input('> ').lower().startswith('y'):
55 break
56 print('Thanks for playing!')
57
58
59def getSecretNum():
60 """Returns a string made up of NUM_DIGITS unique random digits."""
61 numbers = list('0123456789') # Create a list of digits 0 to 9.
62 random.shuffle(numbers) # Shuffle them into random order.
63
64 # Get the first NUM_DIGITS digits in the list for the secret number:
65
66 secretNum = ''
67 for i in range(NUM_DIGITS):
68 secretNum += str(numbers[i])
69 return secretNum
70
71
72def getClues(guess, secretNum):
73 """Returns a string with the pico, fermi, bagels clues for a guess
74 and secret number pair."""
75 if guess == secretNum:
76 return 'You got it!'
77
78 clues = []
79
80 for i in range(len(guess)):
81 if guess[i] == secretNum[i]:
82 # A correct digit is in the correct place.
83 clues.append('Fermi')
84 elif guess[i] in secretNum:
85 # A correct digit is in the incorrect place.
86 clues.append('Pico')
87 if len(clues) == 0:
88 return 'Bagels' # There are no correct digits at all.
89 else:
90 # Sort the clues into alphabetical order so their original order
91 # doesn't give information away.
92 clues.sort()
93 # Make a single string from the list of string clues.
94 return ' '.join(clues)
95
96
97# If the program is run (instead of imported), run the game:
98if __name__ == '__main__':
99 main()