首页 » 父与子的编程之旅:与小卡特一起学Python » 父与子的编程之旅:与小卡特一起学Python全文在线阅读

《父与子的编程之旅:与小卡特一起学Python》22.9 又到了游戏时间Hangman

关灯直达底部

既然讨论的是文件,为什么要在这一章建立一个游戏呢?嗯,Hangman 游戏之所以有趣,原因在于它有一个庞大的词汇表,可以从这个词汇表中选择题目。要做到这一点,最容易的办法就是从文件中读取。我们仍然使用 PythonCard 来完成这个游戏,也想由此说明并非只能使用 Pygame 建立图形化游戏。

我不打算像介绍其他程序那样详细地解释这个程序。现在你应该已经会看代码了,相信你能自己搞清楚其中大部分代码的作用。我只会稍稍给你一点指导,帮助你顺利读懂代码。

Hangman GUI

我们的 Hangman 程序的主 GUI 是像下图这样的:

这里显示了上吊小人的各个部分,不过程序运行时,我们首先会隐藏小人的所有部分。玩家猜错一个字母时,就会显示这个小人的下一部分。如果整个小人都显示出来,玩家可以再猜一次,然后游戏结束!

玩家猜一个字母时,程序会查看这个字母是否在秘密词中。如果确实是秘密词中的字母,就把这个字母显示出来。在窗口下方,玩家可以看见到目前为止他猜过的所有字母。玩家什么时候都可以尝试猜词。

下面概括一下这个程序的工作原理。

开始时,程序完成以下工作:

  • 从文件加载词汇表;

  • 从每行的末尾去除换行符;

  • 让小人的所有部分都不可见;

  • 从词汇表随机选择一个词;

  • 根据秘密词中的字母个数显示相同数目的横线。

玩家点击 Guess! 按钮时,程序做以下工作。

  • 检查猜的是一个字母还是一个词。

  • 如果是一个字母:

    • 检查秘密词,查看是否包含这个字母。

    • 如果玩家猜对了,用这个字母取代横线,显示这个字母出现在什么位置。

    • 如果玩家猜错了,显示小人的另一部分。

    • 把猜出的字母增加到 Previous guesses 显示区。

    • 查看玩家是否已经猜出单词(猜出所有字母)。

  • 如果是一个词:

    • 检查玩家猜得正确与否。

    • 如果正确,显示一个对话框,指出 You Won!(你赢了!)并开始新游戏。

  • 查看玩家是不是已经没有机会了,如果是,显示一个对话框,指出 You Lost(你失败了),并显示这个秘密词到底是什么。

从词汇表得到单词

这一章讨论的是文件,所以下面来看程序中得到词汇表的部分。相应代码如下:

words.txt 文件只是一个文本文件,所以可以使用 readlines 读这个文件。为了从词汇表中选择一个词,我们使用了 random.choice 函数,如下:

self.currentword = random.choice(self.lines)  

显示小人

要跟踪已经显示了小人的哪些部分,另外下一步要显示哪一部分,这有很多方法。我们决定使用一个循环,代码如下:

def wrong(self):       self.pieces_shown += 1       for i in range(self.pieces_shown):   self.pieces[i].setHidden(False)       if self.pieces_shown == len(self.pieces):   message = /"You lose.  The word was /" + self.currentword   QtGui.QMessageBox.warning(self,/"Hangman/",message)   self.new_game  

我们使用 self.pieces_shown 来跟踪上吊小人显示了多少部分。如果所有的部分都显示出来了,我们就使用一个对话框来告知玩家他输了。

检查猜到的字母

这个程序最难的一部分就是检查玩家猜到的字母,看它是否出现在秘密词中。这个工作之所以困难,是因为字母可能在一个单词中出现多次。例如,如果秘密词是 lever,玩家猜到了 e,就必须把第 2 个和第 4 个字母都显示出来,因为它们都是 e。

我们有几个函数来完成这项工作。find_letters 函数会查找某个字母在单词中出现的所有位置,并返回一个包含这些位置的列表。例如,对于字母 e 和单词 lever,这个函数会返回 [1, 3],因为字母 e 出现在这个字符串的索引 1 和索引 3 的位置上。(记住,索引从 0 开始。)代码如下:

replace_letters 函数从 find_letters 得到列表,用正确的字母替换这些位置上的横线。在我们的例子中(lever 中的字母 e),它会用 -e-e- 替换 -----。这就向玩家显示出猜对的字母出现在单词的什么位置,其余仍然为横线。代码如下:

def replace_letters(string, locations, letter):    new_string = /'/'    for i in range (0, len(string)):if i in locations:    new_string = new_string + letterelse:    new_string = new_string + string[i]    return new_string 

玩家猜一个字母时,我们使用刚才定义的两个函数 find_lettersreplace_letters

整个程序大约 95 行代码,另外我还加入了一些空行,让代码看起来更美观。代码清单 22-8 给出了整个程序,这里加了对各个不同部分做的一些解释。如果使用本书的安装程序,你的计算机上的 ExamplesHangman 文件夹中应该已经有这个代码了,另外也可以在网站上找到这个代码,包括 hangman.py、hangman.ui 和 words.txt。切记,正如我们在第 20 章提到的,如果你使用的是 Mac,则需要在 Qt Designer 中打开 hangman.ui,并勾选掉 menubar 对象的 nativeMenuBar 属性。

代码清单 22-8 完整的 hangman.py 程序

为了简化起见,我们的 Hangman 程序只使用了小写字母。我们提供的单词表只有小写字母,用户也必须将其猜测的内容以小写形式输入。

新游戏开始时,处的 dashes 函数使用横杠替换了字母。但它并没有替换标点符号,比如撇号。所以如果单词是 doesn/'t,玩家将会看到 -----/'-

建议你自己创建这个程序。可以用 Qt Designer 构建 GUI,即使看上去与这里的版本不完全一样也没有关系。不过一定要仔细查看代码,看看组件分别使用什么名字。代码中的名字必须与 .ui 文件中的名字一致。

尽可能自己键入代码。运行程序,看看结果怎么样。如果你想做些不同的尝试,那就放手去做!充分尝试,大胆试验,并享受其中的快乐。这正是编程最有意思也最有收获的地方,大多数知识都是通过这个途径获得的。

你学到了什么

在这一章,你学到了以下内容。

  • 什么是文件。

  • 如何打开和关闭文件。

  • 打开文件的不同方式:读、写和追加。

  • 写文件的不同方法:writeprint >>

  • 如何使用 pickle 在文件中保存列表和对象(以及其他 Python 数据结构)。

  • 很多与文件夹(也称为目录)、文件位置和路径相关的内容。

我们还建立了一个 Hangman 游戏,这个游戏使用来自文件的数据得到一个词汇表。

测试题

1. Python 中用来处理文件的对象称为 ________。

2. 如何创建一个文件对象?

3. 文件对象和文件名之间有什么区别?

4. 完成文件读写时应该对文件做什么操作?

5. 如果用追加模式打开一个文件然后在文件中写入内容会怎样?

6. 如果用写模式打开一个文件然后在文件中写入内容会怎样?

7. 读过文件的一部分之后如何从文件起始位置开始读?

8. 将一个 Python 对象保存到文件中要使用哪个 pickle 函数?

9. 要“还原”一个对象 ( 从 pickle 文件得到对象 , 并放回到 Python 变量中 ),应当使用哪个 pickle 方法?

动手试一试

1. 建立程序造一些滑稽句子。每个句子应该至少有 4 部分,类似于:

The ____________ _______________ ______________ _________________

(形容词) ( 名词 ) ( 动词短语 )( 副词短语 )

例如:

这个程序会随机选择一个形容词、一个名词、一个动词短语和一个副词短语来创建句子。这些单词都存储在文件中,可以使用“记事本”创建这些单词。要完成这个程序,最简单的方法是为这 4 组单词分别创建一个文件,不过也可以采用你希望的任何方式创建文件。下面给出一些点子来启发一下你,不过,我相信你也能提出自己的想法。

  • 形容词:crazed, silly, shy, goofy, angry, lazy, obstinate, purple

  • 名词:monkey, elephant, cyclist, teacher, author, hockey player

  • 动词短语:played a ukulele, danced a jig, combed his hair, flapped her ears

  • 副词短语:on the table, at the grocery store, in the shower, after breakfast,with a broom

再给出一个示例输出:“The lazy author combed his hair with a broom”。

2. 编写一个程序,让用户输入名字、年龄、最喜欢的颜色和最喜欢的食物。程序要把所有这 4 项保存在一个文本文件中,每一项分别放在单独的一行上。

3. 完成第 2 题的任务,不过使用 pickle 将数据保存到一个文件。(提示:如果先把数据放在一个列表中就会很容易做到。)