0%

Hangman:经典单词游戏

tl,dr

在童年时代的剑桥英语课上,老师为了提高大家学习语言的兴趣带我们玩过类似的猜单词游戏。而再次接触到这个游戏并留下深刻印象(马失前蹄小人突然被吊死,悲惨接受 game over 结局),则要到中学阶段的文曲星上了。
所谓的 classic 随着时代的变化,都成为了并不遥远,但也已经朦朦胧胧的美好记忆了。

游戏规则

基本的游戏规则如下:Wiki/Hangman

交互方式

  1. 游戏开始阶段,玩家需要被告知需要猜测的单词的长度
  2. 玩家每轮提供一次猜测(字母)
  3. 计算机给出对本轮猜测的判定结果
  4. 显示本轮猜测之后当前单词猜测状态(已经猜对的部分显示,未能猜出的部分用符号之类替代留出)

额外规则

  • 每次游戏的玩家可以有 8 次游戏机会。
  • 每轮结束后,计算机给出提示,还有 * 次机会
  • 假定玩家每轮只输入一个字母(A-Z),如果猜测不在答案之中,则本轮失败。
  • 如果玩家多次猜测相同字母,不计入失败,而是显示信息:已经猜过了,请再试一次
  • 猜对单词中的全部字母,则游戏挑战成功。使用完全部机会,则游戏挑战失败

分解函数

而复现这个刽子手的游戏,编程前需要如何规划?

  1. 首先,需要构建两个大模块
    • helper functions, 完成辅助性函数的定义
    • hangman:游戏主程序
  2. 划分功能
    • Is the Word Guessed,
      函数:用来判断这个字母是否已经猜过
      isWordGuessed 函数有两个参数:
      1. string 的 secretWord
      2. list 的 lettersGuessed
      返回 boolean:
      如果secretWord已经猜测过,True
      else False
    • Printing Out the User’s Guess
      函数:用来显示玩家当前猜测轮后单词的“被猜测”状态
      getGuessedWord 也是两个参数,secretWord,lettersGuessed
      secretWord 是 string 需要转成 list 才可以更改
      用' _ ' 代替没有猜到的字母
      返回替代修改后的单词
    • Printing Out all Available Letters
      函数:显示当前可用的单词
      调用了string.ascii_lowercase
      如果字母在猜测过的列表中,则从可用中去除

思考过程

在真正开始搭建游戏的主程序之前,我们先完成小的函数模块。
在 hangman 主程序中拼接小的功能、循环控制游戏进程、提供输入输出的信息与玩家进行交互。
主要用到 list、string 之类的简单知识,并不难但是编程思想非常重要 XD
参考

Code Solution 如下

isWordGuessed(secretWord, lettersGuessed)

1
2
3
4
5
6
7
8
9
10
11
12
def isWordGuessed(secretWord, lettersGuessed):
'''
secretWord: string, the word the user is guessing
lettersGuessed: list, what letters have been guessed so far
returns: boolean, True if all the letters of secretWord are in lettersGuessed;
False otherwise
'''
gussed = True
for elm in secretWord:
if elm not in lettersGuessed:
gussed = False
return gussed

getGuessedWord(secretWord, lettersGuessed)

1
2
3
4
5
6
7
8
9
10
11
12
def getGuessedWord(secretWord,  ):
'''
secretWord: string, the word the user is guessing
lettersGuessed: list, what letters have been guessed so far
returns: string, comprised of letters and underscores that represents
what letters in secretWord have been guessed so far.
'''
ans = list(secretWord)
for i in range(0,len(secretWord)):
if ans[i] not in lettersGuessed:
ans[i] = ' _ '
return ''.join(ans)

getAvailableLetters(lettersGuessed)

1
2
3
4
5
6
7
8
9
10
11
12
def getAvailableLetters(lettersGuessed):
'''
lettersGuessed: list, what letters have been guessed so far
returns: string, comprised of letters that represents what letters have not
yet been guessed.
'''
alpha = list(string.ascii_lowercase)
ans =[]
for i in range(0,len(alpha)):
if alpha[i] not in lettersGuessed:
ans.append(alpha[i])
return ''.join(ans)

hangman

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def hangman(secretWord):

secretWord: string, the secret word to guess.

Starts up an interactive game of Hangman.

* At the start of the game, let the user know how many
letters the secretWord contains.

* Ask the user to supply one guess (i.e. letter) per round.

* The user should receive feedback immediately after each guess
about whether their guess appears in the computers word.

* After each round, you should also display to the user the
partially guessed word so far, as well as letters that the
user has not yet guessed.

Follows the other limitations detailed in the problem write-up.
'''
num_word = len(secretWord)
print("Welcome to the game, Hangman!")
print("I am thinking of a word that is " + str(num_word) + " letters long.")
print("-----------")
letters_Guessed = []
left_guess = 8
while left_guess > 0:
print("You have " + str(left_guess) + " guesses left.")
print("Available letters: " + str(getAvailableLetters(letters_Guessed)))

# get input guess from player:
# Please guess a letter: a

new_input_letter = input("Please guess a letter: ")


# Case one : if You have alreaday guessed

while new_input_letter in letters_Guessed:
print("Oops! You've already guessed that letter: " + str(getGuessedWord(secretWord, letters_Guessed)))
print("-----------")
print("You have " + str(left_guess) + " guesses left.")
print("Available letters: " + str(getAvailableLetters(letters_Guessed)))
new_input_letter = input("Please guess a letter: ")

letters_Guessed.append(new_input_letter)
# Case Two: success guess
if new_input_letter in secretWord:
print("Good guess: " + str(getGuessedWord(secretWord, letters_Guessed)))
print("-----------")
else :
print("Oops! That letter is not in my word: " + str(getGuessedWord(secretWord, letters_Guessed)))
print("-----------")
left_guess -= 1

# check the game win condition
if isWordGuessed(secretWord, letters_Guessed):

print("Congratulations, you won!")
return None

print("Sorry, you ran out of guesses. The word was else.")
return None

Test

进行测试时,我们需要提供包括所有情况的测试案例。

1
2
secretWord = chooseWord(wordlist).lower()
hangman(secretWord)

测试用例

分别使用

1:成功猜测一个短单词的情况

1
2
3
4
5
6
7
8
9
10
Welcome to the game, Hangman!
I am thinking of a word that is 1 letters long.
-----------
You have 8 guesses left.
Available letters: abcdefghijklmnopqrstuvwxyz
Please guess a letter: c
Good guess: c
-----------
Congratulations, you won!
None

2:单词中是重复字母的情况

1
2
3
4
5
6
7
8
9
10
Welcome to the game, Hangman!
I am thinking of a word that is 3 letters long.
-----------
You have 8 guesses left.
Available letters: abcdefghijklmnopqrstuvwxyz
Please guess a letter: z
Good guess: zzz
-----------
Congratulations, you won!
None

3:猜测极短但失败用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Welcome to the game, Hangman!
I am thinking of a word that is 1 letters long.
-----------
You have 8 guesses left.
Available letters: abcdefghijklmnopqrstuvwxyz
Please guess a letter: a
Oops! That letter is not in my word: _
-----------
You have 7 guesses left.
Available letters: bcdefghijklmnopqrstuvwxyz
Please guess a letter: b
Oops! That letter is not in my word: _
-----------
You have 6 guesses left.
Available letters: cdefghijklmnopqrstuvwxyz
Please guess a letter: d
Oops! That letter is not in my word: _
-----------
You have 5 guesses left.
Available letters: cefghijklmnopqrstuvwxyz
Please guess a letter: e
Oops! That letter is not in my word: _
-----------
You have 4 guesses left.
Available letters: cfghijklmnopqrstuvwxyz
Please guess a letter: f
Oops! That letter is not in my word: _
-----------
You have 3 guesses left.
Available letters: cghijklmnopqrstuvwxyz
Please guess a letter: g
Oops! That letter is not in my word: _
-----------
You have 2 guesses left.
Available letters: chijklmnopqrstuvwxyz
Please guess a letter: h
Oops! That letter is not in my word: _
-----------
You have 1 guesses left.
Available letters: cijklmnopqrstuvwxyz
Please guess a letter: i
Oops! That letter is not in my word: _
-----------
Sorry, you ran out of guesses. The word was else.
None

4:游戏最终成功的用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Welcome to the game, Hangman!
I am thinking of a word that is 3 letters long.
-----------
You have 8 guesses left.
Available letters: abcdefghijklmnopqrstuvwxyz
Please guess a letter: a
Good guess: _ _ a
-----------
You have 8 guesses left.
Available letters: bcdefghijklmnopqrstuvwxyz
Please guess a letter: e
Good guess: _ ea
-----------
You have 8 guesses left.
Available letters: bcdfghijklmnopqrstuvwxyz
Please guess a letter: a
Oops! You've already guessed that letter: _ ea
-----------
You have 8 guesses left.
Available letters: bcdfghijklmnopqrstuvwxyz
Please guess a letter: e
Oops! You've already guessed that letter: _ ea
-----------
You have 8 guesses left.
Available letters: bcdfghijklmnopqrstuvwxyz
Please guess a letter: s
Good guess: sea
-----------
Congratulations, you won!
None

5:不断失败的用例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Welcome to the game, Hangman!
I am thinking of a word that is 1 letters long.
-----------
You have 8 guesses left.
Available letters: abcdefghijklmnopqrstuvwxyz
Please guess a letter: x
Oops! That letter is not in my word: _
-----------
You have 7 guesses left.
Available letters: abcdefghijklmnopqrstuvwyz
Please guess a letter: z
Oops! That letter is not in my word: _
-----------
You have 6 guesses left.
Available letters: abcdefghijklmnopqrstuvwy
Please guess a letter: x
Oops! You've already guessed that letter: _
-----------
You have 6 guesses left.
Available letters: abcdefghijklmnopqrstuvwy
Please guess a letter: z
Oops! You've already guessed that letter: _
-----------
You have 6 guesses left.
Available letters: abcdefghijklmnopqrstuvwy
Please guess a letter: y
Good guess: y
-----------
Congratulations, you won!
None