-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# CS0 Lab - Game and Unit testing | ||
|
||
Possible Points: 100 | ||
|
||
Python lab to explore working with YAML files. | ||
|
||
## Lab Instructions | ||
|
||
1. Open your CS0Lab-... repo in VS Code | ||
2. Create a lab folder **guessing_game** inside your CS0Lab-... repository | ||
3. Inside the lab folder, create the project folder structre as provided in the lab. | ||
4. Type the partial code stub provided and fix all FIXMEs. (80 points) | ||
5. Follow best programming practices by using proper white spaces, comments, etc. | ||
6. Unittest all the important functions using pytest. Install pyyaml and pytest if required. | ||
|
||
```bash | ||
$ pip install pyyaml | ||
$ pytest --version | ||
$ pip install -U pytest | ||
$ pytest test_*.py | ||
$ python -m pytest test_*.py | ||
``` | ||
|
||
7. Test the whole program manually. | ||
8. Create screenshots showing your local test results (pytest and manual test of main script) and save them to the lab folder. (20 points) | ||
9. Update your README file (10 points) as shown here: [https://github.com/rambasnet/csci000-astudent](https://github.com/rambasnet/csci000-astudent) | ||
|
||
## Submission | ||
|
||
Add all the relevant source file(s), documents, and screenshots into the correct lab folder and do a final add, commit, and push before the due date. | ||
|
||
```bash | ||
$ git pull | ||
$ git status | ||
$ git add <filename>… - add each file in the red that is part of this lab | ||
$ git status | ||
$ git commit -m "Final Submission" | ||
$ git push | ||
$ git status | ||
``` | ||
|
||
- Check and make sure the files are actually pushed to your GitHub repo on github.com. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
""" | ||
Game Application - Guess the Number | ||
""" | ||
|
||
__author__ = "FIXME" | ||
__date__ = "FIXME" | ||
__license__ = "MIT" | ||
__course__ = "CSCI 110 Lab" | ||
__semester__ = "Fall 2023" | ||
|
||
from typing import Any, List, Dict | ||
from utility import functions | ||
import settings | ||
|
||
|
||
def clear_screen() -> None: | ||
"""Clears the screen. | ||
""" | ||
print("\033c", end="") | ||
|
||
|
||
def pause() -> None: | ||
"""Pauses the screen. | ||
""" | ||
input("Press Enter to continue...") | ||
clear_screen() | ||
|
||
|
||
def get_menu_option() -> int: | ||
"""Prints menu for player to interact with. | ||
""" | ||
|
||
menu = """ | ||
Menu Options | ||
============ | ||
1. Play Game | ||
2. View Scoreboard | ||
3. Quit | ||
""" | ||
print(menu) | ||
while True: | ||
option = input("Enter one of the menu options [1-3]: ") | ||
if not option.isdigit(): | ||
print("Invalid option. Try again.") | ||
continue | ||
int_option = int(option) | ||
if not 1 <= int_option <= 3: | ||
print("Invalid option. Try again.") | ||
continue | ||
return int_option | ||
|
||
|
||
def play_game(name: str, max_tries: int) -> bool: | ||
print(f"Let's play Guess the Number Game, {name}! Good luck...") | ||
rand = functions.get_random_number() | ||
print('I am thinking of a number between 1 and 20.') | ||
print('You have 5 chances to guess the number.') | ||
tries = 0 | ||
while tries <= max_tries: | ||
# FIXME: Add code to get the user's guess using the correct function in utility/functions.py. | ||
# FIXME: check if the user's guess is correct using the correct function in utility/functions.py. | ||
# FIXME: If the user's guess is correct, print a message and return True for a win. | ||
return True | ||
else: | ||
return False # return False for a loss | ||
|
||
|
||
def main() -> None: | ||
""" | ||
Main function for the game. | ||
""" | ||
clear_screen() | ||
data = functions.read_data(settings.SCORE_BOARD_FILE) | ||
if not data: | ||
data = [] | ||
print('Welcome to the Guess the Number Game!') | ||
print('=====================================') | ||
print("Let's start by entering your name.") | ||
# Ask who's playing? | ||
player = functions.get_player_info() | ||
if not functions.find_player_in_db(data, player['name']): | ||
data.append(player) | ||
|
||
while True: | ||
clear_screen() | ||
option = get_menu_option() | ||
if option == 1: | ||
win = play_game(player['name'], settings.MAX_TRIES) | ||
if win: | ||
player['win'] += 1 | ||
else: | ||
player['loss'] += 1 | ||
elif option == 2: | ||
view_scoreboard(data) | ||
elif option == 3: | ||
# FIXME - Update data to include the new player's info. | ||
# FIXME - Add code to save the data to the file using correct function in utility/functions.py. | ||
functions.save_data(settings.SCORE_BOARD_FILE, data) | ||
print( | ||
f'saving score board to the file {settings.SCORE_BOARD_FILE}') | ||
print("Goodbye!") | ||
break | ||
|
||
|
||
def view_scoreboard(data: List[Any]) -> None: | ||
"""Display data in tabular format. | ||
Args: | ||
data (dict): data of all the players in the database | ||
""" | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
""" | ||
Global Settings for the guessing game. | ||
""" | ||
|
||
MAX_TRIES = 5 | ||
SCORE_BOARD_FILE = "scoreboard.yaml" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
""" | ||
Module to test functions.py. | ||
""" | ||
|
||
from utility import functions | ||
|
||
|
||
def test_save_data() -> None: | ||
"""Tests save_data function. | ||
""" | ||
data = {"name": "John Smith", "win": 2, "loss": 1} | ||
file_name = "test_data.yaml" | ||
functions.save_data(file_name, data) | ||
my_data = functions.read_data(file_name) | ||
assert data == my_data | ||
|
||
|
||
def test_save_data() -> None: | ||
"""Tests save_data function. | ||
""" | ||
file_name = "test_data1.yaml" | ||
data = [{"name": "John Smith", "win": 2, "loss": 1}, | ||
{"name": "Jake Smith", "win": 1, "loss": 0}] | ||
functions.save_data(file_name, data) | ||
my_data = functions.read_data(file_name) | ||
assert data == my_data | ||
|
||
|
||
# FIXME1: Add a test function to unittest the save_data and read_data functions. | ||
# FIXME2: Add a test function to unittest the save_data and read_data functions. | ||
|
||
|
||
def test_get_random_number() -> None: | ||
"""Tests get_random_number function. | ||
""" | ||
random_number = functions.get_random_number() | ||
assert random_number >= 1 and random_number <= 20 | ||
|
||
|
||
def test_check_guessed() -> None: | ||
"""Tests check_guessed function. | ||
""" | ||
assert functions.check_guessed(5, 5) == True | ||
|
||
|
||
# FIXME3: Add a test function to unittest the check_guessed function. | ||
# FIXME4: Add a test function to unittest the check_guessed function. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
""" | ||
Module for utility functions to support the game. | ||
""" | ||
|
||
from typing import Any | ||
import random | ||
import yaml | ||
|
||
|
||
def get_random_number() -> int: | ||
""" | ||
Returns a random integer between 1 and 20, inclusive. | ||
Returns: | ||
int: integer between 1 and 20, inclusive. | ||
""" | ||
return random.randint(1, 20) | ||
|
||
|
||
def read_data(yaml_file_path: str) -> list: | ||
""" | ||
Reads data from the given file path and returns a dictionary. | ||
Args: | ||
file_path (str): path to the file to read. | ||
Returns: | ||
dict: dictionary containing the data read from the file. | ||
""" | ||
data = [] | ||
try: | ||
with open(yaml_file_path, 'r', encoding='utf-8') as file: | ||
data = yaml.safe_load(file) | ||
except FileNotFoundError: | ||
pass | ||
return data | ||
|
||
|
||
def save_data(yaml_file_path: str, data: Any) -> None: | ||
""" | ||
Writes data to the given file path. | ||
Args: | ||
file_path (str): path to the file to write to. | ||
data (dict): data to write to the file. | ||
""" | ||
with open(yaml_file_path, 'w', encoding='utf-8') as file: | ||
yaml.dump(data, file) | ||
|
||
|
||
def check_guessed(rand: int, guess: int) -> bool: | ||
""" | ||
Checks if the guessed number is correct. | ||
Args: | ||
rand (int): the random number that is hidden. | ||
guess (int): the user's guessed number. | ||
Returns: | ||
bool: True if the guessed number is correct, False otherwise. | ||
""" | ||
return rand == guess | ||
|
||
|
||
def get_player_info() -> dict: | ||
""" | ||
Gets new player's info. | ||
Returns: | ||
dict: new player's info as dict. | ||
""" | ||
name = input("What is your name? ") | ||
return {'name': name.strip(), 'win': 0, 'loss': 0} | ||
|
||
|
||
def get_number_between_1_20() -> int: | ||
""" | ||
Gets a number between 1 and 20, inclusive. | ||
Returns: | ||
int: number between 1 and 20, inclusive. | ||
""" | ||
while True: | ||
guess = input("Enter your guess: ") | ||
if not guess.isdigit(): | ||
print("Invalid guess. Try again.") | ||
continue | ||
int_guess = int(guess) | ||
# FIXME: Add code to check if the guess is between 1 and 20, inclusive. | ||
# if not a valid number print error and ask them to try again | ||
return int_guess | ||
|
||
|
||
def find_player_in_db(database: list[Any], name: str) -> Any: | ||
"""Find and return the player in the database. | ||
Args: | ||
database (list[Any]): database of players. | ||
name (str): player's name to search for. | ||
Returns: | ||
None|dict: Returns player as dict if found, None otherwise. | ||
""" | ||
for player in database: | ||
if player['name'] == name: | ||
return player | ||
return None |