Python 实现 五子棋小游戏【附源码】

引言

五子棋是一种古老而深受欢迎的策略游戏,它具有简单的规则和无穷的变化。作为一种传统的中国棋类游戏,五子棋已经在世界范围内流行起来,并成为智力挑战和休闲娱乐的优秀选择。

在这里插入图片描述

规则和玩法:

五子棋使用一个15x15的棋盘,玩家轮流在空白位置上放置黑色或白色的棋子。目标是在水平、垂直或对角线上先形成连续的五个棋子,即五子连珠。玩家可以利用自己的棋子来阻止对方取得胜利,并同时寻找自己的胜利机会。五子棋规则简单明了,但由于棋盘庞大的可能性,游戏变化多端,需要高度的战略和思考能力。

模块化分析

init():初始化数据,包括清空棋盘上的棋子和提示信息,重置游戏状态。

drawWin():绘制游戏窗口,包括棋盘和各种文本提示信息,使其显示在屏幕上。

inBoard(x, y):判断给定的点是否在棋盘范围内。通过检查坐标x和y是否在0到15之间来确定。

downOk(x, y):判断给定点是否可以落子,即是否在棋盘内且该位置没有被占据。如果位置合法且为空,则返回True,否则返回False。

manPlay():处理玩家下棋的逻辑。首先获取玩家鼠标点击事件的坐标,如果玩家点击了重新开始或退出按钮,则执行相应的操作。如果玩家点击的位置是合法的,则落下一颗棋子,否则重新调用该函数等待合法的点击。

go(x, y):将一颗棋子放置在给定的位置,并判断游戏是否结束。该函数会检查该位置是否合法,如果合法,则在图形界面上放置一个棋子,同时更新棋盘数组和计数器。接下来,该函数会检查是否有一方玩家获胜或棋盘已满,如果是,则设置游戏结束标志,并弹出相应的对话框。

whoStart(p):处理选择先手的逻辑。根据玩家点击的位置(先手按钮或后手按钮),确定玩家和AI的先后顺序,并更新相关的变量。

AI1():博弈树的第一层。该函数用于生成所有可能的下一步落子点,并调用AI2()函数评估每个点的得分。

AI2():博弈树的第二层。该函数遍历了AI1()生成的所有可能的下一步落子点,并调用AI3()函数评估每个点的得分。

AI3(p2):博弈树的第三层。该函数通过模拟对方的下一步落子,评估当前局面的得分。它会考虑到玩家和AI的不同策略,找出对AI最有利的下一步落子点。

完整代码:

from graphics import *
import time
###
num = [[0 for a in range(16)] for a in range(16)]
dx = [1,1,0,-1,-1,-1,0,1] #x,y方向向量
dy = [0,1,1,1,0,-1,-1,-1]
is_end = False
go_first = 1 #先手标志
start = 1 #轮换下棋标志
ai = 1 #AI下棋标志
L1_max=-100000 #剪枝阈值
L2_min=100000
list=[] #保存已画棋子
RESTART_FLAG = False
QUIT_FLAG = False
###
win = GraphWin("五子棋",550,451)
aiFirst = Text(Point(500,100),"")
manFirst = Text(Point(500,140),"")
notice = Text(Point(500,290),"") #提示轮到谁落子
notice.setFill('red')
last_ai = Text(Point(500,330),"") #AI最后落子点
last_man = Text(Point(500,370),"") #玩家最后落子点
QUIT = Text(Point(500,20),"退出")
QUIT.setFill('red')
RESTART = Text(Point(500,60),"重玩")
RESTART.setFill('red')
#数据初始化,把棋盘上的棋子和提示清空
def init():global is_end,start,go_first,RESTART_FLAGis_end=Falsestart=1go_first=1RESTART_FLAG=FalseQUIT_FLAG=Falsefor i in range(16):for j in range(16):if(num[i][j]!=0):num[i][j]=0for i in range(len(list)):list[-1].undraw()list.pop(-1)aiFirst.setText("AI 先手")manFirst.setText("我先手")notice.setText("")last_ai.setText("")last_man.setText("")
#画棋盘
def drawWin():win.setBackground('yellow')for i in range(0,451,30):line=Line(Point(i,0),Point(i,450))line.draw(win)for j in range(0,451,30):line=Line(Point(0,j),Point(450,j))line.draw(win)Rectangle(Point(460,5),Point(540,35)).draw(win)Rectangle(Point(460,45),Point(540,75)).draw(win)Rectangle(Point(460,85),Point(540,115)).draw(win)Rectangle(Point(460,125),Point(540,155)).draw(win)Rectangle(Point(452,275),Point(548,305)).draw(win)Rectangle(Point(452,307),Point(548,395)).draw(win)aiFirst.draw(win)manFirst.draw(win)notice.draw(win)last_ai.draw(win)last_man.draw(win)QUIT.draw(win)RESTART.draw(win)
#判断该点是否在棋盘范围内
def inBoard(x,y):if(x>=0 and x<=15 and y>=0 and y<=15): return Trueelse: return False
#判断该点是否可落子,即是否在棋盘内且没有落子
def downOk(x,y):if(inBoard(x,y) and num[x][y]==0): return Trueelse: return False
#该点值是否和i值相等,即该点棋子颜色和i相同
def sameColor(x,y,i):if(inBoard(x,y) and num[x][y]==i): return Trueelse: return False
#在给定的方向v(v区分正负)上,和该点同色棋子的个数
def numInline(x,y,v):i=x+dx[v]; j=y+dy[v]s=0; ref=num[x][y]if(ref==0): return 0while(sameColor(i,j,ref)):s=s+1; i=i+dx[v]; j=j+dy[v]return s
#该点四个方向里(即v不区分正负),活四局势的个数
def liveFour(x,y):key=num[x][y]; s=0for u in range(4):samekey=1samekey,i=numofSamekey(x,y,u,1,key,samekey)if(not downOk(x+dx[u]*i,y+dy[u]*i)):continuesamekey,i=numofSamekey(x,y,u,-1,key,samekey)if(not downOk(x+dx[u]*i,y+dy[u]*i)):continueif(samekey==4):s=s+1return s
#该点八个方向里(即v区分正负),冲四局势的个数
def chongFour(x,y):key=num[x][y]; s=0for u in range(8):samekey=0; flag=True; i=1while(sameColor(x+dx[u]*i,y+dy[u]*i,key) or flag):if(not sameColor(x+dx[u]*i,y+dy[u]*i,key)):if(flag and inBoard(x+dx[u]*i,y+dy[u]*i) and num[x+dx[u]*i][y+dy[u]*i]!=0):samekey-=10flag=Falsesamekey+=1i+=1i-=1if(not inBoard(x+dx[u]*i,y+dy[u]*i)):continuesamekey,i=numofSamekey(x,y,u,-1,key,samekey)if(samekey==4):s+=1return s-liveFour(x,y)*2
#该点四个方向里活三,以及八个方向里断三的个数
def liveThree(x,y):key=num[x][y]; s=0for u in range(4):samekey=1samekey,i=numofSamekey(x,y,u,1,key,samekey)if(not downOk(x+dx[u]*i,y+dy[u]*i)):continueif(not downOk(x+dx[u]*(i+1),y+dy[u]*(i+1))):continuesamekey,i=numofSamekey(x,y,u,-1,key,samekey)if(not downOk(x+dx[u]*i,y+dy[u]*i)):continueif(not downOk(x+dx[u]*(i-1),y+dy[u]*(i-1))):continueif(samekey==3):s+=1for u in range(8):samekey=0; flag=True; i=1while(sameColor(x+dx[u]*i,y+dy[u]*i,key) or flag):if(not sameColor(x+dx[u]*i,y+dy[u]*i,key)):if(flag and inBoard(x+dx[u]*i,y+dy[u]*i) and num[x+dx[u]*i][y+dy[u]*i]!=0):samekey-=10flag=Falsesamekey+=1i+=1if(not downOk(x+dx[u]*i,y+dy[u]*i)):continueif(inBoard(x+dx[u]*(i-1),y+dy[u]*(i-1)) and num[x+dx[u]*(i-1)][y+dy[u]*(i-1)]==0):continuesamekey,i=numofSamekey(x,y,u,1,key,samekey)if(not downOk(x+dx[u]*i,y+dy[u]*i)):continueif(samekey==3):s+=1return s
#该点在四个方向里,是否有六子或以上连线
def overLine(x,y):flag=Falsefor u in range(4):if((numInline(x,y,u)+numInline(x,y,u+4))>4):flag=Truereturn flag
#该黑子点是否是禁手点,黑子禁手直接判输
def ban(x,y):if(sameColor(x,y,3-go_first)):return Falseflag=((liveThree(x,y)>1) or (overLine(x,y)) or ((liveFour(x,y)+chongFour(x,y))>1))return flag
#统计在u方向上,和key值相同的点的个数,即和key同色的连子个数
def numofSamekey(x,y,u,i,key,sk):if(i==1):while(sameColor(x+dx[u]*i,y+dy[u]*i,key)):sk+=1i+=1elif(i==-1):while(sameColor(x+dx[u]*i,y+dy[u]*i,key)):sk+=1i-=1return sk,i
#游戏是否结束,如果有五子连线或出现禁手
def gameOver(x,y):global is_endfor u in range(4):if((numInline(x,y,u)+numInline(x,y,u+4))>=4):is_end=Truereturn Truereturn False
#对该点落子后的局势进行估分
def getScore(x,y):global is_endif(ban(x,y)):return 0if(gameOver(x,y)):is_end=Falsereturn 10000score=liveFour(x,y)*1000+(chongFour(x,y)+liveThree(x,y))*100for u in range(8):if(inBoard(x+dx[u],y+dy[u]) and num[x+dx[u]][y+dy[u]]!=0):score=score+1return score
#博弈树第一层
def AI1():global L1_maxL1_max=-100000if(num[8][8]==0 and go_first==ai):return go(8,8)keyi=-1; keyj=-1for x in [8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0]:for y in [8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0]:if(not downOk(x,y)):continuenum[x][y]=aitempp=getScore(x,y)if(tempp==0):num[x][y]=0; continueif(tempp==10000):return go(x,y)tempp=AI2()num[x][y]=0if(tempp>L1_max): #取极大L1_max=tempp; keyi=x; keyj=ygo(keyi,keyj)
#博弈树第二层
def AI2():global L2_minL2_min=100000for x in [8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0]:for y in [8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0]:if(not downOk(x,y)):continuenum[x][y]=3-aitempp=getScore(x,y)if(tempp==0):num[x][y]=0; continueif(tempp==10000):num[x][y]=0; return -10000tempp=AI3(tempp)if(tempp<L1_max): #L1层剪枝num[x][y]=0; return -10000num[x][y]=0if(tempp<L2_min): #取极小L2_min=temppreturn L2_min
#博弈树第三层
def AI3(p2):keyp=-100000for x in [8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0]:for y in [8,7,9,6,10,5,11,4,12,3,13,2,14,1,15,0]:if(not downOk(x,y)):continuenum[x][y]=aitempp=getScore(x,y)if(tempp==0):num[x][y]=0; continueif(tempp==10000):num[x][y]=0; return 10000if(tempp-p2*2>L2_min): #L2层剪枝num[x][y]=0; return 10000num[x][y]=0if(tempp-p2*2>keyp): #取极大keyp=tempp-p2*2return keyp
#选手下棋
def manPlay():p=win.getMouse()if(Restart(p) or Quit(p)): returnx=round(p.getX()/30)y=round(p.getY()/30)if(downOk(x,y)): go(x,y)else: manPlay()
#落下一子并且判断游戏是否结束
def go(x,y):global is_endc=Circle(Point(x*30,y*30),13)if(start==ai):num[x][y]=ailast_ai.setText("AI 落子:\n(x:y)=("+str(x)+":"+str(y)+")")if(go_first==ai): c.setFill('black')else: c.setFill('white')else:num[x][y]=3-ailast_man.setText("玩家落子:\n(x:y)=("+str(x)+":"+str(y)+")")if(go_first==ai): c.setFill('white')else: c.setFill('black')c.draw(win)list.append(c)if(ban(x,y)):if(start==ai):notice.setText("AI 禁手,玩家赢!\n点击重玩")else:notice.setText("玩家禁手,AI 赢!\n点击重玩")is_end=Trueelif(gameOver(x,y)):if(start==ai):notice.setText("AI 赢!\n点击重玩")else:notice.setText("玩家赢!\n点击重玩")
##是否重新开始游戏
def Restart(p):global RESTART_FLAGx=p.getX(); y=p.getY()if((abs(500-x)<40) and (abs(60-y)<15)): #restartinit()RESTART_FLAG=Truenotice.setText("重新开始")time.sleep(1)return Trueelse:return False
##是否退出游戏
def Quit(p):global QUIT_FLAG, is_endx=p.getX(); y=p.getY()if((abs(500-x)<40) and (abs(20-y)<15)): #quitinit()QUIT_FLAG=Trueis_end=Truenotice.setText("退出")time.sleep(1)return Trueelse:return False
##选择先后手
def whoStart(p):global start, go_firstx=p.getX(); y=p.getY()if((abs(500-x)<40) and (abs(100-y)<15)): #AI 先手start=1go_first=1aiFirst.setText("AI 执黑")manFirst.setText("玩家执白")return Trueelif((abs(500-x)<40) and (abs(140-y)<15)): #玩家先手start=2go_first=2aiFirst.setText("AI 执白")manFirst.setText("玩家执黑")return Trueelse:return False
##------------------------------------------------------------------##
#主程序入口
if __name__=='__main__':init()drawWin()notice.setText("请选择先手")p=win.getMouse()while(not whoStart(p) and not Quit(p)):p=win.getMouse()while(not is_end):RESTART_FLAG=Falseif(start==ai):notice.setText("AI 正在下棋...")AI1()else:notice.setText("请你下棋...")manPlay()start=3-startif(RESTART_FLAG):notice.setText("请选择先手")p=win.getMouse()while(not whoStart(p) and not Quit(p)):p=win.getMouse()elif(not QUIT_FLAG and is_end):p=win.getMouse()while(not Restart(p) and not Quit(p)):p=win.getMouse()if(RESTART_FLAG):notice.setText("请选择先手")p=win.getMouse()while(not whoStart(p) and not Quit(p)):p=win.getMouse()

总结:

五子棋作为一种古老而精彩的策略游戏,在不同的文化和地区都有着广泛的影响力。它不仅是一种休闲娱乐方式,还是一种锻炼智力和战略思维的有效方法。通过挑战五子棋,我们可以探索无限的可能性,并提高我们的思考能力和决策技巧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/251811.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MIMIC数据库, 使用Python研究万古霉素的剂量 (一)

一、万古霉素 是一种杀菌型 抗生素&#xff0c;抑制细菌细胞壁的合成 万古霉素对以下细菌有效&#xff1a; 大多数革兰阳性球菌和杆菌有抗菌活性&#xff0c;包括几乎所有耐青霉素和头孢菌素的 Staphylococcus aureus 和凝固酶阴性葡萄球菌株 许多菌株 肠球菌 &#xff08;…

【Java报错】显示错误“Error:java: 程序包org.springframework.boot不存在“

使用idea运行项目&#xff0c;显示错误信息如下&#xff1a; 原因是&#xff1a;idea配置的maven加载不到autoconfigure。 解决方案一&#xff1a; 第6步绕过证书语句如下&#xff1a; -Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.allowalltrue 打开终端&am…

2V2无人机红蓝对抗仿真

两架红方和蓝方无人机分别从不同位置起飞&#xff0c;蓝方无人机跟踪及击毁红方无人机 2020a可正常运行 2V2无人机红蓝对抗仿真资源-CSDN文库

【并发编程】原子累加器

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程 ⛺️稳重求进&#xff0c;晒太阳 JDK8之后有专门做累加的类&#xff0c;效率比自己做快数倍以上 累加器性能比较 参数是方法 // supplier 提供者 无中生有 ()->结果// func…

ElasticSearch搜索与分析引擎-Linux离线环境安装教程

目录 一、下载安装包 网盘链接: 二、安装流程及遇到的问题和解决方案 &#xff08;1&#xff09;JDK安装 &#xff08;2&#xff09;Elasticsearch安装 &#xff08;3&#xff09;Kibana安装 ​&#xff08;4&#xff09;Ik分词器安装 三、启动过程中的问题 &#xff…

zabbix监控mariadb数据库

zabbix监控mariadb数据库 1.创建监控用户及授权 [rootchang ~]# mysql -uroot -p123qqq.A MariaDB [(none)]> CREATE USER monitor% IDENTIFIED BY 123qqq.A; MariaDB [(none)]> GRANT REPLICATION CLIENT,PROCESS,SHOW DATABASES,SHOW VIEW ON *.* TO monitor%; Maria…

【复现】WordPress html5-video-player SQL 注入漏洞_39

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 在WordPress中播放各种视频文件。一个简单&#xff0c;可访问&#xff0c;易于使用和完全可定制的视频播放器&#xff0c;适用于所…

Android SELinux:保护您的移动设备安全的关键

Android SELinux&#xff1a;保护您的移动设备安全的关键 1 引言 移动设备在我们的生活中扮演着越来越重要的角色&#xff0c;我们几乎把所有重要的信息都存储在这些设备上。然而&#xff0c;随着移动应用程序的数量不断增加&#xff0c;安全性也变得越来越关键。这就是为什么…

Android14之Selinux报错:unknown type qemu_device at token (一百八十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

PyTorch使用

前言 系统环境&#xff1a;win10 使用Anaconda&#xff0c;Anaconda的安装自行百度。 conda 23.7.4 目录 前言 创建虚拟环境 1、查看当前有哪些虚拟环境 2、创建虚拟环境pytorch 3、激活及关闭pytorch虚拟环境 4、删除pytorch虚拟环境 使用yolov5测试 1、切换至yolo…

ubuntu离线安装k8s

目录 一、前期准备 二、安装前配置 三、安装docker 四、安装cri-dockerd 五、部署k8s master节点 六、整合kubectl与cri-dockerd 七、网络等插件安装 八、常见问题及解决方法 一、前期准备 ①ubuntu系统 本地已安装ubuntu系统&#xff0c;lsb_release -a命令查看版本信…

《vtk9 book》 官方web版 第3章 - 计算机图形基础 (2 / 6)

3.4 表面特性 当光线穿过空间时&#xff0c;其中一些光线会与我们的物体相交。当这种情况发生时&#xff0c;光线会与物体表面相互作用&#xff0c;产生一种颜色。部分由此产生的颜色实际上并不是由直接光线产生的&#xff0c;而是来自其他物体反射或散射的环境光。环境光照模型…

物联网与智慧景区的未来:机遇与挑战并存

随着科技的不断发展&#xff0c;物联网技术在智慧景区中的应用越来越广泛&#xff0c;为旅游业带来了巨大的变革。然而&#xff0c;在物联网与智慧景区的未来发展中&#xff0c;机遇与挑战并存。本文将探讨物联网与智慧景区面临的机遇和挑战&#xff0c;并提出应对措施&#xf…

Spring框架——主流框架

文章目录 Spring(轻量级容器框架)Spring 学习的核心内容-一图胜千言IOC 控制反转 的开发模式Spring快速入门Spring容器剖析手动开发- 简单的 Spring 基于 XML 配置的程序课堂练习 Spring 管理 Bean-IOCSpring 配置/管理 bean 介绍Bean 管理包括两方面: Bean 配置方式基于 xml 文…

网络空间内生安全数学基础(2)——编码信道数学模型

目录 &#xff08;零&#xff09;这篇博客在干什么&#xff08;一&#xff09;内生安全与香农信道编码定理&#xff08;二&#xff09;基本定义&#xff08;三&#xff09;编码信道存在定理&#xff08;三.壹&#xff09;编码信道存在第一定理&#xff08;三.贰&#xff09;编码…

[python] 过年燃放烟花

目录 新年祝福语 一、作品展示 二、作品所用资源 三、代码与资源说明 四、代码库 五、完整代码 六、总结 新年祝福语 岁月总是悄然流转&#xff0c;让人感叹时间的飞逝&#xff0c;转眼间又快到了中国传统的新年&#xff08;龙年&#xff09;。 回首过去&#xf…

LLM - Qwen-72B LoRA 训练与推理实战

目录 一.引言 二.模型简介 1.Qwen-Model 总览 2.Qwen-Chat-72B - PreTrain - Tokenizer - Base Line - SFT / RLHF 3.Qwen-72 模型架构 - Config.json - c_attn/c_proj - Attention Forward - ROPE - Qwen MLP - Qwen Block 三.QLoRA 与 Infer 实战 1.SFT 指…

JavaScript鼠标拖放(Drag and Drop)

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 拖放是现代界面不可或缺的交互方式之一。本文将介绍如何用JavaScript…

【蓝桥杯冲冲冲】 [SCOI2005] 骑士精神

蓝桥杯备赛 | 洛谷做题打卡day28 文章目录 蓝桥杯备赛 | 洛谷做题打卡day28[SCOI2005] 骑士精神题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示题解代码我的一些话[SCOI2005] 骑士精神 题目描述 输入格式 第一行有一个正整数 T T T( T ≤ 10

随机森林超参数的网格优化(机器学习的精华--调参)

随机森林超参数的网格优化&#xff08;机器学习的精华–调参&#xff09; 随机森林各个参数对算法的影响 影响力参数⭐⭐⭐⭐⭐几乎总是具有巨大影响力n_estimators&#xff08;整体学习能力&#xff09;max_depth&#xff08;粗剪枝&#xff09;max_features&#xff08;随机…