Python: Make code testable

Avoid executing code on module level as this prevents importing the
module for testing. Especially infinite loops are evil.
This commit is contained in:
Martin Thoma
2022-03-19 09:54:52 +01:00
parent f40a1fc465
commit 8495e59a8f
23 changed files with 1049 additions and 973 deletions

View File

@@ -22,7 +22,7 @@ jobs:
pip install -r 00_Utilities/python/ci-requirements.txt
- name: Test with pytest
run: |
pytest 01_Acey_Ducey/python 02_Amazing/python 39_Golf/python
pytest -m "not slow"
- name: Test with mypy
run: |
mypy . --exclude 79_Slalom --exclude 27_Civil_War --exclude 38_Fur_Trader --exclude 81_Splat --exclude 09_Battle --exclude 40_Gomoko --exclude 36_Flip_Flop --exclude 43_Hammurabi --exclude 04_Awari --exclude 78_Sine_Wave --exclude 77_Salvo --exclude 34_Digits --exclude 17_Bullfight --exclude 16_Bug

View File

@@ -62,21 +62,21 @@ def display_bankroll(bank_roll: int) -> None:
print("You now have %s dollars\n" % bank_roll)
# Display initial title and instructions
print("\n Acey Ducey Card Game")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
print("Acey-Ducey is played in the following manner")
print("The dealer (computer) deals two cards face up")
print("You have an option to bet or not bet depending")
print("on whether or not you feel the card will have")
print("a value between the first two.")
print("If you do not want to bet, input a 0")
def main():
# Display initial title and instructions
print("\n Acey Ducey Card Game")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
print("Acey-Ducey is played in the following manner")
print("The dealer (computer) deals two cards face up")
print("You have an option to bet or not bet depending")
print("on whether or not you feel the card will have")
print("a value between the first two.")
print("If you do not want to bet, input a 0")
# Loop for series of multiple games
KEEP_PLAYING = True
while KEEP_PLAYING:
# Loop for series of multiple games
KEEP_PLAYING = True
while KEEP_PLAYING:
# Initialize bankroll at start of each game
BANK_ROLL = DEFAULT_BANKROLL
@@ -142,9 +142,13 @@ while KEEP_PLAYING:
else:
KEEP_PLAYING = False
# End of multiple game loop
# End of multiple game loop
print("OK Hope you had fun\n")
print("OK Hope you had fun\n")
if __name__ == "__main__":
main()
########################################################

View File

@@ -108,22 +108,23 @@ def build_result_string(num, guess):
######################################################################
# Intro text
print("\n Bagels")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
def main():
# Intro text
print("\n Bagels")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
# Anything other than N* will show the rules
response = input("Would you like the rules (Yes or No)? ")
if len(response) > 0:
# 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:
else:
print_rules()
games_won = 0
still_running = True
while still_running:
games_won = 0
still_running = True
while still_running:
# New round
num = pick_number()
@@ -156,13 +157,15 @@ while still_running:
if response.upper()[0] != "Y":
still_running = False
if games_won > 0:
if games_won > 0:
print(f"\nA {games_won} point Bagels buff!!")
print("Hope you had fun. Bye.\n")
print("Hope you had fun. Bye.\n")
if __name__ == "__main__":
main()
######################################################################
#
# Porting Notes

View File

@@ -353,4 +353,5 @@ class Basketball:
self.opponent_jumpshot()
new_game = Basketball()
if __name__ == "__main__":
Basketball()

View File

@@ -49,17 +49,18 @@ def print_legs(n_legs):
print()
print_n_whitespaces(34)
print("BUG")
print_n_whitespaces(15)
print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print_n_newlines(3)
def main():
print_n_whitespaces(34)
print("BUG")
print_n_whitespaces(15)
print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print_n_newlines(3)
print("THE GAME BUG")
print("I HOPE YOU ENJOY THIS GAME.")
print()
Z = input("DO YOU WANT INSTRUCTIONS? ")
if Z != "NO":
print("THE GAME BUG")
print("I HOPE YOU ENJOY THIS GAME.")
print()
Z = input("DO YOU WANT INSTRUCTIONS? ")
if Z != "NO":
print("THE OBJECT OF BUG IS TO FINISH YOUR BUG BEFORE I FINISH")
print("MINE. EACH NUMBER STANDS FOR A PART OF THE BUG BODY.")
print("I WILL ROLL THE DIE FOR YOU, TELL YOU WHAT I ROLLED FOR YOU")
@@ -82,21 +83,21 @@ if Z != "NO":
print(f"{row[0]:<16}{row[1]:<16}{row[2]:<20}")
print_n_newlines(2)
A = 0
B = 0
H = 0
L = 0
N = 0
P = 0
Q = 0
R = 0 # NECK
S = 0 # FEELERS
T = 0
U = 0
V = 0
Y = 0
A = 0
B = 0
H = 0
L = 0
N = 0
P = 0
Q = 0
R = 0 # NECK
S = 0 # FEELERS
T = 0
U = 0
V = 0
Y = 0
while Y <= 0:
while Y <= 0:
Z = random.randint(1, 6)
print()
C = 1
@@ -299,4 +300,8 @@ while Y <= 0:
if Y != 0:
break
print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!")
print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!")
if __name__ == "__main__":
main()

View File

@@ -214,13 +214,16 @@ while True:
if death:
break
# 1310
print_n_newlines(3)
if D[4] == 0:
def main():
# 1310
print_n_newlines(3)
if D[4] == 0:
print("THE CROWD BOOS FOR TEN MINUTES. IF YOU EVER DARE TO SHOW")
print("YOUR FACE IN A RING AGAIN, THEY SWEAR THEY WILL KILL YOU--")
print("UNLESS THE BULL DOES FIRST.")
else:
else:
if D[4] == 2:
print("THE CROWD CHEERS WILDLY!")
elif D[5] == 2:
@@ -239,3 +242,7 @@ else:
print()
print("ADIOS")
print_n_newlines(3)
if __name__ == "__main__":
main()

View File

@@ -10,55 +10,56 @@ def print_n_newlines(n: int):
print()
print_n_whitespaces(32)
print("BULLSEYE")
print_n_whitespaces(15)
print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print_n_newlines(3)
print("IN THIS GAME, UP TO 20 PLAYERS THROW DARTS AT A TARGET")
print("WITH 10, 20, 30, AND 40 POINT ZONES. THE OBJECTIVE IS")
print("TO GET 200 POINTS.")
print()
print("THROW", end="")
print_n_whitespaces(20)
print("DESCRIPTION", end="")
print_n_whitespaces(45)
print("PROBABLE SCORE")
print(" 1", end="")
print_n_whitespaces(20)
print("FAST OVERARM", end="")
print_n_whitespaces(45)
print("BULLSEYE OR COMPLETE MISS")
print(" 2", end="")
print_n_whitespaces(20)
print("CONTROLLED OVERARM", end="")
print_n_whitespaces(45)
print("10, 20 OR 30 POINTS")
print(" 3", end="")
print_n_whitespaces(20)
print("UNDERARM", end="")
print_n_whitespaces(45)
print("ANYTHING")
print()
def main():
print_n_whitespaces(32)
print("BULLSEYE")
print_n_whitespaces(15)
print("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
print_n_newlines(3)
print("IN THIS GAME, UP TO 20 PLAYERS THROW DARTS AT A TARGET")
print("WITH 10, 20, 30, AND 40 POINT ZONES. THE OBJECTIVE IS")
print("TO GET 200 POINTS.")
print()
print("THROW", end="")
print_n_whitespaces(20)
print("DESCRIPTION", end="")
print_n_whitespaces(45)
print("PROBABLE SCORE")
print(" 1", end="")
print_n_whitespaces(20)
print("FAST OVERARM", end="")
print_n_whitespaces(45)
print("BULLSEYE OR COMPLETE MISS")
print(" 2", end="")
print_n_whitespaces(20)
print("CONTROLLED OVERARM", end="")
print_n_whitespaces(45)
print("10, 20 OR 30 POINTS")
print(" 3", end="")
print_n_whitespaces(20)
print("UNDERARM", end="")
print_n_whitespaces(45)
print("ANYTHING")
print()
nb_winners = 0
round = 0
nb_winners = 0
round = 0
winners = {}
for i in range(1, 11):
winners = {}
for i in range(1, 11):
winners[i] = 0
total_score = {}
for i in range(1, 21):
total_score = {}
for i in range(1, 21):
total_score[i] = 0
nb_players = int(input("HOW MANY PLAYERS? "))
player_names = {}
for i in range(1, nb_players + 1):
nb_players = int(input("HOW MANY PLAYERS? "))
player_names = {}
for i in range(1, nb_players + 1):
player_name = input("NAME OF PLAYER #")
player_names[i] = player_name
while nb_winners == 0:
while nb_winners == 0:
round = round + 1
print()
print(f"ROUND {round}---------")
@@ -108,10 +109,14 @@ while nb_winners == 0:
nb_winners = nb_winners + 1
winners[nb_winners] = player_index
print()
print("WE HAVE A WINNER!!")
print()
for i in range(1, nb_winners + 1):
print()
print("WE HAVE A WINNER!!")
print()
for i in range(1, nb_winners + 1):
print(f"{player_names[winners[i]]} SCORED {total_score[winners[i]]} POINTS.")
print()
print("THANKS FOR THE GAME.")
print()
print("THANKS FOR THE GAME.")
if __name__ == "__main__":
main()

View File

@@ -22,7 +22,9 @@
import random
WORDS = [
def main():
WORDS = [
[
"Ability",
"Basal",
@@ -68,21 +70,20 @@ WORDS = [
"facility",
"environment",
],
]
]
# Display intro text
print("\n Buzzword Generator")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
print("This program prints highly acceptable phrases in")
print("'educator-speak' that you can work into reports")
print("and speeches. Whenever a question mark is printed,")
print("type a 'Y' for another phrase or 'N' to quit.")
print("\n\nHere's the first phrase:")
# Display intro text
print("\n Buzzword Generator")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
print("This program prints highly acceptable phrases in")
print("'educator-speak' that you can work into reports")
print("and speeches. Whenever a question mark is printed,")
print("type a 'Y' for another phrase or 'N' to quit.")
print("\n\nHere's the first phrase:")
still_running = True
while still_running:
still_running = True
while still_running:
phrase = ""
for section in WORDS:
if len(phrase) > 0:
@@ -99,9 +100,11 @@ while still_running:
except Exception:
still_running = False
print("Come back when you need help with another report!\n")
print("Come back when you need help with another report!\n")
if __name__ == "__main__":
main()
######################################################################
#

View File

@@ -18,17 +18,18 @@ def throw_dice():
return randint(1, 6) + randint(1, 6)
print(" " * 33 + "Craps")
print(" " * 15 + "Creative Computing Morristown, New Jersey")
print()
print()
print()
def main():
print(" " * 33 + "Craps")
print(" " * 15 + "Creative Computing Morristown, New Jersey")
print()
print()
print()
winnings = 0
print("2,3,12 are losers; 4,5,6,8,9,10 are points; 7,11 are natural winners.")
winnings = 0
print("2,3,12 are losers; 4,5,6,8,9,10 are points; 7,11 are natural winners.")
play_again = True
while play_again:
play_again = True
while play_again:
wager = int(input("Input the amount of your wager: "))
print("I will now throw the dice")
@@ -73,9 +74,13 @@ while play_again:
print("You are now even at 0")
play_again = m == "5"
if winnings < 0:
if winnings < 0:
print("Too bad, you are in the hole. Come again.")
elif winnings > 0:
elif winnings > 0:
print("Congratulations---you came out a winner. Come again.")
else:
else:
print("Congratulations---you came out even, not bad for an amateur")
if __name__ == "__main__":
main()

View File

@@ -28,25 +28,26 @@
import random
# We'll track counts of roll outcomes in a 13-element list.
# The first two indices (0 & 1) are ignored, leaving just
# the indices that match the roll values (2 through 12).
freq = [0] * 13
def main():
# We'll track counts of roll outcomes in a 13-element list.
# The first two indices (0 & 1) are ignored, leaving just
# the indices that match the roll values (2 through 12).
freq = [0] * 13
# Display intro text
print("\n Dice")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
# "Danny Freidus"
print("This program simulates the rolling of a")
print("pair of dice.")
print("You enter the number of times you want the computer to")
print("'roll' the dice. Watch out, very large numbers take")
print("a long time. In particular, numbers over 5000.")
# Display intro text
print("\n Dice")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
# "Danny Freidus"
print("This program simulates the rolling of a")
print("pair of dice.")
print("You enter the number of times you want the computer to")
print("'roll' the dice. Watch out, very large numbers take")
print("a long time. In particular, numbers over 5000.")
still_playing = True
while still_playing:
still_playing = True
while still_playing:
print("")
n = int(input("How many rolls? "))
@@ -73,6 +74,9 @@ while still_playing:
still_playing = False
if __name__ == "__main__":
main()
########################################################
#
# Porting Notes

View File

@@ -55,8 +55,9 @@ def limit_set():
return limit, limit_goal
limit, limit_goal = limit_set()
while True:
def main():
limit, limit_goal = limit_set()
while True:
guess_count = 1
still_guessing = True
won = False
@@ -94,3 +95,7 @@ while True:
else:
insert_whitespaces()
limit, limit_goal = limit_set()
if __name__ == "__main__":
main()

View File

@@ -71,27 +71,29 @@ DATA = [
# is the line length used by every row
ROW_LEN = sum(DATA[0])
# Display intro text
print("\n Love")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
print("A tribute to the great American artist, Robert Indiana.")
print("His great work will be reproduced with a message of")
print("your choice up to 60 characters. If you can't think of")
print("a message, simple type the word 'love'\n") # (sic)
# Get message from user
message = input("Your message, please? ")
if message == "":
def main():
# Display intro text
print("\n Love")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
print("A tribute to the great American artist, Robert Indiana.")
print("His great work will be reproduced with a message of")
print("your choice up to 60 characters. If you can't think of")
print("a message, simple type the word 'love'\n") # (sic)
# Get message from user
message = input("Your message, please? ")
if message == "":
message = "LOVE"
# Repeat the message until we get at least one line's worth
while len(message) < ROW_LEN:
# Repeat the message until we get at least one line's worth
while len(message) < ROW_LEN:
message += message
# Display image
print("\n" * 9)
for row in DATA:
# Display image
print("\n" * 9)
for row in DATA:
print_message = True
position = 0
line_text = ""
@@ -106,7 +108,11 @@ for row in DATA:
position += length
print(line_text)
print("")
print("")
if __name__ == "__main__":
main()
######################################################################

View File

@@ -59,4 +59,5 @@ def main():
print("HAVE A NICE DAY!")
main()
if __name__ == "__main__":
main()

View File

@@ -39,8 +39,9 @@ def parse_input():
return i
initial_message()
while True:
def main():
initial_message()
while True:
dead = False
n = 0
print("Type '1' to Spin chamber and pull trigger")
@@ -73,6 +74,9 @@ while True:
print("...Next victim....")
if __name__ == "__main__":
main()
########################################################
# Porting Notes
#

View File

@@ -489,21 +489,17 @@ def execute_turn(turn):
#
######################################
######################
#
# main game flow
#
######################
# initialize the player and computer
# boards
initialize_game()
def main():
# initialize the player and computer
# boards
initialize_game()
# execute turns until someone wins or we run
# out of squares to shoot
# execute turns until someone wins or we run
# out of squares to shoot
game_over = False
while not game_over:
game_over = False
while not game_over:
# increment the turn
current_turn = current_turn + 1
@@ -522,3 +518,7 @@ while not game_over:
if execute_turn(second_turn) == 0:
game_over = True
continue
if __name__ == "__main__":
main()

View File

@@ -24,29 +24,29 @@
import math
import time
# Constants
STRINGS = ("Creative", "Computing") # Text to display
MAX_LINES = 160
STEP_SIZE = 0.25 # Number of radians to increase at each
# line. Controls speed of horizontal
# printing movement.
CENTER = 26 # Controls left edge of "middle" string
DELAY = 0.05 # Amount of seconds to wait between lines
def main():
# Constants
STRINGS = ("Creative", "Computing") # Text to display
MAX_LINES = 160
STEP_SIZE = 0.25 # Number of radians to increase at each
# line. Controls speed of horizontal
# printing movement.
CENTER = 26 # Controls left edge of "middle" string
DELAY = 0.05 # Amount of seconds to wait between lines
# Display "intro" text
print("\n Sine Wave")
print(" Creative Computing Morristown, New Jersey")
print("\n\n\n\n")
# "REMarkable program by David Ahl"
# Display "intro" text
print("\n Sine Wave")
print(" Creative Computing Morristown, New Jersey")
print("\n\n\n\n")
# "REMarkable program by David Ahl"
string_index = 0
radians = 0
width = CENTER - 1
string_index = 0
radians = 0
width = CENTER - 1
# "Start long loop"
for _line_num in range(MAX_LINES):
# "Start long loop"
for _line_num in range(MAX_LINES):
# Get string to display on this line
curr_string = STRINGS[string_index]
@@ -66,6 +66,9 @@ for _line_num in range(MAX_LINES):
time.sleep(DELAY)
if __name__ == "__main__":
main()
########################################################
#
# Porting Notes

View File

@@ -160,7 +160,8 @@ def run():
medals["bronze"] += 1
while True:
def main():
while True:
gates = ask_int("How many gates does this course have (1 to 25)")
if gates < 1:
print("Try again,")
@@ -169,16 +170,16 @@ while True:
print("25 is the limit.")
break
pre_run()
pre_run()
while True:
while True:
lvl = ask_int("Rate yourself as a skier, (1=Worst, 3=Best)")
if lvl < 1 or lvl > 3:
print("The bounds are 1-3.")
else:
break
while True:
while True:
run()
while True:
answer = ask("Do you want to play again?")
@@ -189,10 +190,14 @@ while True:
if answer == "NO":
break
print("Thanks for the race")
if medals["gold"] > 0:
print("Thanks for the race")
if medals["gold"] > 0:
print(f"Gold medals: {medals['gold']}")
if medals["silver"] > 0:
if medals["silver"] > 0:
print(f"Silver medals: {medals['silver']}")
if medals["bronze"] > 0:
if medals["bronze"] > 0:
print(f"Bronze medals: {medals['bronze']}")
if __name__ == "__main__":
main()

View File

@@ -126,11 +126,12 @@ def final_message(profits):
print("Collect your winings from the H&M cashier.")
profits = 0
keep_betting = True
def main():
profits = 0
keep_betting = True
initial_message()
while keep_betting:
initial_message()
while keep_betting:
m = input_betting()
w = spin_wheels()
profits = adjust_profits(w, m, profits)
@@ -144,9 +145,12 @@ while keep_betting:
except IndexError:
keep_betting = False
final_message(profits)
final_message(profits)
if __name__ == "__main__":
main()
######################################################################
#
# Porting notes

View File

@@ -293,14 +293,11 @@ def print_header():
)
#
# Main program.
#
def main():
print_header()
print_header()
successful_jumps = []
while True:
successful_jumps = []
while True:
chute_altitude = jump()
if chute_altitude > 0:
# We want the statistics on previous jumps (i.e. not including the
@@ -317,3 +314,7 @@ while True:
if not z:
print("SSSSSSSSSS.")
break
if __name__ == "__main__":
main()

View File

@@ -57,18 +57,19 @@ def get_guess():
return guess
# Display intro text
print("\n Stars")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
# "*** Stars - People's Computer Center, MenloPark, CA"
def main():
# Display intro text
print("\n Stars")
print("Creative Computing Morristown, New Jersey")
print("\n\n")
# "*** Stars - People's Computer Center, MenloPark, CA"
response = input("Do you want instructions? ")
if response.upper()[0] == "Y":
response = input("Do you want instructions? ")
if response.upper()[0] == "Y":
print_instructions()
still_playing = True
while still_playing:
still_playing = True
while still_playing:
# "*** Computer thinks of a number"
secret_number = random.randint(1, MAX_NUM)
@@ -104,6 +105,9 @@ while still_playing:
still_playing = False
if __name__ == "__main__":
main()
######################################################################
#
# Porting Notes

View File

@@ -11,10 +11,11 @@ def equation(x: float) -> float:
return 30 * exp(-x * x / 100)
print(" " * 32 + "3D PLOT")
print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n\n")
def main():
print(" " * 32 + "3D PLOT")
print(" " * 15 + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n\n\n\n")
for x in range(-300, 315, 15):
for x in range(-300, 315, 15):
x1 = x / 10
max_column = 0
y1 = 5 * floor(sqrt(900 - x1 * x1) / 5)
@@ -26,3 +27,7 @@ for x in range(-300, 315, 15):
max_column = column
y_plot[column] = "*"
print("".join(y_plot))
if __name__ == "__main__":
main()

View File

@@ -3,7 +3,7 @@ import unittest
import tower
class MyTestCase(unittest.TestCase):
class TowerTestCase(unittest.TestCase):
def test_something(self):
t = tower.Tower()
self.assertTrue(t.empty())
@@ -44,9 +44,6 @@ class MyTestCase(unittest.TestCase):
t.add(d5)
t.add(d3)
f = t.vertical_format(6, 3)
self.assertEqual(f, [" ", "[ 3 ] ", "[ 5 ] "])
if __name__ == "__main__":
unittest.main()

View File

@@ -44,23 +44,6 @@ class Tower:
print(r)
print(
"""
IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH
2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15. WITH 3 DISKS
THE CODE NAMES WOULD BE 11, 13 AND 15, ETC. THE NEEDLES
ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL
START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
TO NEEDLE 3.
GOOD LUCK!
"""
)
class Game:
def __init__(self):
# use fewer sizes to make debugging easier
@@ -144,8 +127,25 @@ class Game:
from_tower.add(disk)
game = Game()
while True:
def main():
print(
"""
IN THIS PROGRAM, WE SHALL REFER TO DISKS BY NUMERICAL CODE.
3 WILL REPRESENT THE SMALLEST DISK, 5 THE NEXT SIZE,
7 THE NEXT, AND SO ON, UP TO 15. IF YOU DO THE PUZZLE WITH
2 DISKS, THEIR CODE NAMES WOULD BE 13 AND 15. WITH 3 DISKS
THE CODE NAMES WOULD BE 11, 13 AND 15, ETC. THE NEEDLES
ARE NUMBERED FROM LEFT TO RIGHT, 1 TO 3. WE WILL
START WITH THE DISKS ON NEEDLE 1, AND ATTEMPT TO MOVE THEM
TO NEEDLE 3.
GOOD LUCK!
"""
)
game = Game()
while True:
game.print()
game.take_turn()
@@ -168,3 +168,7 @@ while True:
elif game.moves() > 128:
print("SORRY, BUT I HAVE ORDERS TO STOP IF YOU MAKE MORE THAN 128 MOVES.")
sys.exit(0)
if __name__ == "__main__":
main()