---利用启发式搜索策略模拟机器人进行井字棋对弈---
文章目录
实现井字棋人机对弈小游戏编程:
例如:python作为一种简单过程化的高级语言,具备很好的性能,用python做一个小游戏既能提升自己对python的掌握能力,又能为大家的学习带来更多乐趣。
以下是本篇文章正文内容
人机对弈,简单来说就是电脑通过分析棋局,得到胜算最大的落棋点,然后与人对弈,此程序采用的是类似迪杰斯特拉算法求解最短路径来求得最优解,也类似于人工智能方向的启发式搜索策略。在面对任何一种棋盘形势时,通过寻找棋子的可落脚点的各种可能,并通过每种可能状态下的可赢的可能性来寻找棋子最好的落脚点。
原理:井字棋一共有八种赢的方式,分别是横三种竖三种和对角线两种,定义一个列表可以用来储存棋盘上的这八种路线,用line来表示,那么每发现line中的一条边不可能行得通,line中就会少一条边,通过分析棋子在不同落脚点时line中能赢的可能情况总和即可得出最优解,在对弈中除了要考虑最优解以外还需分析最优解中的最优解,以及两种情况:一步即赢时优先一步即赢,在不能一步即赢的情况下,要优先考虑拦截对手,其次再考虑其他情况中的最优解。
玩法:利用电脑键盘右方小键盘0-9输入即可,与棋盘上一一对应
此程序仅需要用到内置库:time,copy.
代码如下:
import copy
import time
class Tic_toc_tae():
def __init__(self):
self.chessboard=[[],[],[]]#存放棋盘
self.line=[[],[],[],[],[],[],[],[]]#存放各条边,包括斜着的边
self.player_plot='x'#玩家用x号
self.rebot_plot='o'#电脑用o号
self.n=0
self.STOP=False#决定整个游戏是否继续
代码如下:
def initialation(self): for i in range(len(self.chessboard)):#初始化棋盘 self.chessboard[i]=[' ',' ',' '] for j in range(3):#初始化记录各条能赢的边 self.line[j]=self.chessboard[j] self.line[j+3]=[self.chessboard[j][0],self.chessboard[j][1],self.chessboard[j][2]] self.line[6]=[self.chessboard[0][0],self.chessboard[1][1],self.chessboard[2][2]] self.line[7]=[self.chessboard[2][0],self.chessboard[1][1],self.chessboard[2][2]] return self.chessboarddef get_now_line(self,chessboard):#方便后续调用 line=[[],[],[],[],[],[],[],[]] for j in range(3): line[j]=copy.deepcopy(chessboard[j]) line[j+3]=copy.deepcopy([chessboard[0][j],chessboard[1][j],chessboard[2][j]]) line[6]=copy.deepcopy([chessboard[0][0],chessboard[1][1],chessboard[2][2]]) line[7]=copy.deepcopy([chessboard[2][0],chessboard[1][1],chessboard[0][2]]) return line
代码如下(注意到copy内置函数的使用,由于列表直接赋值会导致地址错误,所以不得不使用copy函数让一个列表可以多次使用):
def change_chessboard(self,keys1):#这里是主要的下棋部分,后面都要引用到 plot=self.player_plot chessboard=copy.deepcopy(self.chessboard)#得到目前的棋盘 STOP=0 n=0 body=True key=False while(True and STOP==0): if keys1==0: try: n=int(input("从小键盘输入对应位置\n")) except(ValueError): print("请重新输入") else: STOP=1 if keys1!=0: n=keys1 body=False if n>0 and n<=3: if chessboard[2][n-1]==plot or chessboard[2][n-1]==self.rebot_plot: print("这里不能再下") continue if body==False: chessboard[2][n-1]=self.rebot_plot else: chessboard[2][n-1]=plot key=True STOP=1 elif n>=4 and n<=6: if chessboard[1][n-4]==plot or chessboard[1][n-4]==self.rebot_plot: print("这里不能再下") continue if body==False: chessboard[1][n-4]=self.rebot_plot else: chessboard[1][n-4]=plot key=True STOP=1 elif n>=7 and n<=9: if chessboard[0][n-7]==plot or chessboard[0][n-7]==self.rebot_plot: print("这里不能再下") continue if body==False: chessboard[0][n-7]=self.rebot_plot else: chessboard[0][n-7]=plot key=True STOP=1 #if key==True: # print("操作成功") return chessboarddef show_chessboard(self):#输出功能,把棋盘可视化出来 for i in self.chessboard: for j in i: print("|"+j,end='|') print()
机器人这块主要分三部分:
1,主函数
2,搜索寻求最优可能
3,分析得出最优解
def rebot(self):#主函数 if self.STOP==None:#STOP约束,方便停止游戏 try: x,y=self.rebot_analyze() self.chessboard[x][y] = self.rebot_plot except(TypeError,UnboundLocalError):#输入非0-9时报错情况处理 print("-------")def rebot_get_line(self,Chessboard):#分析一个落棋点的可行度 self.line=copy.deepcopy(self.get_now_line(Chessboard)) line=0 for i in self.line: n=0 prevent=0 for j in i: if j==self.player_plot: #self.line.remove(i) prevent+=1 if j==self.rebot_plot: n+=1 if n==3:#在一步能赢时,优先一步取得胜利 line+=300 if prevent==2 and n==1:#在一步不能赢时,优先拦截对方 line+=200 n=0 if n==1: line+=1 if n==2: line+=50 return linedef rebot_analyze(self):#分析得出最优解,可以说是主程序 all_situation=[] Chessboard=copy.deepcopy(self.chessboard) for i in range(len(Chessboard)): for j in range(len(Chessboard[i])): if Chessboard[i][j]!=self.player_plot and Chessboard[i][j]!=self.rebot_plot: Chessboard=self.change_chessboard(3*(2-i)+j+1) n=self.rebot_get_line(Chessboard) all_situation.append([n,i,j]) if all_situation==[]: print("游戏结束,平局") self.STOP=True return self.STOP all_situation2=[] for i in all_situation: all_situation2.append(i[0]) max_n=0 for j in range(len(all_situation2)): if all_situation2[j]==max(all_situation2): max_n=j x=all_situation[max_n][1] y=all_situation[max_n][2] return x,y
代码如下(及时分析棋盘,得出胜负):
def referee(self):
if self.STOP==None:
line=copy.deepcopy(self.get_now_line(self.chessboard))
rebot=player=0
n=0
for i in line:
rebot=player=0
for k in i:
if k==self.rebot_plot:
rebot+=1
if k==self.player_plot:
player+=1
if rebot==3:
print("------机器人获胜------")
return True
if player==3:
print("------玩家获胜------")
return True
代码如下:
def run(self):#使用run函数作为主函数,调用整个程序的自定义函数 print("---|井字棋|---") print("->人机对弈-1.0版本-503<-") print("[x 为玩家,o 为电脑]") print() while(self.STOP==False): self.initialation() self.show_chessboard() while(self.STOP!=True): self.chessboard=self.change_chessboard(0) self.STOP=self.referee() print("机器思考中") time.sleep(1) self.rebot() if self.STOP!=True: self.STOP=self.referee() self.show_chessboard() print("->是否再来一局?") anything=input("->按0退出,按其他键再来一局\n") if anything=='0': self.STOP=True else: self.STOP=Falsetic_toc_tae=Tic_toc_tae() tic_toc_tae.run()

希望大家玩的开心,由于作者水平有限,文章可能会出现谬误,欢迎大佬指正。
------------------------------------------------------------
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的