首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python Hangman反馈

Python Hangman反馈
EN

Code Review用户
提问于 2014-01-17 16:17:12
回答 1查看 543关注 0票数 2

只是想找些关于刽子手剧本的反馈。它工作得很好,我只是想掌握Python语言,最好的方法就是问真正的大师!

代码语言:javascript
复制
import random

UNKNOWN_CHARACTER = "*"
GUESS_LIMIT = 7

words = []

def load_words():
    global words
    with open("dictionary.txt") as file:
        words = file.readlines()
    stripped = []
    for word in words:
        stripped.append(word.strip())
    words = stripped

def play():
    word = random.choice(words)
    solved = False
    constructed = ""
    guessed = []
    guess = ""
    for i in range(0, len(word)):
        constructed += UNKNOWN_CHARACTER
    while not solved and len(guessed) < GUESS_LIMIT:
        print("\n" + str(GUESS_LIMIT - len(guessed)) + " errors left...")
        print(constructed)
        valid_guess = False
        while not valid_guess:
            guess = input("Guess a letter: ").lower()
            if len(guess) == 1:
                if guess not in guessed and guess not in constructed:
                    valid_guess = True
                else:
                    print("You've already guessed that letter!")
            else:
                print("Please guess a single letter.")
        if guess in word:
            new_constructed = ""
            for i in range(0, len(word)):
                if word[i] == guess:
                    new_constructed += guess
                else:
                    new_constructed += constructed[i]
            constructed = new_constructed
        else:
            guessed.append(guess)
        solved = constructed == word
    print("\n" + word)


def main():
    load_words()
    keep_playing = True
    while keep_playing:
        play()
        keep_going = input("Continue playing? (y/n): ").lower()
        if keep_going not in ["yes", "y"]:
            keep_playing = False

if __name__ == "__main__":
    main()

dictionary.txt节选:

代码语言:javascript
复制
logorrheic
logos
logotype
logotypes
logotypies
logotypy
logroll
logrolled
logroller
logrollers
logrolling
logrollings
logrolls
logs
logway
logways
logwood
logwoods
logy
loin
loincloth
loincloths
loins
loiter
loitered
loiterer
loiterers
loitering
loiters
loll
lollapalooza
lollapaloozas
lolled
loller
lollers
EN

回答 1

Code Review用户

回答已采纳

发布于 2014-01-17 17:56:06

列表理解是在Python中构造列表的一种非常巧妙的方法。例如:

代码语言:javascript
复制
stripped = []
for word in words:
    stripped.append(word.strip())

变成了

代码语言:javascript
复制
stripped = [word.strip() for words in word]

(然后可以在代码中完全消除stripped变量)。

循环某物的节奏式方法是不使用rangelen (除非您真的必须使用)。例如,我们首先:

代码语言:javascript
复制
for i in range(0, len(word)):
    constructed += UNKNOWN_CHARACTER

它可以写成:

代码语言:javascript
复制
for i in word:
    constructed += UNKNOWN_CHARACTER

然后有人可能会说,您可以在这里使用*运算符来编写:

代码语言:javascript
复制
constructed = UNKNOWN_CHARACTER * len(word)

有时,您可能会认为需要使用rangelen,因为需要对应于迭代的索引。这就是enumerate的目的。例如:

代码语言:javascript
复制
        new_constructed = ""
        for i in range(0, len(word)):
            if word[i] == guess:
                new_constructed += guess
            else:
                new_constructed += constructed[i]

变成:

代码语言:javascript
复制
        new_constructed = ""
        for i,l in enumerate(word): # i in the index, l is the letter
            if l == guess: # note that we don't need to get the i-th element here
                new_constructed += l # I prefer l to guess here because it's shorter :-P
            else:
                new_constructed += constructed[i]

这里真正令人敬畏的是能够在同一时间迭代两个以上的容器。zip允许您做这样的事情。

代码语言:javascript
复制
        new_constructed = ""
        for w,c in zip(word,constructed):
            if w == guess:
                new_constructed += w
            else:
                new_constructed += c

然后,它很酷,因为我们可以使事情稍微简洁:

代码语言:javascript
复制
        new_constructed = ""
        for w,c in zip(word,constructed):
            new_constructed += w if w == guess else c

如果您想冷静地使用列表理解(甚至生成器表达式(我使用花哨的单词,以便您可以在需要的情况下搜索):您可以构建某种字符/字符串列表,并将它们与join连接在一起。

代码语言:javascript
复制
        new_constructed = ''.join((w if w == guess else c for w,c in zip(word,constructed)))

尽管如此,我可能不会用这种方式构建字符串,但我只是指出这一点,以便您能够发现新的东西。

通常,全局变量被拒绝,因为它们使事情难以跟踪。在您的例子中,这并不是什么问题,但是让我们尝试将逻辑分割成更小的部分。它使事情更容易理解和测试。

在这里,我们只需要返回来自load_words的单词列表。

储存已经猜到的字母是很有趣的。但是,list (使用[]构建并填充append())可能不是正确的容器。在一天结束时,你真正想要的只是能够快速判断出某个字母是否已经猜到了。这就是sets的目的。

你可以储存所有的猜测,或者只是错误的猜测。您已经决定只存储错误的猜测(因为正确的猜测可以从constructed字符串中推断)。

就个人而言,我宁愿一方面保存所有的猜测,另一方面,错误猜测的次数可能会使以后的事情变得更容易一些。我不是说你做错了什么,我只是想展示一种不同的方式。

另外,我试图分裂过去的逻辑

  1. 显示已发现的与用于
  2. 知道一封信是否已经猜到了
  3. 知道这个角色是否已经完全找到了。

目前,变量constructed在用于这3件事,并可能使事情难以理解。

最后,我想出的是:

代码语言:javascript
复制
#!/usr/bin/python

import random

UNKNOWN_CHARACTER = "*"
GUESS_LIMIT = 7

def load_words():
    words = []
    with open("dictionary.txt") as file:
        words = file.readlines()
    return [word.strip() for word in words]

def play(word):
    nb_wrong = 0
    guesses = set()
    while nb_wrong < GUESS_LIMIT:
        print("\n" + str(GUESS_LIMIT - nb_wrong) + " errors left...")
        print(''.join(c if c in guesses else UNKNOWN_CHARACTER for c in word))
        while True:
            guess = input("Guess a letter: ").lower()
            if len(guess) == 1:
                if guess in guesses:
                    print("You've already guessed that letter!")
                else:
                    guesses.add(guess)
                    break # stop when we have a valid guess 
            else:
                print("Please guess a single letter.")
        if all(c in guesses for c in word):
            break # stop when all characters are found
    print("\n" + word)


def main():
    words = load_words()
    while True:
        play(random.choice(words))
        if input("Continue playing? (y/n): ").lower() not in ["yes", "y"]:
            break

if __name__ == "__main__":
    main()

(它没有经过很高的测试,但重点在于解释我做了什么,而不是向你展示一个工作程序)

票数 6
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/39484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档