Skip to main content
Code Review

Return to Answer

added 134 characters in body
Source Link
scripta
  • 519
  • 2
  • 11

Good and useful pointsNot sure if posting as usualan answer is the right way to do this? Here's the code reworked to take into account suggestions from @Alex Waygood (thanks for good and useful points Alex).

Good and useful points as usual @Alex Waygood.

Not sure if posting as an answer is the right way to do this? Here's the code reworked to take into account suggestions from @Alex Waygood (thanks for good and useful points Alex).

Source Link
scripta
  • 519
  • 2
  • 11

Good and useful points as usual @Alex Waygood.

  • Running pycodestyle did throw up a lot of conflicts with PEP8!
  • Swapped ‘ for " as the string delimiter (seems we’re more likely to need to embed a ‘ than a " within a string).
  • Moved everything relating to the command line out of the hangman module into main.py. The hangman module can then be, for example, used to support a GUI version (next project?). Means saying goodbye to the Gallows class (and excellent docstring suggestion for it)
  • Acted on the suggestion to get the words from a text file but amended slightly - multiple topic files for topic focused word lists.
  • Reading text files allowed experimenting with exception handling. I don’t really get exception handling. If you can predict an exception couldn’t you just write normal code to deal with it?
  • Program now allows for spaces and hyphens in words/names.
  • Adding docstrings comments - a work in progress at the momement. Harder to write than expected, but focuses the mind.
  • Repl here: https://replit.com/@scripta/Hangman?v=1

Hangman.py

"""
Support for a game of hangman
Classes:
 Word
 Guesses
"""
import random
import sys
class Word:
 """Represents the target word for the game. """
 TOPICS = ("bird", "city", "scientist", "animal")
 def __init__(self):
 """Gets random topic and then a random word from that topic's file."""
 self._topic = random.choice(Word.TOPICS)
 filename = (self._topic+".txt")
 try:
 f = open(filename, "r")
 except OSError:
 print("Cannot open word list " + filename + " unable to continue")
 sys.exit()
 with f:
 WORDS = tuple(f.read().splitlines())
 self._word = random.choice(WORDS)
 self.extract_letters()
 @property
 def word(self):
 return self._word
 @property
 def topic(self):
 return self._topic
 @property
 def letters(self):
 return self._letters
 def extract_letters(self):
 """Extracts unique letters from the word,
 discarding spaces and hyphens."""
 uppercase_word = self._word.upper()
 self._letters = set(uppercase_word)
 self._letters.discard(" ")
 self._letters.discard("-")
 def progress(self, guesses):
 """Creates a string of guessed letters, spaces & hyphens.
 Unguessed letters replaced with underscores."""
 progress_string = ""
 for char in self.word:
 if guesses.guessed(char.upper()):
 progress_string += f" {char} "
 elif char == " ":
 progress_string += " "
 elif char == "-":
 progress_string += " - "
 else:
 progress_string += " _ "
 return progress_string
 def guessed(self, guesses):
 """Determines if the player has successfully guessed the word."""
 letters_guessed = self._letters.intersection(guesses.guesses_made)
 return letters_guessed == self._letters
class Guesses:
 """Guesses holds all guesses made (right or wrong)."""
 def __init__(self):
 self.guesses_made = set()
 def guessed(self, char):
 """Determines whether a character already been guessed."""
 return char in self.guesses_made
 def record(self, guess):
 """Adds all valid guesses (wrong or right) to the guesses set."""
 self.guesses_made.add(guess)
 def made(self):
 """Creates a comma separated string of letters guessed so far."""
 guesses_list = sorted(self.guesses_made)
 guesses_string = ",".join(guesses_list)
 return guesses_string

main.py

import hangman
GALLOWS_IMAGES = (" ",
 " \n \n \n \n \n__________",
 " \n | \n | \n | \n | \n_|________",
 " _____\n | \n | \n | \n | \n_|________",
 " _____\n |/ \n | \n | \n | \n_|________",
 " _____\n |/ |\n | \n | \n | \n_|________",
 " _____\n |/ |\n | O \n | \n | \n_|________",
 " _____\n |/ |\n | O \n | | \n | \n_|________",
 " _____\n |/ |\n | O \n | /| \n | \n_|________",
 " _____\n |/ |\n | O \n | /|\\ \n | \n_|________",
 " _____\n |/ |\n | O \n | /|\\ \n | / \n_|________",
 " _____\n |/ |\n | O \n | /|\\ \n | / \\\n_|________",)
def hanged(number_of_bad_guesses):
 return number_of_bad_guesses >= len(GALLOWS_IMAGES) - 1
def draw_gallows(number_of_bad_guesses):
 print(GALLOWS_IMAGES[number_of_bad_guesses])
def display_progress_to_target_word(target_word, guesses):
 print("\n", target_word.progress(guesses))
def display_letters_guessed(guesses):
 print("\nUsed: \n", guesses.made())
def display_topic(target_word):
 print("\nHangman - guess the name of the", target_word.topic)
def get_letter(guesses):
 while True:
 char = input("\nEnter a letter: ")
 char = char.upper()
 if len(char) < 1:
 print("You didn't choose a letter!")
 elif len(char) != 1:
 print("One letter at a time!")
 elif not char.isalpha():
 print("Alphabetic characters only!")
 elif guesses.guessed(char):
 print("You already guessed that letter")
 else:
 break
 return char
def display_status_of_game(target_word, guesses, number_of_bad_guesses):
 display_topic(target_word)
 display_progress_to_target_word(target_word, guesses)
 draw_gallows(number_of_bad_guesses)
 display_letters_guessed(guesses)
def play_game():
 number_of_bad_guesses = 0
 target_word = hangman.Word()
 guesses = hangman.Guesses()
 display_topic(target_word)
 display_progress_to_target_word(target_word, guesses)
 while True:
 guess = get_letter(guesses)
 guesses.record(guess)
 if guess not in target_word.letters:
 number_of_bad_guesses += 1
 display_status_of_game(target_word, guesses, number_of_bad_guesses)
 if target_word.guessed(guesses):
 print("\nYou win, well done")
 break
 if hanged(number_of_bad_guesses):
 print("\nI win. The", target_word.topic, "was:", target_word.word)
 break
if __name__ == "__main__":
 play_game()

scientist.txt

Albert Einstein
Issac Newton
Galileo
Charles Darwin
Copernicus
Aristotle
Niels Bohr
Max Planck
Michael Faraday

city.txt

Sydney
Los Angeles
Frankfurt
Kuala Lumpur

bird.txt

blackbird
buzzard
crow
curlew
dunnock
eagle
firecrest
gannet
goldfinch
heron
hobby
house martin
jackdaw
moorhen
nightingale
quail
robin
skylark
song thrush
sparrow
swallow
swift
tern
waxwing
woodpecker
yellowhammer
black-headed gull

animal.txt

Aardvark
Chimpanzee
Crocodile
Iguana
Squirrel
Walrus
lang-py

AltStyle によって変換されたページ (->オリジナル) /