python初学---猜数字游戏(游戏与AI,原创)

最近在学习python,并用python写了一个小时候玩的益智游戏,猜数字游戏,python语言真的是简洁啊,上来就是写代码逻辑,不用加一堆外壳的东西,话不多说,贴代码,取个名字叫guessL1.py,L1顾名思义是初级版本,就是能玩而已,后面会出个稍微高级一点的版本,加点智能化(AI)的东西。

#*********************************L1********************************

import random
print("/*******************************猜数字游戏***********************************/ \
游戏规则:系统随机给出1-9的4位数字,您可以输入您猜测的4位数字,系统会比较并给予反馈,A表示数字对,且位置对,B表示数字对位置不对,如1A2B表示有1位您猜对了数字和位置,有2位您猜对数字,但位置不对。您总共有6次机会,加油哦!")
total='123456789'
answer=random.sample(total,4)
for guessTimes in range(6):
guess=""
for inputErros in range(3):
guess=input("请输入4位1-9的不重复数字:")
if guess.isdigit()==True and len(guess)==4:
guessSet=set(guess)
if len(guessSet)==4 and guessSet.isdisjoint(set('0')):
break
else:
print("您没有理解游戏规则,游戏结束。")
break
A=0
B=0
for j in range(4):
if guess[j]==answer[j]:
A+=1
else:
for k in range(4):
if guess[j]==answer[k]:
B+=1
if A<4:
if guessTimes<5:
print("%dA%dB,您还有%d次机会。" %(A,B,5-guessTimes))
else:
print("很遗憾您没有猜对,答案是%s,再玩一局吧。" %(answer))
else:
print("恭喜您猜对了!")
break

先玩一局吧,python3 guessL1.py,开始

/*******************************猜数字游戏***********************************/ 游戏规则:系统随机给出1-9的4位数字,您可以输入您猜测的4位数字,系统会比较并给予反馈,A表示数字对,且位置对,B表示数字对位置不对,如1A2B表示有1位您猜对了数字和位置,有2位您猜对数字,但位置不对。您总共有6次机会,加油哦!
请输入4位1-9的不重复数字:1234
1A0B,您还有5次机会。
请输入4位1-9的不重复数字:5678
0A2B,您还有4次机会。
请输入4位1-9的不重复数字:7839
1A2B,您还有3次机会。
请输入4位1-9的不重复数字:7694
1A1B,您还有2次机会。
请输入4位1-9的不重复数字:7982
0A3B,您还有1次机会。
请输入4位1-9的不重复数字:1897
恭喜您猜对了!

 

初战告捷!很牛逼的样子。下面简单说一下我玩这游戏的思路(说着说着就啰嗦了。。。):

第一步,1234,没啥说的,因为4位数字是随机的,第一步输啥都行

第二步,5678,第一步反馈是1A0B,说明1234中有一位数字猜对了,那么另外三位数字,就分布在56789中,就尝试5678好了

接下来,第三步要开始动脑了,这里结合第一步和第二步的反馈结果进行猜测,第二步反馈0A2B,说明5678中有两位数字对了(位置不对),第一步1234有一位数字对了(位置也对),加起来3位数字对了,那么最后一位数字9肯定是对的,这里再假定5678中78是对的,位置调整一下,1234中假定3是对的,位置不变,然后就是9,看看运气如何吧

第三步,7839,反馈1A2B

有点接近了,这里9数字肯定是对的,位置可能不对吧,因为总共才有1位位置是对的,9换一下位置,3对的概率是1/4,姑且假设他不对吧,换成4,78假设是对的吧,假设7的位置也对,换成76试试,

第四步,7694,反馈1A1B

有点崩溃,7694不是一个好的尝试,在9数字肯定对的情况下,764只有一位是对的,返回第三步,7839有三位是对的,789应该是对的吧,换回来,3和4都尝试过了,再尝试一下2

第五步,7982,反馈0A3B,结果还不错,猜测789数字是对的,2也不对,那第一步就剩1了,参考第一步的反馈,1肯定在第一位,第四步中7694反馈1A1B,只有7和9是对的,7的位置显然不对,那9的位置就是对的,9在第三位,剩下7和8的位置,根据第二步5678反馈0A2B,8肯定不在第四位,那8只能在第二位了,7在第四位,大概这样吧1897

第六步,1897,恭喜您猜对了!

其实,这不是一个很完美的猜数字过程,人脑就是这样,无法时刻精确抓住所有信息,比如第四步猜7694,显然7894更合适点,还有第五步7982也不合适,因为既然选择2,根据第一步反馈结果,应该把2放在第二位,不过就因为玩的过程中的模糊和不确定性,最终猜对数字时才有了更多的喜悦(辛苦没白费)

 

#*********************************L2**************************

多玩几局游戏,有了稍微深入一点的思考,整个猜数字的过程,还是有一个相对固定的思路的,初次接触可能有点没头绪,慢慢的就找到方法和套路了,这就是常说的经验吧,我发觉我6步内猜出数字的概率还是挺高的。那么能不能改进一下游戏,把玩家的经验体现在游戏里,一般游戏里常有提示或者锦囊啥的,就加这个吧,每做完一步,就给个提示,下一步猜什么合适,或者还剩下多少可能,这个提示,玩家可以选择查看,或者不查看,把每步的提示连起来,就是电脑模拟人玩游戏的过程(AI),听起来就高大上了,虽然是很简单的AI,话不多说,先贴代码

 

import random
import time

def runGame(testAnswer):
for i in range(10):
playGuess(testAnswer);
if i==9:
print("您已经玩了10局了,休息一下吧。")
else:
again=input("您还想再玩一局吗?输入y再玩一局,按其他键退出:")
if again!='y':
break

def playGuess(testAnswer):
print("/*******************************猜数字游戏***********************************/ \
游戏规则:系统随机给出1-9的4位数字,您可以输入您猜测的4位数字,系统会比较并给予反馈,A表示数字对,且位置对,B表示数字对位置不对,如1A2B表示有1位您猜对了数字和位置,有2位您猜对数字,但位置不对。您总共有6次机会,加油哦!")
answer=getAnswer(testAnswer)
answerSet=answerSetInit(set())
for guessTimes in range(6):
for inputErros in range(3):
guess=input("请输入4位1-9的不重复数字:")
if guess.isdigit()==True and len(guess)==4:
guessSet=set(guess)
if len(guessSet)==4 and guessSet.isdisjoint(set('0')):
break
else:
print("您没有理解游戏规则,游戏结束。")
return
A,B=compareAnswer(guess,answer)
if A<4:
if guessTimes<5:
print("%dA%dB,您还有%d次机会。" %(A,B,5-guessTimes))
delCount=answerSetDelNum(answerSet,guess,A,B)
answerSetUpd(answerSet,guess,A,B)
helpFlag=input("输入h查看帮助,按其他键继续游戏:")
if helpFlag=='h':
print("本次排除可能答案:%d个,剩余:%d个" %(delCount,len(answerSet)))
print(helpInfo(answerSet))
if len(answerSet)<=200:
print(answerSet)
print("推荐数字:",suggestedNum(answerSet,100) )
else:
print("很遗憾您没有猜对,答案是%s,再玩一局吧。" %(answer))
else:
print("恭喜您猜对了!")
break

def guessTrainner(testAnswer):
start =time.time()
answer=getAnswer(testAnswer)
print (answer)
answerSet=answerSetInit(set())
for i in range(6):
inputStrMax=suggestedNum(answerSet,100)
print('第%d步----' %(i+1), end="")
print('尝试:' +inputStrMax, end="")
print('----', end="")
AMax,BMax = compareAnswer(inputStrMax, answer)
print('反馈:%dA%dB' % (AMax, BMax), end="")
print('----', end="")
print('排除可能答案:%d个' % (answerSetDelNum(answerSet,inputStrMax,AMax,BMax)))
answerSetUpd(answerSet,inputStrMax,AMax,BMax)
if AMax==4:
elapsed = (time.time() - start)
print("猜数字成功,总用时:%f秒,总步数:%d。" %(elapsed,i+1))
break
elif i==5:
print("猜数字失败!")

def getAnswer(testAnswer):
total = '123456789'
answer = random.sample(total, 4)
if testAnswer > 999:
answer = str(testAnswer)
return answer

def compareAnswer(inputStr,answerStr):
A=0
B=0
for j in range(4):
if inputStr[j]==answerStr[j]:
A+=1
else:
for k in range(4):
if inputStr[j]==answerStr[k]:
B+=1
return A,B

def answerSetInit(answerSet):
answerSet.clear()
for i in range(1234,9877):
seti=set(str(i))
if len(seti)==4 and seti.isdisjoint(set('0')):
answerSet.add(str(i))
return answerSet

def answerSetUpd(answerSet,inputStr,A,B):
answerSetCopy=answerSet.copy()
for answerStr in answerSetCopy:
A1,B1=compareAnswer(inputStr,answerStr)
if A!=A1 or B!=B1:
answerSet.remove(answerStr)

def answerSetDelNum(answerSet,inputStr,A,B):
i=0
for answerStr in answerSet:
A1, B1 = compareAnswer(inputStr, answerStr)
if A!=A1 or B!=B1:
i+=1
return i

def helpInfo(answerSet):
answer0=set()
answer1=set()
answer2=set()
answer3=set()
for answerStr in answerSet:
answer0.add(answerStr[0])
answer1.add(answerStr[1])
answer2.add(answerStr[2])
answer3.add(answerStr[3])
helpInfoStr="提示:第一位可能是"+"|".join(answer0)+",第二位可能是"+"|".join(answer1)+",第三位可能是"+"|".join(answer2)+",第四位可能是"+"|".join(answer3)
return helpInfoStr

def suggestedNum(answerSet,lvl):
suggestedNum=''
delCountMax=0
if len(answerSet) > lvl:
suggestedNum = list(answerSet)[0]
else:
for inputStr in answerSet:
delCount = 0
for answerStr in answerSet:
A,B = compareAnswer(inputStr, answerStr)
delCount += answerSetDelNum(answerSet, inputStr,A,B)
if delCount > delCountMax:
delCountMax = delCount
suggestedNum = inputStr
if delCount == delCountMax:
if suggestedNum == '' or int(suggestedNum) > int(inputStr):
suggestedNum = inputStr
# print(inputStr+'-----'+str(delCount)+'-----'+str(delCountMax)+'-----'+suggestedNum)
return suggestedNum


代码量翻了不少倍!玩玩看!

➜ python python3 -c "import guess;guess.runGame(1)"

/*******************************猜数字游戏***********************************/ 游戏规则:系统随机给出1-9的4位数字,您可以输入您猜测的4位数字,系统会比较并给予反馈,A表示数字对,且位置对,B表示数字对位置不对,如1A2B表示有1位您猜对了数字和位置,有2位您猜对数字,但位置不对。您总共有6次机会,加油哦!
请输入4位1-9的不重复数字:1234
2A0B,您还有5次机会。
输入h查看帮助,按其他键继续游戏:h
本次排除可能答案:2904个,剩余:120个
{'1538', '8264', '1268', '9634', '6934', '7236', '8734', '1297', '8534', '1674', '1974', '1754', '7834', '1287', '1537', '5236', '1279', '6534', '1637', '7934', '1954', '1784', '1738', '6734', '9834', '7254', '1539', '5934', '7238', '8254', '1964', '6238', '5274', '1295', '1594', '6274', '6235', '5834', '8294', '8235', '1864', '1739', '1298', '9238', '1894', '6294', '1984', '1684', '9734', '6284', '1938', '8274', '1584', '9534', '8634', '8934', '1836', '1639', '6254', '1735', '1564', '1694', '7239', '5734', '9274', '6237', '1286', '6239', '1267', '1935', '5239', '5634', '9254', '9237', '5237', '1638', '7534', '1854', '1289', '1574', '1276', '1794', '7264', '8237', '5238', '1278', '1764', '1936', '5264', '1937', '1259', '7235', '9236', '1635', '8239', '9284', '7634', '1839', '5294', '7294', '9264', '1874', '8236', '1285', '1296', '1256', '1837', '1835', '1257', '1265', '1654', '7284', '1269', '1258', '1736', '6834', '5284', '1275', '9235', '1536'}

提示:第一位可能是7|5|6|9|1|8,第二位可能是7|5|6|9|8|2,第三位可能是7|5|6|9|8|3,第四位可能是7|5|6|9|8|4
推荐数字: 1538
请输入4位1-9的不重复数字:1538
0A1B,您还有4次机会。
输入h查看帮助,按其他键继续游戏:h
本次排除可能答案:108个,剩余:12个

{'8264', '7254', '5274', '8294', '6284', '8274', '6254', '9254', '5264', '9284', '5294', '7284'}
提示:第一位可能是7|5|6|9|8,第二位可能是2,第三位可能是7|5|6|9|8,第四位可能是4
推荐数字: 5264
请输入4位1-9的不重复数字:5264
恭喜您猜对了!
您还想再玩一局吗?输入y再玩一局,按其他键退出:y
/*******************************猜数字游戏***********************************/ 游戏规则:系统随机给出1-9的4位数字,您可以输入您猜测的4位数字,系统会比较并给予反馈,A表示数字对,且位置对,B表示数字对位置不对,如1A2B表示有1位您猜对了数字和位置,有2位您猜对数字,但位置不对。您总共有6次机会,加油哦!
请输入4位1-9的不重复数字:1234
0A2B,您还有5次机会。
输入h查看帮助,按其他键继续游戏:h
本次排除可能答案:2184个,剩余:840个
提示:第一位可能是7|5|6|9|8|2|3|4,第二位可能是7|5|6|9|1|8|3|4,第三位可能是7|5|6|9|1|8|2|4,第四位可能是7|5|6|9|1|8|2|3
推荐数字: 4378
请输入4位1-9的不重复数字:4378
1A1B,您还有4次机会。
输入h查看帮助,按其他键继续游戏:h
本次排除可能答案:692个,剩余:148个
{'4752', '8329', '7319', '4517', '3972', '5346', '7392', '5472', '4527', '7315', '2648', '9471', '4761', '6382', '8319', '4157', '9382', '4197', '4729', '7352', '7128', '7361', '4862', '4725', '4829', '4185', '3628', '6349', '8316', '2386', '9148', '3572', '3158', '7329', '8362', '3518', '2458', '4693', '6381', '4627', '4953', '4762', '2973', '4715', '5382', '8351', '4819', '9345', '6327', '7391', '2475', '8391', '9381', '4581', '4682', '5173', '4917', '3928', '4653', '6428', '4861', '4927', '7325', '3672', '7316', '4825', '6173', '4681', '2871', '4892', '2476', '8352', '2718', '9317', '4593', '6317', '7351', '8392', '2948', '4719', '5428', '5148', '3528', '7362', '8361', '9472', '5418', '7326', '3618', '2389', '4792', '2479', '6345', '3176', '4851', '2468', '4815', '2357', '2673', '9428', '9346', '4563', '8326', '8172', '3571', '4716', '8315', '4891', '6471', '9173', '4189', '4582', '8325', '6148', '9327', '2498', '4981', '4852', '4982', '2548', '4816', '4826', '2397', '9418', '5471', '4963', '5327', '3168', '3175', '5349', '6472', '4791', '3918', '6418', '2573', '3971', '3179', '2385', '5381', '4617', '3671', '5317', '4186', '2367', '4751', '4167', '3198', '4726'}

提示:第一位可能是7|5|6|9|8|2|3|4,第二位可能是7|5|6|9|1|8|3|4,第三位可能是7|5|6|9|1|8|2|4,第四位可能是7|5|6|9|1|8|2|3
推荐数字: 4752
请输入4位1-9的不重复数字:4752
0A3B,您还有3次机会。
输入h查看帮助,按其他键继续游戏:h
本次排除可能答案:140个,剩余:8个
{'7325', '2476', '5428', '2479', '2548', '5471', '5327', '2573'}

提示:第一位可能是7|5|2,第二位可能是5|4|3,第三位可能是7|4|2,第四位可能是7|5|6|9|1|8|3
推荐数字: 2476
请输入4位1-9的不重复数字:2476
1A1B,您还有2次机会。
输入h查看帮助,按其他键继续游戏:h
本次排除可能答案:6个,剩余:2个
{'5428', '2548'}

提示:第一位可能是5|2,第二位可能是5|4,第三位可能是4|2,第四位可能是8
推荐数字: 2548
请输入4位1-9的不重复数字:2548
1A3B,您还有1次机会。
输入h查看帮助,按其他键继续游戏:h
本次排除可能答案:1个,剩余:1个
{'5428'}

提示:第一位可能是5,第二位可能是4,第三位可能是2,第四位可能是8
推荐数字: 5428
请输入4位1-9的不重复数字:5428
恭喜您猜对了!
您还想再玩一局吗?输入y再玩一局,按其他键退出:

玩这游戏变的轻松好多,几乎不用动脑,根据提示的可能性,随便玩玩就能猜出答案!

 

还有更高级的,模拟电脑玩游戏

➜ python python3 -c "import guess;guess.guessTrainner(1)"
['6', '4', '7', '3']
第1步----尝试:7861----反馈:0A2B----排除可能答案:2184个
第2步----尝试:6947----反馈:1A2B----排除可能答案:786个
第3步----尝试:6729----反馈:1A1B----排除可能答案:43个
第4步----尝试:6374----反馈:2A2B----排除可能答案:10个
第5步----尝试:6473----反馈:4A0B----排除可能答案:0个
猜数字成功,总用时:0.541268秒,总步数:5。
➜ python python3 -c "import guess;guess.guessTrainner(1)"
['5', '8', '2', '3']
第1步----尝试:9642----反馈:0A1B----排除可能答案:2304个
第2步----尝试:8795----反馈:0A2B----排除可能答案:502个
第3步----尝试:1983----反馈:1A1B----排除可能答案:171个
第4步----尝试:5184----反馈:1A1B----排除可能答案:41个
第5步----尝试:3586----反馈:0A3B----排除可能答案:5个
第6步----尝试:5823----反馈:4A0B----排除可能答案:0个
猜数字成功,总用时:0.411014秒,总步数:6。
➜ python python3 -c "import guess;guess.guessTrainner(1)"
['4', '1', '2', '6']
第1步----尝试:7569----反馈:0A1B----排除可能答案:2304个
第2步----尝试:5842----反馈:0A2B----排除可能答案:502个
第3步----尝试:9421----反馈:1A2B----排除可能答案:199个
第4步----尝试:1624----反馈:1A3B----排除可能答案:18个
第5步----尝试:4126----反馈:4A0B----排除可能答案:0个
猜数字成功,总用时:0.082934秒,总步数:5。
➜ python python3 -c "import guess;guess.guessTrainner(1)"
['7', '6', '4', '2']
第1步----尝试:1258----反馈:0A1B----排除可能答案:2304个
第2步----尝试:9316----反馈:0A1B----排除可能答案:598个
第3步----尝试:7489----反馈:1A1B----排除可能答案:104个
第4步----尝试:2467----反馈:0A4B----排除可能答案:16个
第5步----尝试:7624----反馈:2A2B----排除可能答案:1个
第6步----尝试:7642----反馈:4A0B----排除可能答案:0个
猜数字成功,总用时:0.080719秒,总步数:6。
➜ python python3 -c "import guess;guess.guessTrainner(1)"
['2', '5', '1', '4']
第1步----尝试:2173----反馈:1A1B----排除可能答案:2544个
第2步----尝试:2345----反馈:1A2B----排除可能答案:455个
第3步----尝试:2754----反馈:2A1B----排除可能答案:23个
第4步----尝试:2451----反馈:1A3B----排除可能答案:1个
第5步----尝试:2514----反馈:4A0B----排除可能答案:0个
猜数字成功,总用时:0.105326秒,总步数:5。

 

 



posted @ 2020-06-30 17:41  funolove  阅读(1835)  评论(0编辑  收藏  举报