Files
basic-computer-games/05_Bagels/python/bagels.py
2024-08-19 03:46:27 +03:00

181 lines
5.4 KiB
Python

"""
Bagels
From: BASIC Computer Games (1978)
Edited by David H. Ahl
"In this game, the computer picks a 3-digit secret number using
the digits 0 to 9 and you attempt to guess what it is. You are
allowed up to twenty guesses. No digit is repeated. After
each guess the computer will give you clues about your guess
as follows:
PICO One digit is correct, but in the wrong place
FERMI One digit is in the correct place
BAGELS No digit is correct
"You will learn to draw inferences from the clues and, with
practice, you'll learn to improve your score. There are several
good strategies for playing Bagels. After you have found a good
strategy, see if you can improve it. Or try a different strategy
altogether and see if it is any better. While the program allows
up to twenty guesses, if you use a good strategy it should not
take more than eight guesses to get any number.
"The original authors of this program are D. Resek and P. Rowe of
the Lawrence Hall of Science, Berkeley, California."
Python port by Jeff Jetton, 2019
"""
import random
from typing import List
MAX_GUESSES = 20
def print_rules() -> None:
print("\nI am thinking of a three-digit number. Try to guess")
print("my number and I will give you clues as follows:")
print(" PICO - One digit correct but in the wrong position")
print(" FERMI - One digit correct and in the right position")
print(" BAGELS - No digits correct")
def pick_number() -> List[str]:
# Note that this returns a list of individual digits
# as separate strings, not a single integer or string
numbers = list(range(10))
random.shuffle(numbers)
num = numbers[:3]
return [str(i) for i in num]
def get_valid_guess(guesses: int) -> str:
valid = False
while not valid:
guess = input(f"Guess # {guesses} ? ")
guess = guess.strip()
# Guess must be three characters
if len(guess) == 3:
# And they should be numbers
if guess.isnumeric():
# And the numbers must be unique
if len(set(guess)) == 3:
valid = True
else:
print("Oh, I forgot to tell you that the number I have in mind")
print("has no two digits the same.")
else:
print("What?")
else:
print("Try guessing a three-digit number.")
return guess
def build_result_string(num: List[str], guess: str) -> str:
result = ""
# Correct digits in wrong place
for i in range(2):
if num[i] == guess[i + 1]:
result += "PICO "
if num[i + 1] == guess[i]:
result += "PICO "
if num[0] == guess[2]:
result += "PICO "
if num[2] == guess[0]:
result += "PICO "
# Correct digits in right place
for i in range(3):
if num[i] == guess[i]:
result += "FERMI "
# Nothing right?
if result == "":
result = "BAGELS"
return result
def main() -> None:
# Intro text
print("\n Bagels")
print("Creative Computing Morristown, New Jersey\n\n")
# Anything other than N* will show the rules
response = input("Would you like the rules (Yes or No)? ")
if len(response) > 0:
if response.upper()[0] != "N":
print_rules()
else:
print_rules()
games_won = 0
still_running = True
while still_running:
# New round
num = pick_number()
num_str = "".join(num)
guesses = 1
print("\nO.K. I have a number in mind.")
guessing = True
while guessing:
guess = get_valid_guess(guesses)
if guess == num_str:
print("You got it!!!\n")
games_won += 1
guessing = False
else:
print(build_result_string(num, guess))
guesses += 1
if guesses > MAX_GUESSES:
print("Oh well")
print(f"That's {MAX_GUESSES} guesses. My number was {num_str}")
guessing = False
valid_response = False
while not valid_response:
response = input("Play again (Yes or No)? ")
if len(response) > 0:
valid_response = True
if response.upper()[0] != "Y":
still_running = False
if games_won > 0:
print(f"\nA {games_won} point Bagels buff!!")
print("Hope you had fun. Bye.\n")
if __name__ == "__main__":
main()
######################################################################
#
# Porting Notes
#
# The original program did an unusually good job of validating the
# player's input (compared to many of the other programs in the
# book). Those checks and responses have been exactly reproduced.
#
#
# Ideas for Modifications
#
# It should probably mention that there's a maximum of MAX_NUM
# guesses in the instructions somewhere, shouldn't it?
#
# Could this program be written to use anywhere from, say 2 to 6
# digits in the number to guess? How would this change the routine
# that creates the "result" string?
#
######################################################################