Python算法- 为游戏“鬼”智能查找所有“获胜”字母排列的方法
我正在写一个电脑程序来玩单词游戏“鬼魂”。
现在这个程序的工作方式是这样的:
--用户选择一个字母(目前只有用户先出手时才能使用)
--电脑有一个包含所有可能的奇数单词的字典列表(这样用户必须完成每个单词,否则就会输)。在用户每次选择字母后,电脑会通过一个循环来缩减它的单词列表:
wordList = [w for w in wordList if w.startswith(currentWord)]
这样它的“wordList”中只保留符合当前正在拼写的单词。
--然后,电脑从当前的单词列表中随机选择一个单词,并返回这个单词的相应字母。接着,它会通过以下代码更新自己的列表:
randomnumber = random.randint(0, len(wordList)-1)
currentWord+=wordList[randomnumber][len(currentWord)]
wordList = [w for w in wordList if w.startswith(currentWord)]
--这个过程会持续进行,直到用户拼出一个单词,这会通过checkLoss函数来检测,或者电脑无法继续拼单词而触发checkBluff函数。checkBluff函数要求用户写出他在想的单词,以确保他不是在编造。
--*问题在这里:* 显然,因为电脑是随机选择字母,所以有些单词会导致输。例如,如果第一个玩家选择字母“d”,那么电脑很可能会选择“e”,因为有很多单词以“de”开头。然而,如果用户在第三轮选择字母“e”,使得当前拼写为“dee”,那么电脑的列表中就没有符合的单词(英语中只有一个符合这个形式的单词:'deed',而且是偶数,因此会输),所以触发了bluff函数,电脑就输了,因为用户揭示他想到的确实是一个真实的单词“deed”。
所以,我想要一个算法,让电脑提前思考,这样它就不会选择一个让第一个玩家强制输的后续字母。 例如,如果选择了“d”,电脑就不应该选择“e”,因为这样会导致后面再选一个“e”就会输。同样,如果用户选择了“h”,电脑就不应该跟着选“o”,因为用户可以再说“c”,这样就会拼出“hock”。
我想不出办法来实现这个。
如果需要,这里是完整的程序:
import os, random, sys, math, string
def checkBluff(currentWord, choice, fullList):
if choice.startswith(currentWord):
#print "this is accurate"
for line in fullList:
if line == choice:
return 1
return 0
def checkLoss(currentWord, fullList):
for line in fullList:
if currentWord == line:
return 1
return 0
def instantiateWordList(dictionary, wordList):
for line in dictionary:
wordList.append(line.strip())
return wordList
def main():
fullDict = open("wordlist.txt", "r") #fullDict contains all possible words
winFirst = open("firstwin.txt", "r") #winFirst contains all odd-numbered words
winSecond = open("secondwin.txt", "r")#winSecond contains all even-numbered words
turn = "Human"
currentWord = ""
wordList = []
fullList= []
bluff = ""
#Instantiates a list with every word for use in evaluating win/loss
for line in fullDict:
fullList.append(line.strip())
#Decide who goes first
choice = raw_input("1. I will go first \n2. I will go second\n>>")[0]
if choice == "1":
wordList = instantiateWordList(winSecond, wordList)
turn == "Human"
else:
wordList = instantiateWordList(winFirst, wordList)
turn == "Computer"
while True:
if turn == "Human":
choice = raw_input("Choose a letter: ")[0]
currentWord+=choice
if checkLoss(currentWord, fullList) == 1:
print "You have lost by spelling the word "+ currentWord
break
print "**Current Word**"+ currentWord
wordList = [w for w in wordList if w.startswith(currentWord)]
turn = "Computer"
if turn == "Computer":
try:
randomnumber = random.randint(0, len(wordList)-1)
currentWord+=wordList[randomnumber][len(currentWord)]
print "I am thinking of the word: "+ str(wordList[randomnumber])
wordList = [w for w in wordList if w.startswith(currentWord)]
print "**Current word**: "+ currentWord
print "length: "+ str(len(wordList))
turn = "Human"
except StandardError:
bluff = raw_input("I call bluff. What word were you thinking of?\n>>")
if checkBluff(currentWord, bluff, fullList) == 1:
print "You actually won!"
break
else:
print "You lost. You lying son of a bitch."
break
if __name__ == "__main__":
main()
2 个回答
为了让程序不输,它还需要保留一个偶数位置单词的列表(哦,它确实有,只是我一开始没注意到)
在决定下一个字母时,程序应该先查看它的偶数位置(失去的)单词列表。如果有 n+2 个字符长的单词(当 n=1 时是4个字符,n=3 时是6个字符等等,n
是当前字母的位置),那么它就不应该使用那些单词中 n 位置的字母。
举个“deed”的例子:
- 用户输入“d”
- 程序发现有一个以“d”开头且长度为4个字符的单词:“deed”。
- 它把“deed”中第1个字母(也就是“e”)加到“限制”字母的列表里。
- 它扫描“获胜”单词的列表,忽略那些以“de”开头的单词,然后得到一个“可用”字母的列表。
- 它从这个列表中随机选择一个字母并显示给用户。
你想让电脑提前预测,但又要随机选择?:-)
这个游戏其实很简单,也很容易让电脑总是赢,如果你愿意的话。实际上,你可以提前生成一些策略树,这样就能确保电脑获胜。这些策略树其实也不复杂,如果你想的话,可以把它们记住。
如果你不想这样做,那就只需要考虑下一轮的情况。在你提到的例子中,提前一轮就能看到对手可以在下一轮强迫获胜,所以电脑会避免“de”。但这样做并不能避免对手在两轮后让电脑输的情况。
不过,要做到这一点,你需要考虑所有可能的情况。然后你可以在剩下的选择中随机挑选。