基于Python如何实现围棋游戏
本篇内容主要讲解“基于Python如何实现围棋游戏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“基于Python如何实现围棋游戏”吧!
1.导入模块
tkinter:ttk覆盖tkinter部分对象,ttk对tkinter进行了优化
copy:深拷贝时需要用到copy模块
tkinter.messagebox:围棋应用对象定义
如没有以上模块,在pycharm终端输入以下指令:
pip install 相应模块 -i pypi.douban/simple
fromtkinterimport*fromtkinter.ttkimport*importcopyimporttkinter.messagebox
2.初始化棋盘
对棋盘进行初始化和棋盘右侧的按钮设置,以及对棋子的控制。
classApplication(Tk):#初始化棋盘,默认九路棋盘def__init__(self,my_mode_num=9):Tk.__init__(self)#模式,九路棋:9,十三路棋:13,十九路棋:19self.mode_num=my_mode_num#窗口尺寸设置,默认:1.8self.size=1.8#棋盘每格的边长self.dd=360*self.size/(self.mode_num-1)#相对九路棋盘的矫正比例self.p=1ifself.mode_num==9else(2/3ifself.mode_num==13else4/9)#定义棋盘阵列,超过边界:-1,无子:0,黑棋:1,白棋:2self.positions=[[0foriinrange(self.mode_num+2)]foriinrange(self.mode_num+2)]#初始化棋盘,所有超过边界的值置-1forminrange(self.mode_num+2):forninrange(self.mode_num+2):if(m*n==0orm==self.mode_num+1orn==self.mode_num+1):self.positions[m][n]=-1#拷贝三份棋盘“快照”,悔棋和判断“打劫”时需要作参考self.last_3_positions=copy.deepcopy(self.positions)self.last_2_positions=copy.deepcopy(self.positions)self.last_1_positions=copy.deepcopy(self.positions)#记录鼠标经过的地方,用于显示shadow时self.cross_last=None#当前轮到的玩家,黑:0,白:1,执黑先行self.present=0#初始停止运行,点击“开始游戏”运行游戏self.stop=True#悔棋次数,次数大于0才可悔棋,初始置0(初始不能悔棋),悔棋后置0,下棋或弃手时恢复为1,以禁止连续悔棋self.regretchance=0#图片资源,存放在当前目录下的/Pictures/中self.photoW=PhotoImage(file="./Pictures/W.png")self.photoB=PhotoImage(file="./Pictures/B.png")self.photoBD=PhotoImage(file="./Pictures/"+"BD"+"-"+str(self.mode_num)+".png")self.photoWD=PhotoImage(file="./Pictures/"+"WD"+"-"+str(self.mode_num)+".png")self.photoBU=PhotoImage(file="./Pictures/"+"BU"+"-"+str(self.mode_num)+".png")self.photoWU=PhotoImage(file="./Pictures/"+"WU"+"-"+str(self.mode_num)+".png")#用于黑白棋子图片切换的列表self.photoWBU_list=[self.photoBU,self.photoWU]self.photoWBD_list=[self.photoBD,self.photoWD]#窗口大小self.geometry(str(int(600*self.size))+'x'+str(int(400*self.size)))#画布控件,作为容器self.canvas_bottom=Canvas(self,bg='#369',bd=0,width=600*self.size,height=400*self.size)self.canvas_bottom.place(x=0,y=0)#几个功能按钮self.startButton=Button(self,text='开始游戏'mand=self.start)self.startButton.place(x=480*self.size,y=200*self.size)self.passmeButton=Button(self,text='弃一手'mand=self.passme)self.passmeButton.place(x=480*self.size,y=225*self.size)self.regretButton=Button(self,text='悔棋'mand=self.regret)self.regretButton.place(x=480*self.size,y=250*self.size)#初始悔棋按钮禁用self.regretButton['state']=DISABLEDself.replayButton=Button(self,text='重新开始'mand=self.reload)self.replayButton.place(x=480*self.size,y=275*self.size)self.newGameButton1=Button(self,text=('十三'ifself.mode_num==9else'九')+'路棋'mand=self.newGame1)self.newGameButton1.place(x=480*self.size,y=300*self.size)self.newGameButton2=Button(self,text=('十三'ifself.mode_num==19else'十九')+'路棋'mand=self.newGame2)self.newGameButton2.place(x=480*self.size,y=325*self.size)self.quitButton=Button(self,text='退出游戏'mand=self.quit)self.quitButton.place(x=480*self.size,y=350*self.size)#画棋盘,填充颜色self.canvas_bottom.create_rectangle(0*self.size,0*self.size,400*self.size,400*self.size,fill='#c51')#刻画棋盘线及九个点#先画外框粗线self.canvas_bottom.create_rectangle(20*self.size,20*self.size,380*self.size,380*self.size,width=3)#棋盘上的九个定位点,以中点为模型,移动位置,以作出其余八个点formin[-1,0,1]:fornin[-1,0,1]:self.oringinal=self.canvas_bottom.create_oval(200*self.size-self.size*2,200*self.size-self.size*2,200*self.size+self.size*2,200*self.size+self.size*2,fill='#000')self.canvas_bottom.move(self.oringinal,m*self.dd*(2ifself.mode_num==9else(3ifself.mode_num==13else6)),n*self.dd*(2ifself.mode_num==9else(3ifself.mode_num==13else6)))#画中间的线条foriinrange(1,self.mode_num-1):self.canvas_bottom.create_line(20*self.size,20*self.size+i*self.dd,380*self.size,20*self.size+i*self.dd,width=2)self.canvas_bottom.create_line(20*self.size+i*self.dd,20*self.size,20*self.size+i*self.dd,380*self.size,width=2)#放置右侧初始图片self.pW=self.canvas_bottom.create_image(500*self.size+11,65*self.size,image=self.photoW)self.pB=self.canvas_bottom.create_image(500*self.size-11,65*self.size,image=self.photoB)#每张图片都添加image标签,方便reload函数删除图片self.canvas_bottom.addtag_withtag('image',self.pW)self.canvas_bottom.addtag_withtag('image',self.pB)#鼠标移动时,调用shadow函数,显示随鼠标移动的棋子self.canvas_bottom.bind('<Motion>',self.shadow)#鼠标左键单击时,调用getdown函数,放下棋子self.canvas_bottom.bind('<Button-1>',self.getDown)#设置退出快捷键<Ctrl>+<D>,快速退出游戏self.bind('<Control-KeyPress-d>',self.keyboardQuit)
3. 开始游戏
defstart(self):#删除右侧太极图self.canvas_bottom.delete(self.pW)self.canvas_bottom.delete(self.pB)#利用右侧图案提示开始时谁先落子ifself.present==0:self.create_pB()self.del_pW()else:self.create_pW()self.del_pB()#开始标志,解除stopself.stop=None
4.放弃当前回合落子
点击弃一手,可跳过当前回合落子。
defpassme(self):#悔棋恢复ifnotself.regretchance==1:self.regretchance+=1else:self.regretButton['state']=NORMAL#拷贝棋盘状态,记录前三次棋局self.last_3_positions=copy.deepcopy(self.last_2_positions)self.last_2_positions=copy.deepcopy(self.last_1_positions)self.last_1_positions=copy.deepcopy(self.positions)self.canvas_bottom.delete('image_added_sign')#轮到下一玩家ifself.present==0:self.create_pW()self.del_pB()self.present=1else:self.create_pB()self.del_pW()self.present=0
5.悔棋判断
若当前回合悔棋,则下两个回合都不能悔棋。
defregret(self):#判定是否可以悔棋ifself.regretchance==1:self.regretchance=0self.regretButton['state']=DISABLEDlist_of_b=[]list_of_w=[]self.canvas_bottom.delete('image')ifself.present==0:self.create_pB()else:self.create_pW()forminrange(1,self.mode_num+1):forninrange(1,self.mode_num+1):self.positions[m][n]=0forminrange(len(self.last_3_positions)):forninrange(len(self.last_3_positions[m])):ifself.last_3_positions[m][n]==1:list_of_b+=[[n,m]]elifself.last_3_positions[m][n]==2:list_of_w+=[[n,m]]self.recover(list_of_b,0)self.recover(list_of_w,1)self.last_1_positions=copy.deepcopy(self.last_3_positions)forminrange(1,self.mode_num+1):forninrange(1,self.mode_num+1):self.last_2_positions[m][n]=0self.last_3_positions[m][n]=0
6.重新开始
点击重新开始,恢复棋盘。
defreload(self):ifself.stop==1:self.stop=0self.canvas_bottom.delete('image')self.regretchance=0self.present=0self.create_pB()forminrange(1,self.mode_num+1):forninrange(1,self.mode_num+1):self.positions[m][n]=0self.last_3_positions[m][n]=0self.last_2_positions[m][n]=0self.last_1_positions[m][n]=0
7.右侧太极图的设置
defcreate_pW(self):self.pW=self.canvas_bottom.create_image(500*self.size+11,65*self.size,image=self.photoW)self.canvas_bottom.addtag_withtag('image',self.pW)defcreate_pB(self):self.pB=self.canvas_bottom.create_image(500*self.size-11,65*self.size,image=self.photoB)self.canvas_bottom.addtag_withtag('image',self.pB)defdel_pW(self):self.canvas_bottom.delete(self.pW)defdel_pB(self):self.canvas_bottom.delete(self.pB)
8.落子设置
defshadow(self,event):ifnotself.stop:#找到最近格点,在当前位置靠近的格点出显示棋子图片,并删除上一位置的棋子图片if(20*self.size<event.x<380*self.size)and(20*self.size<event.y<380*self.size):dx=(event.x-20*self.size)%self.dddy=(event.y-20*self.size)%self.ddself.cross=self.canvas_bottom.create_image(event.x-dx+round(dx/self.dd)*self.dd+22*self.p,event.y-dy+round(dy/self.dd)*self.dd-27*self.p,image=self.photoWBU_list[self.present])self.canvas_bottom.addtag_withtag('image',self.cross)ifself.cross_last!=None:self.canvas_bottom.delete(self.cross_last)self.cross_last=self.cross#落子,并驱动玩家的轮流下棋行为defgetDown(self,event):ifnotself.stop:#先找到最近格点if(20*self.size-self.dd*0.4<event.x<self.dd*0.4+380*self.size)and(20*self.size-self.dd*0.4<event.y<self.dd*0.4+380*self.size):dx=(event.x-20*self.size)%self.dddy=(event.y-20*self.size)%self.ddx=int((event.x-20*self.size-dx)/self.dd+round(dx/self.dd)+1)y=int((event.y-20*self.size-dy)/self.dd+round(dy/self.dd)+1)#判断位置是否已经被占据ifself.positions[y][x]==0:#未被占据,则尝试占据,获得占据后能杀死的棋子列表self.positions[y][x]=self.present+1self.image_added=self.canvas_bottom.create_image(event.x-dx+round(dx/self.dd)*self.dd+4*self.p,event.y-dy+round(dy/self.dd)*self.dd-5*self.p,image=self.photoWBD_list[self.present])self.canvas_bottom.addtag_withtag('image',self.image_added)#棋子与位置标签绑定,方便“杀死”self.canvas_bottom.addtag_withtag('position'+str(x)+str(y),self.image_added)deadlist=self.get_deadlist(x,y)self.kill(deadlist)#判断是否重复棋局ifnotself.last_2_positions==self.positions:#判断是否属于有气和杀死对方其中之一iflen(deadlist)>0orself.if_dead([[x,y]],self.present+1,[x,y])==False:#当不重复棋局,且属于有气和杀死对方其中之一时,落下棋子有效ifnotself.regretchance==1:self.regretchance+=1else:self.regretButton['state']=NORMALself.last_3_positions=copy.deepcopy(self.last_2_positions)self.last_2_positions=copy.deepcopy(self.last_1_positions)self.last_1_positions=copy.deepcopy(self.positions)#删除上次的标记,重新创建标记self.canvas_bottom.delete('image_added_sign')self.image_added_sign=self.canvas_bottom.create_oval(event.x-dx+round(dx/self.dd)*self.dd+0.5*self.dd,event.y-dy+round(dy/self.dd)*self.dd+0.5*self.dd,event.x-dx+round(dx/self.dd)*self.dd-0.5*self.dd,event.y-dy+round(dy/self.dd)*self.dd-0.5*self.dd,width=3,outline='#3ae')self.canvas_bottom.addtag_withtag('image',self.image_added_sign)self.canvas_bottom.addtag_withtag('image_added_sign',self.image_added_sign)ifself.present==0:self.create_pW()self.del_pB()self.present=1else:self.create_pB()self.del_pW()self.present=0else:#不属于杀死对方或有气,则判断为无气,警告并弹出警告框self.positions[y][x]=0self.canvas_bottom.delete('position'+str(x)+str(y))self.bell()self.showwarningbox('无气',"你被包围了!")else:#重复棋局,警告打劫self.positions[y][x]=0self.canvas_bottom.delete('position'+str(x)+str(y))self.recover(deadlist,(1ifself.present==0else0))self.bell()self.showwarningbox("打劫","此路不通!")else:#覆盖,声音警告self.bell()else:#超出边界,声音警告self.bell()
9.吃子规则判定设置
defif_dead(self,deadList,yourChessman,yourPosition):foriin[-1,1]:if[yourPosition[0]+i,yourPosition[1]]notindeadList:ifself.positions[yourPosition[1]][yourPosition[0]+i]==0:returnFalseif[yourPosition[0],yourPosition[1]+i]notindeadList:ifself.positions[yourPosition[1]+i][yourPosition[0]]==0:returnFalseif([yourPosition[0]+1,yourPosition[1]]notindeadList)and(self.positions[yourPosition[1]][yourPosition[0]+1]==yourChessman):midvar=self.if_dead(deadList+[[yourPosition[0]+1,yourPosition[1]]],yourChessman,[yourPosition[0]+1,yourPosition[1]])ifnotmidvar:returnFalseelse:deadList+=copy.deepcopy(midvar)if([yourPosition[0]-1,yourPosition[1]]notindeadList)and(self.positions[yourPosition[1]][yourPosition[0]-1]==yourChessman):midvar=self.if_dead(deadList+[[yourPosition[0]-1,yourPosition[1]]],yourChessman,[yourPosition[0]-1,yourPosition[1]])ifnotmidvar:returnFalseelse:deadList+=copy.deepcopy(midvar)if([yourPosition[0],yourPosition[1]+1]notindeadList)and(self.positions[yourPosition[1]+1][yourPosition[0]]==yourChessman):midvar=self.if_dead(deadList+[[yourPosition[0],yourPosition[1]+1]],yourChessman,[yourPosition[0],yourPosition[1]+1])ifnotmidvar:returnFalseelse:deadList+=copy.deepcopy(midvar)if([yourPosition[0],yourPosition[1]-1]notindeadList)and(self.positions[yourPosition[1]-1][yourPosition[0]]==yourChessman):midvar=self.if_dead(deadList+[[yourPosition[0],yourPosition[1]-1]],yourChessman,[yourPosition[0],yourPosition[1]-1])ifnotmidvar:returnFalseelse:deadList+=copy.deepcopy(midvar)returndeadList#警告消息框,接受标题和警告信息defshowwarningbox(self,title,message):self.canvas_bottom.delete(self.cross)tkinter.messagebox.showwarning(title,message)#落子后,依次判断四周是否有棋子被杀死,并返回死棋位置列表defget_deadlist(self,x,y):deadlist=[]foriin[-1,1]:ifself.positions[y][x+i]==(2ifself.present==0else1)and([x+i,y]notindeadlist):killList=self.if_dead([[x+i,y]],(2ifself.present==0else1),[x+i,y])ifnotkillList==False:deadlist+=copy.deepcopy(killList)ifself.positions[y+i][x]==(2ifself.present==0else1)and([x,y+i]notindeadlist):killList=self.if_dead([[x,y+i]],(2ifself.present==0else1),[x,y+i])ifnotkillList==False:deadlist+=copy.deepcopy(killList)returndeadlist#恢复位置列表list_to_recover为b_or_w指定的棋子defrecover(self,list_to_recover,b_or_w):iflen(list_to_recover)>0:foriinrange(len(list_to_recover)):self.positions[list_to_recover[i][1]][list_to_recover[i][0]]=b_or_w+1self.image_added=self.canvas_bottom.create_image(20*self.size+(list_to_recover[i][0]-1)*self.dd+4*self.p,20*self.size+(list_to_recover[i][1]-1)*self.dd-5*self.p,image=self.photoWBD_list[b_or_w])self.canvas_bottom.addtag_withtag('image',self.image_added)self.canvas_bottom.addtag_withtag('position'+str(list_to_recover[i][0])+str(list_to_recover[i][1]),self.image_added)#杀死位置列表killList中的棋子,即删除图片,位置值置0defkill(self,killList):iflen(killList)>0:foriinrange(len(killList)):self.positions[killList[i][1]][killList[i][0]]=0self.canvas_bottom.delete('position'+str(killList[i][0])+str(killList[i][1]))
10.其他
退出游戏和全局变量的说明。
defkeyboardQuit(self,event):self.quit()#以下两个函数修改全局变量值,newApp使主函数循环,以建立不同参数的对象defnewGame1(self):globalmode_num,newAppmode_num=(13ifself.mode_num==9else9)newApp=Trueself.quit()defnewGame2(self):globalmode_num,newAppmode_num=(13ifself.mode_num==19else19)newApp=Trueself.quit()#声明全局变量,用于新建Application对象时切换成不同模式的游戏globalmode_num,newAppmode_num=9newApp=False
11.程序入口
if__name__=='__main__':#循环,直到不切换游戏模式whileTrue:newApp=Falseapp=Application(mode_num)app.title('围棋')app.mainloop()ifnewApp:app.destroy()else:break
12.效果图
到此,相信大家对“基于Python如何实现围棋游戏”有了更深的了解,不妨来实际操作一番吧!这里是主机评测网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
输入法切换键是哪个键?输入法切
冬月是哪一个月?冬月是什么意思
个人所得税退税金额怎么算出来的
输入法全角和半角有什么区别?输
a4纸尺寸是多少厘米?a4纸的由来
个人所得税扣除标准?个人所得税
输入法哪个好用?输入法介绍
卡拉OK是哪个国家发明的?卡拉OK
mikutools原神网页版入口链接?m
关机特别慢什么原因?电脑和手机