用Python编程以显示在show子手游戏中猜到的字母不起作用

时间:2019-05-27 10:44:27

标签: python

我必须用Python编写有关玩playing子手游戏的代码。目前,我的代码无法用猜中的字母正确替换“ _”,只能替换其中的一个而不显示所有猜中的字母。

我的代码如下:

import random

word = random.choice(["bread", "clouds", "plane"])

guess = 0
correct_guess = 0
play_again = True

print(word)
name = input("Hello, what's your name? ")
print('Hello', name)
status = input('Do you wish to play hangman? Yes/No ')
hyphens = print('_ ' * (len(word)))

if status == 'No' 'no' 'N' 'n':
  exit()

while play_again is True:

  letter = input('Guess a letter: ')

  if letter in word:
    guess = guess + 1
    correct_guess = correct_guess + 1
    print('You guessed a letter correctly!')
    position = word.find(letter)
    print("The letter is in position", position + 1, "out of", len(word), "in the word. Guess Count:", guess)
    if position == 0:
      print(letter, "_ _ _ _")
    if position == 1:
      print("_", letter, "_ _ _ ")
    if position == 2:
      print("_ _", letter, "_ _ ")
    if position == 3:
      print("_ _ _", letter, "_ ")
    if position == 4:
      print("_ _ _ _", letter)
  else:
    guess = guess + 1
    print("That letter isn't in the word. Guess Count:", guess)
  if guess == 10:
    print('Bad luck. You lost.')
    play = input('Do you want to play again? ')
    if play == 'No' 'no' 'N' 'n':
      exit()
  if correct_guess == 5:
    print('Congratulations! You have guessed the word! The word was', word + '.')
    play = input('Do you want to play again? ')
    if play == 'No' 'no' 'N' 'n':
      exit()

非常感谢您的帮助。另外,我对编程知识不多,而且还很陌生。

詹姆斯

3 个答案:

答案 0 :(得分:1)

您不能像这样写表达式:

if status == 'No' 'no' 'N' 'n':

正确的方法是:

if play == 'No' or play == 'no' or play == 'N' or play == 'n':

或:

if play in ['No' ,'no', 'N' ,'n']

一种解决方案:

import random

word = random.choice(["bread", "clouds", "plane"])


print(word)
name = input("Hello, what's your name? ")
print('Hello', name)
status = input('Do you wish to play hangman? Yes/No ')


def play():
    if status == 'No' or status == 'no' or status == 'N' or status == 'n':
        print ("Goodbye")
        return # exit 
    else:
        print('_ ' * (len(word))) # _ _ _ _ _ 

    guess = 0
    correct_guess = 0
    play_again = True

    pos_list = ['_' for x in range(len(word))] # define list where you will put your guessed letters ['_', '_', '_', '_', '_']
    while play_again is True:
      letter = input('Guess a letter: ')

      if letter in word:
        guess = guess + 1
        correct_guess = correct_guess + 1
        print('You guessed a letter correctly!')
        position = word.find(letter)
        print("The letter is in position", position + 1, "out of", len(word), "in the word. Guess Count:", guess)
        pos_list[position] = letter # save letter at position # ['_', '_', '_', 'a', '_']
        print (' '.join(pos_list)) # _ _ _ a _

      else:
        guess = guess + 1
        print("That letter isn't in the word. Guess Count:", guess)
      if guess == 10:
        print('Bad luck. You lost.')
        play = input('Do you want to play again? ')
        if play == 'No' or play == 'no' or play == 'N' or play == 'n':
            print("Goodbye")
            return
        else:
             print('_ ' * (len(word)))
      if correct_guess == len(word):
        print('Congratulations! You have guessed the word! The word was', word + '.')
        play = input('Do you want to play again? ')
        if play == 'No' or play == 'no' or play == 'N' or play == 'n':
            print("Goodbye")
            return
        else:
            print('_ ' * (len(word)))

play()

答案 1 :(得分:0)

稍微清理一下,删除重复的代码。也是有问题的情况:

if status == 'No' 'no' 'N' 'n':

将其更改为:

if status.lower().startswith("n"):

降低用户输入的字母也很重要。这里是完整的工作代码。

import random
import re

def start():
    status = input('Do you wish to play hangman? Yes/No ')
    if status.lower().startswith("n"):
        return True
    # Computer chooses word
    word = random.choice(["bread", "clouds", "plane"])
    # Setup game vars
    guess = []
    game_status = ["_"] * len(word)

    while True:
        print(" ".join(game_status))
        letter = input('Guess a letter: ').lower()
        if letter in guess:
            print("You already tried that one.")
            continue
        guess.append(letter)
        if letter in word:
            print('You guessed a letter correctly!')
            positions = [m.start() for m in re.finditer(letter, word)]
            for pos in positions:
                game_status[pos] = letter
        else:
            print("That letter isn't in the word.")
        if len(guess) == 10:
            print(f'Bad luck {name}. You lost. The word was: {word}.')
            return
        if "_" not in game_status:
            print(f'Congratulations {name}! You have guessed the word! The word was {word}.')
            return

# Welcome
name = input("Hello, what's your name? ")
print('Hello', name)
while True:
    stop = start()
    if stop:
        break
print("Goodbye!")

答案 2 :(得分:0)

TL; DR ' '.join(l if l in guessed_letters else '_' for l in word)是一个衬里,但对于OP,我已经详细介绍了。

我想对我的评论稍加扩展。

编写出色代码的一种方法是颠倒编写和测试代码,然后对尚未编写的代码进行先测试。这就是测试驱动的开发

有许多测试代码的工具,例如unittest,但我将在此处演示的一个工具是pytest

首先,我们确定我们要实现的一小部分功能。在这种情况下,以hangman形式返回字符串。这需要两个输入,我们要猜的单词和字母要猜的单词。我想将其实现为一个函数,所以我将编写该函数,但现在放置pass

现在是时候用输入和期望输出注释功能了。 现在总比没有好。

def hangman_word(word, guessed_letters):
    """Returns a string in hangman form where letters are hyphens
    or guessed letters. Letters or hyphens are space separated.

    `word` is a string. This is the word to be printed in hangman form.

    `guessed_letters` is a list of the letters guessed that should be shown.

    For example::

        >>> hangman_word('bordereau', ['o', 'd', 'e'])
        '_ o _ d e _ e _ _'

    """
    pass

然后我们编写测试,但是我们故意这样做。我们想涵盖可能出问题的不同方面...不要猜测字母,重复字母,字母顺序与单词顺序不同。每个测试都针对每个方面。 Pytest将对以test_开头的函数运行测试。

def test_hangman_word_no_guessed_letters():
    assert hangman_word('zonule', []) == '_ _ _ _ _ _'
def test_hangman_word_one_letter():
    assert hangman_word('zonule', ['n']) == '_ _ n _ _ _'
def test_hangman_word_multiple_letters_ordered():
    assert hangman_word('zonule', ['n', 'u']) == '_ _ n u _ _'
def test_hangman_word_multiple_letters_unordered():
    assert hangman_word('zonule', ['u', 'n']) == '_ _ n u _ _'
def test_hangman_word_repeated_letters():
    assert hangman_word('bordereau', ['o', 'd', 'e']) == '_ o _ d e _ e _ _'
def test_hangman_word_guessed_letter_wrong():
    assert hangman_word('hypostrophe', ['o', 'd', 'e']) == '_ _ _ o _ _ _ o _ _ e'
def test_hangman_word_multiple_repeats():
    assert hangman_word('intempestive', ['t', 'd', 'e']) == '_ _ t e _ _ e _ t _ _ e'
def test_hangman_word_all_letters():
    assert hangman_word('intempestive', list('intempestive')) == 'i n t e m p e s t i v e'

if __name__ == '__main__':
    print('main has run')

如果我运行pytest,则使用功能hangman_word和这些测试一起在名为hang_man.py的文件中进行测试

C:\Users\Andrew\Desktop>pytest hang_man.py

我会得到详细的报告

C:\Users\Andrew\Desktop>pytest hang_man.py
============================= test session starts =============================
platform win32 -- Python 3.4.0, pytest-4.2.0, py-1.7.0, pluggy-0.8.1
rootdir: C:\Users\Andrew\Desktop, inifile:
collected 8 items

hang_man.py FFFFFFFF                                                     [100%]

================================== FAILURES ===================================
____________________ test_hangman_word_no_guessed_letters _____________________

    def test_hangman_word_no_guessed_letters():
>       assert hangman_word('zonule', []) == '_ _ _ _ _ _'
E       AssertionError: assert None == '_ _ _ _ _ _'
E        +  where None = hangman_word('zonule', [])

hang_man.py:21: AssertionError
________________________ test_hangman_word_one_letter _________________________

    def test_hangman_word_one_letter():
>       assert hangman_word('zonule', ['n']) == '_ _ n _ _ _'
E       AssertionError: assert None == '_ _ n _ _ _'
E        +  where None = hangman_word('zonule', ['n'])

<<REMOVED>>
========================== 8 failed in 0.21 seconds ===========================

因此所有8个测试均失败。 。现在我们可以编写代码了。

现在我知道足够的python编写一个内衬,所以我将pass替换为

return ' '.join(l if l in guessed_letters else '_' for l in word)

当我再次运行pytest时...

C:\Users\Andrew\Desktop>pytest hang_man.py
=========================================================================================================== test session starts ============================================================================================================
platform win32 -- Python 3.4.0, pytest-4.2.0, py-1.7.0, pluggy-0.8.1
rootdir: C:\Users\Andrew\Desktop, inifile:
collected 8 items

hang_man.py ........                                                                                                                                                                                                                  [100%]
=================== 8 passed in 0.13 seconds ===================

这里的要点是我拥有知道的可重复使用的代码,因为我已经对其进行了测试,现在我可以继续进行其他方面的工作,例如计算不正确的猜测和无效的输入方面。

完整的代码解决方案

我决定使用面向对象的状态模式设计(出于自我学习的目的)来实现此目的,因此我想也将其保留在这里。虽然代码比功能样式大,但优点是代码可测试性强,可以很好地将游戏机制与输入分开。

运行游戏只是运行问题:

game = Context('represents', lives=15)
game.startGame()
class Context(object):
    """A class that keeps track of the hangman game context and current state.
    This follows a State Design Pattern.

    `word` is string. This is the word to guess.
    `guessed_letters` is a list containing letters guessed
    `lives` is a number that is the number of incorrect guesses allowed.
    `state` is class representing the state of the game.
    `message` is a string message from processing the letter guess.

    The :meth:`.process` method processes guessed letters, updating the
    lives, guessed_letters and message for the gameplay.
    """
    def __init__(self, word, lives=10):
        self.word = word
        self.guessed_letters = []
        self.lives = lives
        self.state = HoldingState()
        self.message = ''

    def won(self):
        """Tests if all letters of in word are in guessed_letters"""
        return all(l in self.guessed_letters for l in self.word)

    def lost(self):
        """Tests if we have run out of lives"""
        return self.lives <= 0

    def hangman_word(self):
        """Returns a string in hangman form where letters are hyphens
        or guessed letters. Letters or hyphens are space separated.

        `word` is a string. This is the word to be printed in hangman form.

        `guessed_letters` is a list of the letters guessed that should be shown.

        For example::

            >>> hangman_word('bordereau', ['o', 'd', 'e'])
            '_ o _ d e _ e _ _'

        """
        return ' '.join(l if l in self.guessed_letters else '_' for l in self.word)

    def process(self, letter):
        """Requests the state to process the guessed letter.

        The State takes care of updating the lives, guessed_letters and providing a
        message for the gameplay"""
        self.state.process(letter, self)

    def startGame(self):
        """Runs the game.

        Checks for final states (WonState / DeadState) else shows the hangman
        word, letters guessed and takes as input the letter guessed and 
        processes this.

        """
        while True:
            if self.state == WonState():
                print(f'You win! The word was indeed {self.word}')
                return
            if self.state == DeadState():
                print(f'You lose! The word was {self.word}')
                return
            print('Hangman Word:', self.hangman_word() + '\n')
            print('Letters guessed: ' + ' '.join(sorted(self.guessed_letters)) + '\n')
            letter = input('Guess a letter: ')
            self.process(letter)
            print('\n' + self.message + '\n')


class BaseState(object):
    """Represents a state of the context.

    This is an abstract base class. Subclasses must override and
    implement the :meth:`.process` method.

    The :meth:`.process` method updates the context variables and changes the
    context state.

    """
    def process(self, letter, context):
        """Updates the context variables and changes the context state..

        **This method is not implemented in this base class; subclasses
        must override this method.**

        """
        raise NotImplementedError

    def __eq__(self, other):
        """Overrides the default implementation

        Tests equality of states by testing if there are the same class

        """
        if isinstance(other, self.__class__):
            return True
        return False

class HoldingState(BaseState):
    """The default state."""
    def process(self, letter, context):
        if letter in context.guessed_letters:
            context.state = RepeatedGuessState()
        elif letter in context.word:
            context.state = CorrectGuessState()
        else:
            context.state = IncorrectGuessState()
        # Calls process again to return to HoldingState / WonState / DeadState
        context.state.process(letter, context)

class RepeatedGuessState(BaseState):
    """An intermediate state."""
    def process(self, letter, context):
        context.message = "You've repeated a guess!"
        context.state = HoldingState()

class CorrectGuessState(BaseState):
    """An intermediate state."""
    def process(self, letter, context):
        context.message = "Correct guess!"
        context.guessed_letters.append(letter)
        if context.won():
            context.state = WonState()
        else:
            context.state = HoldingState()

class IncorrectGuessState(BaseState):
    """An intermediate state."""
    def process(self, letter, context):
        context.lives -= 1
        context.message = f"Incorrect guess! You've lost a life. {context.lives} lives remaining"
        context.guessed_letters.append(letter)
        if context.lost():
            context.state = DeadState()
        else:
            context.state = HoldingState()

class DeadState(BaseState):
    """A final state representing a lost game."""
    def process(self, letter, context):
        pass

class WonState(BaseState):
    """A final state representing a game won."""
    def process(self, letter, context):
        pass

if __name__ == '__main__':
    game = Context('represents')
    game.startGame()

这通过了以下测试(pytest):

def test_start_to_correct():
    game = Context('represents')
    game.process('r')
    assert game.state == HoldingState()
    assert game.lives == 10

def test_start_to_incorrect():
    game = Context('represents')
    game.process('i')
    assert game.state == HoldingState()
    assert game.lives == 9

def test_repeated_guess():
    game = Context('represents')
    game.process('i')
    game.process('i')
    assert game.state == HoldingState()
    assert game.lives == 9

def test_guesses():
    game = Context('word', lives=4)
    game.process('a')
    assert game.lives == 3

def test_win():
    game = Context('word', lives=4)
    game.process('w')
    game.process('o')
    game.process('r')
    game.process('d')
    assert game.state == WonState()

def test_lost():
    game = Context('wort', lives=4)
    game.process('a')
    assert game.lives == 3
    game.process('b')
    assert game.lives == 2
    game.process('c')
    assert game.lives == 1
    game.process('d')
    assert game.lives == 0
    assert game.state == DeadState()