Beispiel #1
0
    def _initialize(self, initialization_object: dict = None) -> None:
        """ Initializes the game of Hangman

        :param initialization_object - an optional dictionary containing the required game parameters to use
        """
        initialization_object = self._get_user_input(initialization_object)
        self.difficulty = initialization_object["difficulty"]
        self.dictionary = dictionary.Dictionary(self.config)
        word_sizes_by_difficulty = self.config["word_sizes_by_difficulty"][self.difficulty]
        self.min_word_length = word_sizes_by_difficulty["min_word_length"]
        self.max_word_length = word_sizes_by_difficulty["max_word_length"]
        self.board = GameBoard(self.config["board_length"], self.config["board_width"], " ")
        self.noose = noose.Noose(self.board)
        self.noose.draw()
Beispiel #2
0
def test_is_complete():
    """ Tests noose.Noose.is_complete method """
    test_board = GameBoard(10, 10, " ")
    noose_object = noose.Noose(test_board)
    # Initially not all components will be displayed so ensure that the noose is not complete
    assert not noose_object.is_complete()
    for component in noose_object.noose_components:
        component["displayed"] = True
    # After forcefully displaying all components though, the noose should be complete
    assert noose_object.is_complete()
Beispiel #3
0
    def construct_board(length: int,
                        width: int,
                        board: GameBoard = None) -> GameBoard:
        """ Creates a new board of the given length and width if an existing board is not provided

        :param length - the length of a new board to create
        :param width - the width of a new board to create
        :param board - an existing board to use
        """
        if not board:
            board = GameBoard(length, width)
        return board
Beispiel #4
0
def test_update():
    """ Tests noose.Noose.update method """
    test_board = GameBoard(10, 10, " ")
    noose_object = noose.Noose(test_board)
    previous_pointer = noose_object.next_piece
    assert not noose_object.is_complete()
    for i in range(pytest.large_iteration_count):
        noose_object.update()
        current_pointer = noose_object.next_piece
        if current_pointer < len(noose_object.noose_components):
            assert current_pointer == previous_pointer + 1
        previous_pointer = current_pointer
    assert previous_pointer == current_pointer and noose_object.is_complete()
Beispiel #5
0
def test_last_displayed():
    """ Tests noose.Noose.get_last_displayed method """
    test_board = GameBoard(10, 10, " ")
    noose_object = noose.Noose(test_board)
    # When first created the noose object should have a pointer to the element right after the last displayed
    assert noose_object.get_last_displayed() == noose_object.next_piece - 1
    idx = 0
    for component in noose_object.noose_components:
        if component["displayed"]:
            idx += 1
        else:
            break
    assert noose_object.get_last_displayed() == idx - 1
Beispiel #6
0
def test_draw():
    """ Tests noose.Noose.draw method """
    empty_char = " "
    test_board = GameBoard(10, 10, empty_char)
    noose_object = noose.Noose(test_board)
    noose_object.draw()
    components_on_grid = set()
    for component in noose_object.noose_components:
        if component["displayed"]:
            components_on_grid.add(repr(component["part"]))
            # Ensure that if a component is supposed to be displayed that the board has been refreshed with it
            assert test_board.board[component["x_index"]][
                component["y_index"]] == repr(component["part"])
    for column in test_board.board:
        for element in column:
            # Ensure that no other elements beyond the displayed parts and the empty square character are on the board
            assert element == empty_char or element in components_on_grid
Beispiel #7
0
def test_noose_construction():
    """ Tests noose.Noose constructor and noose_components class attribute """
    test_board = GameBoard(10, 10, " ")
    noose_object = noose.Noose(test_board)
    required_parts = [
        "base", "pole", "top", "rope", "head", "body", "left_leg", "right_leg",
        "left_arm", "right_arm"
    ]
    expected_representations = [
        "_", "|", "_", "|", "O", "|", "/", "\\", "-", "-"
    ]
    # Test that all required parts are present
    for part, representation in zip(required_parts, expected_representations):
        found = False
        for component in noose_object.noose_components:
            component_part = component["part"]
            if part == component_part.part:
                # Ensure the matching part has the expected character representation
                assert repr(component_part) == representation and str(
                    component_part) == representation
                found = True
        assert found
Beispiel #8
0
class HangmanGame(Game):
    """ Contains the necessary logic to run a game of Hangman

    Constructor parameters:

    @param config - the configuration dictionary to use for the game (should be defined in data packaged with pygme)
    @param name - the name of the game to feed to parent class
    @param difficulty - a difficulty to assume (provided by user during initialization)
    """

    def __init__(self, config: dict, name: str = "hangman", difficulty: str = "normal") -> None:
        super().__init__(name, config, difficulty)
        self.dictionary = None
        self.noose = None
        self.min_word_length = None
        self.max_word_length = None
        self.guessed_characters = set()
        self.board = None
        self.noose = None
        self.word = None

    def _validate_initialization(self, initialization_object: dict) -> None:
        """ Validates the initialization object to ensure a Hangman game can occur

        :param initialization_object - required game parameters to follow
        """
        self._validate_base(initialization_object)

    def _initialize(self, initialization_object: dict = None) -> None:
        """ Initializes the game of Hangman

        :param initialization_object - an optional dictionary containing the required game parameters to use
        """
        initialization_object = self._get_user_input(initialization_object)
        self.difficulty = initialization_object["difficulty"]
        self.dictionary = dictionary.Dictionary(self.config)
        word_sizes_by_difficulty = self.config["word_sizes_by_difficulty"][self.difficulty]
        self.min_word_length = word_sizes_by_difficulty["min_word_length"]
        self.max_word_length = word_sizes_by_difficulty["max_word_length"]
        self.board = GameBoard(self.config["board_length"], self.config["board_width"], " ")
        self.noose = noose.Noose(self.board)
        self.noose.draw()

    def _has_won(self) -> bool:
        """ Checks whether the player has won the game by checking if all the letters in the word have been guessed

        :returns True if the game has been won; False otherwise
        """
        for letter in self.word:
            if letter not in self.guessed_characters:
                return False
        return True

    def _man_died(self) -> bool:
        """ Checks whether the man has died by checking if the noose is complete

        :returns True if the man is dead; False otherwise
        """
        return self.noose.is_complete()

    def _is_game_over(self) -> bool:
        """ Checks whether the game has finished from two possible options - the player has won (guessed all letters) or
        the man has died

        :returns True if the game is over; False otherwise
        """
        if self._has_won() or self._man_died():
            return True
        return False

    def _display_word(self) -> None:
        """ Prints the current word to be guessed by hiding characters that have not been guessed yet when displaying
        the word to the user """
        if not self.guessed_characters:
            self.word.hide_all = True
        else:
            self.word.hide_all = False
            self.word.show_only = self.guessed_characters
        print("Word to guess:\n{0}\n".format(repr(self.word)))
        print("Guessed character: {0}\n".format(self.guessed_characters))

    def _display_final_status(self) -> None:
        """ Displays a message to let the user know how they did after the game finishes """
        self.word.show_only = set()
        self.word.hide_all = False
        print("\nThe word was: {0}\n".format(repr(self.word)))
        if self._has_won():
            print("Congratulations, you won!")
        else:
            print("Better luck next time!")

    def _get_guess_input(self) -> str:
        """ Accepts string input from the user to be the next guess (for monkeypatching instead of built-in input func)

        :returns the string input received from the user
        """
        return input("Enter a character to guess next:")

    def _get_guess(self) -> str:
        """ Retrieves a letter guess from the user and validates it before returning it to be used in the game

        :returns a single ASCII character to be the next letter guess in the game
        """
        guess_valid = False
        guess = None
        while not guess_valid:
            guess = self._get_guess_input()
            # Ensure the guess has not been already provided
            if guess in self.guessed_characters:
                print("You already guessed that character. Try again.")
            # There must be a guess
            elif len(guess) > 1:
                print("You can only enter one character at a time")
            # The guess must be either a lowercase or upper case letter
            elif guess not in string.ascii_letters:
                print("Guesses must be one of {0}".format(string.ascii_letters))
            else:
                guess_valid = True
        self.guessed_characters.add(guess)
        return guess

    def run(self, initialization_object: dict = None) -> dict:
        """ Runs the game of Hangman

        :param initialization_object - an optional dictionary containing the required game parameters to use
        """
        self._initialize(initialization_object)
        self.word = self.dictionary.get_random_word(min_length=self.min_word_length, max_length=self.max_word_length)
        assert len(self.word) > 1
        while not self._is_game_over():
            # Display noose and word on board
            self.board.print(join_char="")
            self._display_word()
            guess = self._get_guess()
            # Get the noose to display a new piece if the guess is wrong
            if guess not in self.word:
                self.noose.update()
            # Update the current noose on the board to be displayed to the user
            self.noose.draw()
        self.board.print(join_char="")
        self._display_final_status()
        return {}