mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 07:10:42 -08:00
Python: Add tests for bounce and bowling
This commit is contained in:
@@ -6,7 +6,7 @@ A physics simulation
|
|||||||
Ported by Dave LeCompte
|
Ported by Dave LeCompte
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Tuple
|
from typing import Tuple, List
|
||||||
|
|
||||||
PAGE_WIDTH = 64
|
PAGE_WIDTH = 64
|
||||||
|
|
||||||
@@ -51,8 +51,8 @@ def print_at_tab(line: str, tab: int, s: str) -> str:
|
|||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
def run_simulation(delta_t, v0, coeff_rest) -> None:
|
def run_simulation(delta_t: float, v0: float, coeff_rest: float) -> None:
|
||||||
bounce_time = [0] * 20 # time of each bounce
|
bounce_time: List[float] = [0] * 20 # time of each bounce
|
||||||
|
|
||||||
print("FEET")
|
print("FEET")
|
||||||
print()
|
print()
|
||||||
@@ -67,7 +67,7 @@ def run_simulation(delta_t, v0, coeff_rest) -> None:
|
|||||||
line = ""
|
line = ""
|
||||||
if int(h) == h:
|
if int(h) == h:
|
||||||
line += str(int(h))
|
line += str(int(h))
|
||||||
total_time = 0
|
total_time: float = 0
|
||||||
for i in range(1, sim_dur + 1):
|
for i in range(1, sim_dur + 1):
|
||||||
tm: float = 0
|
tm: float = 0
|
||||||
while tm <= bounce_time[i]:
|
while tm <= bounce_time[i]:
|
||||||
|
|||||||
72
13_Bounce/python/test_bounce.py
Normal file
72
13_Bounce/python/test_bounce.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import io
|
||||||
|
|
||||||
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
|
from _pytest.capture import CaptureFixture
|
||||||
|
|
||||||
|
from bounce import main
|
||||||
|
|
||||||
|
|
||||||
|
def test_bounce(monkeypatch: MonkeyPatch, capsys: CaptureFixture[str]) -> None:
|
||||||
|
time_increment = 0.1
|
||||||
|
velocity = 30
|
||||||
|
coefficient = 1
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"sys.stdin",
|
||||||
|
io.StringIO(f"{time_increment:0.1f}\n{velocity}\n{coefficient}\n"),
|
||||||
|
)
|
||||||
|
main()
|
||||||
|
actual = capsys.readouterr().out
|
||||||
|
expected = """ BOUNCE
|
||||||
|
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
THIS SIMULATION LETS YOU SPECIFY THE INITIAL VELOCITY
|
||||||
|
OF A BALL THROWN STRAIGHT UP, AND THE COEFFICIENT OF
|
||||||
|
ELASTICITY OF THE BALL. PLEASE USE A DECIMAL FRACTION
|
||||||
|
COEFFICIENCY (LESS THAN 1).
|
||||||
|
|
||||||
|
YOU ALSO SPECIFY THE TIME INCREMENT TO BE USED IN
|
||||||
|
'STROBING' THE BALL'S FLIGHT (TRY .1 INITIALLY).
|
||||||
|
|
||||||
|
TIME INCREMENT (SEC)?
|
||||||
|
VELOCITY (FPS)?
|
||||||
|
COEFFICIENT?
|
||||||
|
FEET
|
||||||
|
|
||||||
|
14 000 000 000
|
||||||
|
0 0 0
|
||||||
|
13 0 0 0 0 0 0
|
||||||
|
|
||||||
|
12 0 0 0 0 0 0
|
||||||
|
|
||||||
|
11 0 0 0
|
||||||
|
0 0 0
|
||||||
|
10
|
||||||
|
0 0 0
|
||||||
|
9 0 0 0
|
||||||
|
|
||||||
|
8
|
||||||
|
0 0 0
|
||||||
|
7 0 0 0
|
||||||
|
|
||||||
|
6
|
||||||
|
0 0 0
|
||||||
|
5 0 0 0
|
||||||
|
|
||||||
|
4
|
||||||
|
|
||||||
|
3 0 0 0
|
||||||
|
|
||||||
|
2 0 0 0
|
||||||
|
|
||||||
|
1
|
||||||
|
|
||||||
|
00 0 0
|
||||||
|
...................................................................
|
||||||
|
0 1 2 3 4 5 6
|
||||||
|
|
||||||
|
SECONDS
|
||||||
|
|
||||||
|
""" # noqa: W291
|
||||||
|
assert actual.split("\n") == expected.split("\n")
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
import random
|
import random
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
def simulate_roll(pins) -> None:
|
def simulate_roll(pins: List[int]) -> None:
|
||||||
for _ in range(20):
|
for _ in range(20):
|
||||||
x = random.randint(0, 14)
|
x = random.randint(0, 14)
|
||||||
if x < len(pins):
|
if x < len(pins):
|
||||||
pins[x] = 1
|
pins[x] = 1
|
||||||
|
|
||||||
|
|
||||||
def calculate_score(rolls) -> int:
|
def calculate_score(rolls: List[int]) -> int:
|
||||||
score = 0
|
score = 0
|
||||||
frame = 1
|
frame = 1
|
||||||
b = 1
|
b = 1
|
||||||
@@ -32,11 +33,11 @@ def calculate_score(rolls) -> int:
|
|||||||
|
|
||||||
|
|
||||||
class Player:
|
class Player:
|
||||||
def __init__(self, name):
|
def __init__(self, name: str):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.rolls = []
|
self.rolls: List[int] = []
|
||||||
|
|
||||||
def play_frame(self, frame):
|
def play_frame(self, frame: int) -> None:
|
||||||
extra = 0
|
extra = 0
|
||||||
prev_score = 0
|
prev_score = 0
|
||||||
pins = [0] * 10 # reset the pins
|
pins = [0] * 10 # reset the pins
|
||||||
@@ -73,10 +74,10 @@ class Player:
|
|||||||
score = sum(pins)
|
score = sum(pins)
|
||||||
self.rolls.append(score)
|
self.rolls.append(score)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f"{self.name}: {self.rolls}, total:{calculate_score(self.rolls)}"
|
return f"{self.name}: {self.rolls}, total:{calculate_score(self.rolls)}"
|
||||||
|
|
||||||
def show(self, pins):
|
def show(self, pins: List[int]) -> None:
|
||||||
pins_iter = iter(pins)
|
pins_iter = iter(pins)
|
||||||
print()
|
print()
|
||||||
for row in range(4):
|
for row in range(4):
|
||||||
@@ -87,14 +88,14 @@ class Player:
|
|||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def centreText(text, width):
|
def centre_text(text: str, width: int) -> str:
|
||||||
t = len(text)
|
t = len(text)
|
||||||
return (" " * ((width - t) // 2)) + text
|
return (" " * ((width - t) // 2)) + text
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
print(centreText("Bowl", 80))
|
print(centre_text("Bowl", 80))
|
||||||
print(centreText("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", 80))
|
print(centre_text("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY", 80))
|
||||||
print()
|
print()
|
||||||
print("WELCOME TO THE ALLEY.")
|
print("WELCOME TO THE ALLEY.")
|
||||||
print("BRING YOUR FRIENDS.")
|
print("BRING YOUR FRIENDS.")
|
||||||
|
|||||||
273
14_Bowling/python/test_bowling.py
Normal file
273
14_Bowling/python/test_bowling.py
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
import io
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from _pytest.capture import CaptureFixture
|
||||||
|
from _pytest.monkeypatch import MonkeyPatch
|
||||||
|
|
||||||
|
from bowling import main
|
||||||
|
|
||||||
|
|
||||||
|
def test_bowling_strikes(monkeypatch: MonkeyPatch, capsys: CaptureFixture[str]) -> None:
|
||||||
|
def perfect_roll(pins: List[int]) -> None:
|
||||||
|
for i in range(20):
|
||||||
|
x = i
|
||||||
|
if x < len(pins):
|
||||||
|
pins[x] = 1
|
||||||
|
|
||||||
|
monkeypatch.setattr("bowling.simulate_roll", perfect_roll)
|
||||||
|
|
||||||
|
instructions1 = "Y"
|
||||||
|
players1 = 1
|
||||||
|
name1 = "Martin"
|
||||||
|
another_game1 = "Y"
|
||||||
|
|
||||||
|
instructions2 = "N"
|
||||||
|
players2 = 2
|
||||||
|
name21 = "Anna"
|
||||||
|
name22 = "Bob"
|
||||||
|
another_game2 = "N"
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"sys.stdin",
|
||||||
|
io.StringIO(
|
||||||
|
f"{instructions1}\n{players1}\n{name1}\n{another_game1}\n"
|
||||||
|
f"{instructions2}\n{players2}\n{name21}\n{name22}\n{another_game2}"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
main()
|
||||||
|
actual = capsys.readouterr().out
|
||||||
|
expected = """ Bowl
|
||||||
|
CREATIVE COMPUTING MORRISTOWN, NEW JERSEY
|
||||||
|
|
||||||
|
WELCOME TO THE ALLEY.
|
||||||
|
BRING YOUR FRIENDS.
|
||||||
|
OKAY LET'S FIRST GET ACQUAINTED.
|
||||||
|
|
||||||
|
THE INSTRUCTIONS (Y/N)? THE GAME OF BOWLING TAKES MIND AND SKILL. DURING THE GAME
|
||||||
|
THE COMPUTER WILL KEEP SCORE. YOU MAY COMPETE WITH
|
||||||
|
OTHER PLAYERS[UP TO FOUR]. YOU WILL BE PLAYING TEN FRAMES.
|
||||||
|
ON THE PIN DIAGRAM 'O' MEANS THE PIN IS DOWN...'+' MEANS THE
|
||||||
|
PIN IS STANDING. AFTER THE GAME THE COMPUTER WILL SHOW YOUR
|
||||||
|
SCORES.
|
||||||
|
FIRST OF ALL...HOW MANY ARE PLAYING?
|
||||||
|
VERY GOOD...
|
||||||
|
Enter name for player 1:
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Martin
|
||||||
|
STRIKE!!!
|
||||||
|
Extra rolls for Martin
|
||||||
|
Martin: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], total:300
|
||||||
|
DO YOU WANT ANOTHER GAME?
|
||||||
|
THE INSTRUCTIONS (Y/N)? FIRST OF ALL...HOW MANY ARE PLAYING?
|
||||||
|
VERY GOOD...
|
||||||
|
Enter name for player 1: Enter name for player 2:
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Anna
|
||||||
|
STRIKE!!!
|
||||||
|
Extra rolls for Anna
|
||||||
|
|
||||||
|
O O O O
|
||||||
|
O O O
|
||||||
|
O O
|
||||||
|
O
|
||||||
|
10 for Bob
|
||||||
|
STRIKE!!!
|
||||||
|
Extra rolls for Bob
|
||||||
|
Anna: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], total:300
|
||||||
|
Bob: [10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10], total:300
|
||||||
|
DO YOU WANT ANOTHER GAME? """ # noqa: W291
|
||||||
|
assert actual.split("\n") == expected.split("\n")
|
||||||
Reference in New Issue
Block a user