您的位置:首页 > 编程语言 > Python开发

Python项目(一)Hangman游戏实现与破解

2016-10-29 15:46 2176 查看

摘要:本篇博客将介绍Hangman游戏的规则,Python实现以及该游戏的破解玩法。

1.Hangman游戏介绍

Hangman百度百科:http://baike.baidu.com/view/516149.htm

对该游戏进行如下简述:

a.该游戏主要是猜单词,由两个人进行,设A为出题者,B为猜单词的人;

b.当B猜错时,A进行名为“上吊的小人”绘画,每次画一笔,一幅完整的“上吊的小人”需要七笔;

c.当B猜对时,A需要在单词所有位置处是该字母的位置处写上所猜字母,没猜到的用下划线“_”表示;

游戏终止于以下条件:

a.A画完“上吊的小人”;

b.B在A画完之前猜对单词。

现在对游戏进行编程语意简化:

a.由系统随机从文件“words.txt”中选取一个单词,仅给出单词长度;

b.每次所猜字母由人手动输入,由程序进行判断正误,并且由程序打印输出所猜单词情况以及还能用来猜的字母列表;

c.假设程序共给人有7次猜错的机会,当猜对或者猜了以前猜过的字母时,不累计猜错次数;

d.不要再想当然以为假如给的单词字母不同且超过8个岂不是一定错了?记住猜对了以及猜过的再猜是不累计猜错次数的!

2.程序设计预备细节

2.1.如何随机从“words.txt”中随机选择一个单词?

直接上程序:

f=open("words.txt",'r',-1)#-1表示使用默认的缓冲区大小
line=f,read()#"words.txt"内部只有一行,单词之间以空格分隔
wordlist=line.split()#将读取的字符串以空格分开,并存为列表
secretWord=random.choice(wordlist)#随机选取一个单词,注意使用之前需要import random



2.2.如何判断所猜字母是否是正确的?

直接上程序:

if ch in secretWord:#in关键字用于判断是否在母串中出现子串

2.3.如何将待选字母串中的某个字母删除?

ss=ss.replace(ch,'')#用空代替该字母


3.程序设计思路

首先,随机选择一个单词作为secretWord,并计算长度用于打印输出猜中的部分。然后建立一个大循环,终止条件是剩余猜测机会为0,循环内部进行猜测、判断、输出猜中部分。只要在循环内部能够猜中,则游戏成功否则失败。

4.Hangman.源代码

# Hangman game
#

# -----------------------------------
# Helper code
# You don't need to understand this helper code,
# but you will have to know how to use the functions
# (so be sure to read the docstrings!)

import random
import string

WORDLIST_FILENAME = "words.txt"

def loadWords():
"""
Returns a list of valid words. Words are strings of lowercase letters.

Depending on the size of the word list, this function may
take a while to finish.
"""
print ("Loading word list from file...")
# inFile: file
inFile = open(WORDLIST_FILENAME, 'r', -1)
# line: string
line = inFile.readline()
# wordlist: list of strings
wordlist = line.split()
print ("  ", len(wordlist), "words loaded.")
inFile.close()
return wordlist

def chooseWord(wordlist):
"""
wordlist (list): list of words (strings)

Returns a word from wordlist at random
"""
return random.choice(wordlist)

# end of helper code
# -----------------------------------

# Load the list of words into the variable wordlist
# so that it can be accessed from anywhere in the program

'''
*****************
'''
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
'''
for c in set(secretWord):
if not c in lettersGuessed:
return False
return True

'''
*****************
'''
def getGuessedWord(secretWord, lettersGuessed):
'''
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.
'''
ss=""
for s in set(lettersGuessed):
if s in secretWord:
ss=ss+s
return ss

'''
*****************
'''
def getAvailableLetters(lettersGuessed):
'''
lettersGuessed: list, what letters have been guessed so far
returns: string, comprised of letters that represents what letters h
badc
ave not
yet been guessed.
'''
ss="abcdefghijklmnopqrstuvwxyz"
for c in lettersGuessed:
ss=ss.replace(c,'')
return ss

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.
'''
print("*************************************\n\
TEST:secretWord is %s\n\
************************************"%secretWord)
print("Length of secretWord is %d"%len(secretWord))
print("Welcome to the game, Hangman!\n\
I am thinking of a word that is %d letters long."%len(secretWord))
lettersGuessed=''#已经猜过的字符串
AvailableLetters=getAvailableLetters(lettersGuessed)
GuessedWord=getGuessedWord(secretWord, lettersGuessed)#猜中的字符串
tmp_str=""
for i in range(0,len(secretWord)):
tmp_str=tmp_str+"_ "
left=8
while left>0:
print("You have %d guesse(s) left."%left)
print("Available letters:%s"%AvailableLetters)
print("Please guess a letter:",end='')
while 1:
c=input()
if ('a'<=c<='z' or 'A'<=c<='Z')and len(c)==1:
c=c.lower()
break
print("Wrong input!Please guess a letter:")
if c in lettersGuessed:
print("Oops! You've already guessed that letter:%s"%tmp_str)
else:
lettersGuessed=lettersGuessed+c
AvailableLetters=getAvailableLetters(lettersGuessed)
if c in secretWord:
GuessedWord=GuessedWord+c
tmp_str=""
for tmp in secretWord:
if tmp in GuessedWord:
tmp_str=tmp_str+" "+tmp
else:
tmp_str=tmp_str+" "+"_"
print("Good guess:%s"%tmp_str)
if isWordGuessed(secretWord, lettersGuessed):
print("Congratulations, you won!")
break
else:
left=left-1
print("Oops! That letter is not in my word:%s"%tmp_str)
if not isWordGuessed(secretWord, lettersGuessed):
print("Sorry, you ran out of guesses. The word was else.")

wordlist = loadWords()
secretWord=chooseWord(wordlist)
hangman(secretWord)

# When you've completed your hangman function, uncomment these two lines
# and run this file to test! (hint: you might want to pick your own
# secretWord while you're testing)

# secretWord = chooseWord(wordlist).lower()
# hangman(secretWord)


5.Hangman破解

5.1.设计思路

为了简单,仍然是由程序随机选择一个单词,而本次猜单词的也将有程序完成。具体思路如下:

a.首先由所给单词长度将猜单词的待选库压缩至只包含该长度的单词;

b.建立猜中单词的字典,字典的键和值分别是索引位置和对应字母,根据猜中部分的字母,将单词待选库中的对应索引位置不同的单词再删去;

c.按单词待选库中字母出现的频次排序来选择每次的用于猜测的字母,注意单词待选库的不断更新。

5.2.Hangman游戏破解源代码

# -*- coding: utf-8 -*-
"""
Created on Fri Oct 28 11:56:55 2016

@author: gzp
"""

import random
__cnt=0
WORDLIST_FILENAME = "words.txt"

def loadWords():
print ("Loading word list from file...")
inFile = open(WORDLIST_FILENAME, 'r', -1)
line = inFile.readline()
wordlist = line.split()
print ("  ", len(wordlist), "words loaded.")
inFile.close()
return wordlist

def chooseWord(wordlist):
return random.choice(wordlist)

def isWordGuessed(secretWord, lettersGuessed):
for c in set(secretWord):
if not c in lettersGuessed:
return False
return True

def getGuessedWord(secretWord, lettersGuessed):
ss=""
for s in set(lettersGuessed):
if s in secretWord:
ss=ss+s
return ss

def getAvailableLetters(lettersGuessed):
ss="abcdefghijklmnopqrstuvwxyz"
for c in lettersGuessed:
ss=ss.replace(c,'')
return ss
def updateBase0(oldBase,eleLen):
newBase=[]
for ele in oldBase:
if eleLen==len(ele):
newBase.append(ele)
return newBase

def upDateBase1(oldBase,dct={}):
newBase=[]
flag=True
for ele in oldBase:
for key in dct.keys():
if dct[key]!=ele[key]:
flag=False
break
else:
flag=True
if True==flag:
newBase.append(ele)
return newBase

def getCharLst(newBase,AvailableLetters):
dct={}
CharLst=''
for ch in AvailableLetters:
dct[ch]=0
for s in newBase:
dct[ch]=dct[ch]+s.count(ch)
lst=[(dct[ch], ch) for ch in dct]
lst.sort()
lst.reverse()
for i,ch in lst:
CharLst=CharLst+ch
return CharLst

def hangmanCracker(InitBase,secretWord):
cntGuessed=0
eleLen=len(secretWord)
lettersGuessed=''#已经猜过的字符串
AvailableLetters=getAvailableLetters(lettersGuessed)
GuessedWord=getGuessedWord(secretWord, lettersGuessed)#猜中的字符串
tmp_str=""
idx=0
newBase=updateBase0(InitBase,eleLen)
dct={}
len1=0
len2=0
CharLst=getCharLst(newBase,AvailableLetters)
for i in range(0,len(secretWord)):
tmp_str=tmp_str+"_ "
left=8
while left>0:
print("You have %d guesse(s) left."%left)

if 0==cntGuessed:
c=CharLst[0]
else:
if len1==len2:
#print("**********************")
newBase=upDateBase1(newBase,dct)
CharLst=getCharLst(newBase,AvailableLetters)
idx+=1
c=CharLst[idx]

else:
newBase=upDateBase1(newBase,dct)
#print("########")
CharLst=getCharLst(newBase,AvailableLetters)
c=CharLst[0]
idx=0
print("Available letters:%s"%CharLst)
print("Please guess a letter:",end='')
cntGuessed=cntGuessed+1
print("%s"%c)
print("Parent guessed time(s):%d"%cntGuessed)

if c in lettersGuessed:
print("Oops! You've already guessed that letter:%s"%tmp_str)
else:
lettersGuessed=lettersGuessed+c
AvailableLetters=getAvailableLetters(lettersGuessed)
if c in secretWord:
GuessedWord=GuessedWord+c
tmp_str=""
len2=len(dct)
for i,tmp in enumerate(secretWord):
if tmp in GuessedWord:
tmp_str=tmp_str+" "+tmp
dct[i]=tmp
else:
tmp_str=tmp_str+" "+"_"
print("Good guess:%s"%tmp_str)
len1=len(dct)
if isWordGuessed(secretWord, lettersGuessed):
global __cnt
__cnt=__cnt+1
print("Congratulations, you won!")
break
else:
left=left-1
print("Oops! That letter is not in my word:%s"%tmp_str)
if not isWordGuessed(secretWord, lettersGuessed):
print("Sorry, you ran out of guesses. The word was else.")

for i in range(100):
wordlist = loadWords()
secretWord=chooseWord(wordlist)
hangmanCracker(wordlist,secretWord)
print(__cnt)


结束语:

在写这个程序的时候深感Python的便利,其对于字符串、字典等的操作可以减少很多的代码编辑。对于这个破解方法仍然有改进的地方,或者使用神经网络可以更好的预测剩余的字母,从而提高速度和精度。

欢迎交流和指正。。。。

相关下载:

1.Hangman.py

2.HangmanCracker.py

3.words.txt
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: