Skip to content

Commit

Permalink
add guessing_game lab
Browse files Browse the repository at this point in the history
  • Loading branch information
rambasnet committed Nov 2, 2023
1 parent 79ec118 commit 831e930
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 0 deletions.
42 changes: 42 additions & 0 deletions labs/guessing_game/README.md
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.
114 changes: 114 additions & 0 deletions labs/guessing_game/main.py
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()
6 changes: 6 additions & 0 deletions labs/guessing_game/settings.py
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.
47 changes: 47 additions & 0 deletions labs/guessing_game/tests/test_functions.py
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.
107 changes: 107 additions & 0 deletions labs/guessing_game/utility/functions.py
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

0 comments on commit 831e930

Please sign in to comment.