Files
basic-computer-games/14_Bowling/python/bowling.py
2022-04-02 09:12:13 +02:00

150 lines
4.8 KiB
Python

import random
from typing import List
def simulate_roll(pins: List[int]) -> None:
for _ in range(20):
x = random.randint(0, 14)
if x < len(pins):
pins[x] = 1
def calculate_score(rolls: List[int]) -> int:
score = 0
frame = 1
b = 1
for index, pins in enumerate(rolls):
score += pins
if b == 1:
if pins == 10: # strike
score += sum(rolls[index + 1 : index + 3])
frame += 1
else:
b = 2
else:
if sum(rolls[index - 1 : index + 1]) == 10: # spare
score += rolls[index + 1]
b = 1
frame += 1
if frame > 10:
break
return score
class Player:
def __init__(self, name: str) -> None:
self.name = name
self.rolls: List[int] = []
def play_frame(self, frame: int) -> None:
extra = 0
prev_score = 0
pins = [0] * 10 # reset the pins
for ball in range(2):
simulate_roll(pins)
score = sum(pins)
self.show(pins)
pin_count = score - prev_score
self.rolls.append(pin_count) # log the number of pins toppled this roll
print(f"{pin_count} for {self.name}")
if score - prev_score == 0:
print("GUTTER!!!")
if ball == 0:
if score == 10:
print("STRIKE!!!")
extra = 2
break # cannot roll more than once in a frame
else:
print(f"next roll {self.name}")
else:
if score == 10:
print("SPARE!")
extra = 1
prev_score = score # remember previous pins to distinguish ...
if frame == 9 and extra > 0:
print(f"Extra rolls for {self.name}")
pins = [0] * 10 # reset the pins
score = 0
for _ball in range(extra):
if score == 10:
pins = [0] * 10
simulate_roll(pins)
score = sum(pins)
self.rolls.append(score)
def __str__(self) -> str:
return f"{self.name}: {self.rolls}, total:{calculate_score(self.rolls)}"
def show(self, pins: List[int]) -> None:
pins_iter = iter(pins)
print()
for row in range(4):
print(" " * row, end="")
for _ in range(4 - row):
p = next(pins_iter)
print("O " if p else "+ ", end="")
print()
def centre_text(text: str, width: int) -> str:
t = len(text)
return (" " * ((width - t) // 2)) + text
def main() -> None:
print(centre_text("Bowl", 80))
print(centre_text("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", 80))
print()
print("WELCOME TO THE ALLEY.")
print("BRING YOUR FRIENDS.")
print("OKAY LET'S FIRST GET ACQUAINTED.")
while True:
print()
if input("THE INSTRUCTIONS (Y/N)? ") in "yY":
print("THE GAME OF BOWLING TAKES MIND AND SKILL. DURING THE GAME")
print("THE COMPUTER WILL KEEP SCORE. YOU MAY COMPETE WITH")
print("OTHER PLAYERS[UP TO FOUR]. YOU WILL BE PLAYING TEN FRAMES.")
print("ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE")
print("PIN IS STANDING. AFTER THE GAME THE COMPUTER WILL SHOW YOUR")
print("SCORES.")
total_players = int(input("FIRST OF ALL...HOW MANY ARE PLAYING? "))
player_names = []
print()
print("VERY GOOD...")
for index in range(total_players):
player_names.append(Player(input(f"Enter name for player {index + 1}: ")))
for frame in range(10):
for player in player_names:
player.play_frame(frame)
for player in player_names:
print(player)
if input("DO YOU WANT ANOTHER GAME? ") not in "yY":
break
if __name__ == "__main__":
main()
############################################################################################
#
# This is a fairly straight conversion to python with some exceptions.
# I have kept most of the upper case text that the program prints.
# I have added the feature of giving names to players.
# I have added a Player class to store player data in.
# This last change works around the problems in the original storing data in a matrix.
# The original had bugs in calculating indexes which meant that the program
# would overwrite data in the matrix, so the results printed out contained errors.
# The last change is to do with the strict rules which allow extra rolls if the player
# scores a spare or strike in the last frame.
# This program allows these extra rolls and also calculates the proper score.
#
############################################################################################