Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions solutions/hangman_game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
A module for a Hangman game.
Module contents:
- select_random_word: Selects a random word from a list.
- play_hangman: Manages the Hangman game logic.
Created on 11-01-25
@author: Ameen Agha
"""

import random


def select_random_word(word_list: list) -> str:
"""
Select a random word from a given list.
Parameters:
word_list (list): A list of words to choose from.
Returns:
str: A randomly selected word from the list.
Raises:
AssertionError: If word_list is not a list or is empty.
Examples:
>>> random.seed(1) # Fixing seed for test reproducibility
>>> select_random_word(["python", "hangman", "program"])
'program'
"""
assert (
isinstance(word_list, list) and len(word_list) > 0
), "Input must be a non-empty list."
return random.choice(word_list)


def play_hangman(word: str, guesses: list) -> dict:
"""
Manage the Hangman game logic.
Parameters:
word (str): The word to guess.
guesses (list): A list of guessed letters.
Returns:
dict: A dictionary containing the game state with keys:
- 'progress': The current state of the word (e.g., '_ a n g _ a n').
- 'missed': List of incorrect guesses.
- 'attempts_left': Number of attempts remaining.
- 'status': 'ongoing', 'won', or 'lost'.
Raises:
AssertionError: If word is not a string or guesses is not a list.
Examples:
>>> play_hangman("hangman", ["h", "a", "z"])
{'progress': 'h a _ _ _ a n', 'missed': ['z'], 'attempts_left': 5, 'status': 'ongoing'}
"""
assert isinstance(word, str), "Word must be a string."
assert isinstance(guesses, list), "Guesses must be a list."

max_attempts = 6
missed = [guess for guess in guesses if guess not in word]
attempts_left = max_attempts - len(missed)

progress = " ".join([char if char in guesses else "_" for char in word])

if "_" not in progress:
status = "won"
elif attempts_left <= 0:
status = "lost"
else:
status = "ongoing"

return {
"progress": progress,
"missed": missed,
"attempts_left": attempts_left,
"status": status,
}
67 changes: 67 additions & 0 deletions solutions/tests/test_hangman_game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
Unit test module for the Hangman game.
Contains tests for word selection and game logic.
Created on 11-01-25
@author: Ameen Agha
"""

import unittest
from ..hangman_game import select_random_word, play_hangman


class TestHangmanGame(unittest.TestCase):
"""
Test cases for the Hangman game functions.
These tests ensure random word selection and game logic work as expected.
"""

def test_select_random_word(self):
"""Test random word selection from a valid list."""
random_words = ["python", "hangman", "program"]
word = select_random_word(random_words)
self.assertIn(word, random_words)

def test_select_random_word_invalid_input(self):
"""Test word selection with invalid input."""
with self.assertRaises(AssertionError):
select_random_word(123)

def test_select_random_word_empty_list(self):
"""Test word selection with an empty list."""
with self.assertRaises(AssertionError):
select_random_word([])

def test_hangman_progress(self):
"""Test progress tracking in Hangman."""
result = play_hangman("hangman", ["h", "a", "n"])
expected = {
"progress": "h a n _ _ a n",
"missed": [],
"attempts_left": 6,
"status": "ongoing",
}
self.assertEqual(result, expected)

def test_hangman_missed_guesses(self):
"""Test missed guesses in Hangman."""
result = play_hangman("hangman", ["x", "y", "z"])
self.assertEqual(result["missed"], ["x", "y", "z"])

def test_hangman_attempts_left(self):
"""Test remaining attempts after missed guesses."""
result = play_hangman("hangman", ["h", "x", "y"])
self.assertEqual(result["attempts_left"], 4)

def test_hangman_won(self):
"""Test winning condition in Hangman."""
result = play_hangman("hangman", ["h", "a", "n", "g", "m"])
self.assertEqual(result["status"], "won")

def test_hangman_lost(self):
"""Test losing condition in Hangman."""
result = play_hangman("hangman", ["x", "y", "z", "w", "q", "e", "t"])
self.assertEqual(result["status"], "lost")


if __name__ == "__main__":
unittest.main()