编程说明: pygame编程五子棋程序。
设计流程:新建棋盘,落子画圆,校验五子相连,赢家信息显示,自动重启下一局,程序打包成exe。
关键点:
新建棋盘:考虑线的间隔,需提前计算好。
落子画圆:考虑黑白交替,已落子坐标位不可重复落子。
校验五子相连:分成横、竖、左斜、右斜四个方向的相连,其中如果第一个为白子,第二个不为同色的白子,则列表清零重新计算,当列表出现五子相连即列表长度出现5个值,则跳出循环,提示赢家信息。
赢家信息显示:先提前获取系统字体简称,设定正确的字体,否则中文显示为方框设定函数为pygame.font.SysFont("simhei",25)。
程序打包成exe:准备.ico图标,使用指令在cmd框下执行Pyinstaller -F -w -i wzq.ico wzq.py 指定icon图标进行打包,在cmd黑框查看生成文件路径,找到生成的exe文件即可,坑为Pyinstaller确认为最新版本,版本过旧会报错导致打包失败,pip升级或者卸载重装即可。
参考链接:
1.pygame基础教程
https://blog.csdn.net/qq_40801987/article/details/121506910
2.Python Pygame制作简单五子棋游戏(详细代码+解释)
https://blog.csdn.net/weixin_43918046/article/details/119521845?spm=1001.2014.3001.5506
3.python中的tkinter库弹窗messagebox详解
https://www.jb51.net/article/216076.htm
4.pygame在屏幕上显示中文的方法
https://www.jianshu.com/p/eeea79aaf4b8
5.pygame基础语法
https://www.cnblogs.com/liuzhongkun/p/16165288.html
效果展示:
程序详情:
# encoding:utf-8
#调用pygame库
import pygame
import sys
#调用常用关键字常量,例当产生 KEYDOWN 或 KEYUP 事件时,key 属性描述具体哪个按键被按下
from pygame.locals import QUIT,KEYDOWN
import numpy as np
# from tkinter import *
# from tkinter import messagebox #一方获胜后弹出面板,第二种显示样式
#判断鼠标的落点
def find_pos(x,y):
for i in range(27,670,44):
for j in range(27,670,44):
L1=i-22
L2=i+22
R1=j-22
R2=j+22
if x>=L1 and x<=L2 and y>=R1 and y<=R2:
return i,j
return x,y
#已落子不可以重复落子
def check_over_pos(x,y,over_pos):
for val in over_pos:
if val[0][0]==x and val[0][1]==y:
return False #表示已落子
return True #表示没有落子
#判断五子连心
def check_win(over_pos):
mp=np.zeros([15,15],dtype=int)
for val in over_pos:
x=int((val[0][0]-27)/44)
y=int((val[0][1]-27)/44)
if val[1]==white_color: #通过颜色判断白子
mp[x][y]=2#表示白子
else:
mp[x][y]=1#表示黑子
for i in range(15): #查看有没竖型五子相连。例横坐标为0,查看纵坐标是否有五子相连的白子或者黑子
pos1=[]
pos2=[]
for j in range(15):
if mp[i][j]==1: #把黑子保存到列表post1
pos1.append([i,j])
else:
pos1=[] #关键点,如果下次循环不为白色,则列表情空,重新计算,保证只有五子相连才保存列表,下面横竖左斜右斜计算同理。
if mp[i][j]==2: #把白子保存到列表post2
pos2.append([i,j]) #关键点,如果下次循环不为黑色,则列表情空,重新计算,保证只有五子相连才保存列表下面横竖左斜右斜计算同理。
else:
pos2=[]
if len(pos1)>=5: #五子连心
return(1,pos1)
if len(pos2)>=5:
return [2,pos2]
for j in range(15): #查看有没横型五子相连。例竖坐标为0,查看横坐标是否有五子相连的白子或者黑子
pos1=[]
pos2=[]
for i in range(15):
if mp[i][j]==1:
pos1.append([i,j])
else:
pos1=[]
if mp[i][j]==2:
pos2.append([i,j])
else:
pos2=[]
if len(pos1)>=5:
return(1,pos1)
if len(pos2)>=5:
return [2,pos2]
for i in range(15): #查看有没左斜型五子相连。
for j in range(15):
pos1=[]
pos2=[]
for k in range(15):
if i+k>=15 or j+k>=15:
break
if mp[i+k][j+k]==1:
pos1.append([i+k,j+k])
else:
pos1=[]
if mp[i+k][j+k]==2:
pos2.append([i+k,j+k])
else:
pos2=[]
if len(pos1)>=5:
return(1,pos1)
if len(pos2)>=5:
return [2,pos2]
for i in range(15): #查看有没右斜型五子相连。
for j in range(15):
pos1=[]
pos2=[]
for k in range(15):
if i+k>=15 or j-k<0:
break
if mp[i+k][j-k]==1:
pos1.append([i+k,j-k])
else:
pos1=[]
if mp[i+k][j-k]==2:
pos2.append([i+k,j-k])
else:
pos2=[]
if len(pos1)>=5:
return(1,pos1)
if len(pos2)>=5:
return [2,pos2]
return [0,[]]
#获胜信息 一方获胜后在(250,0)坐标显示获胜信息
def message_rt(message_text):
# fonts=pygame.font.get_fonts()
# print(fonts) #查看系统字体
text=pygame.font.SysFont("simhei",25) #坑,中文显示都是方框
print(message_text)
print(message_text.encode("utf-8"))
text_fmt=text.render(message_text,1,(255,0,0))
screen.blit(text_fmt,(250,0))
while True: #一局结束重新开始下一局
#初始化pygame
pygame.init()
#窗口创建
#获取对显示系统的访问,并创建一个窗口screen
#窗口大小为670x670
screen=pygame.display.set_mode((670,670))
screen_color=[255,165,79] #背景颜色,[255,165,79]对应为棕色
line_color=[0,0,0] #线条颜色,[0,0,0]对应黑色
flag=False
tm=0
over_pos=[]
white_color=[255,255,255]
black_color=[0,0,0]
while True: #不断训练刷新画布
for event in pygame.event.get(): #获取事件,如果鼠标点击右上角关闭按钮,关闭
if event.type in (QUIT,KEYDOWN):
pygame.quit()
sys.exit()
screen.fill(screen_color) #清屏,重新开始
#画棋盘
for i in range(27,670,44):
#先画竖线
if i==27 or i==670-27: #边缘线稍微粗一些
pygame.draw.line(screen,line_color,[i,27],[i,670-27],4)
else:
pygame.draw.line(screen,line_color,[i,27],[i,670-27],2)
#先画横线
if i==27 or i==670-27: #边缘线稍微粗一些
pygame.draw.line(screen,line_color,[27,i],[670-27,i],4)
else:
pygame.draw.line(screen,line_color,[27,i],[670-27,i],2)
#在棋盘中心画个小圆表示正中心位置
pygame.draw.circle(screen,line_color,[27+44*7,27+44*7],8,0)
for val in over_pos: #显示所有落下的棋子
pygame.draw.circle(screen,val[1],val[0],20,0)
#判断是否存在五子连心
res=check_win(over_pos)
if res[0]!=0:
for pos in res[1]:
pygame.draw.rect(screen,[238,48,167],[pos[0]*44+27-22,pos[1]*44+27-22,44,44],2,5)
pygame.display.update() #刷新显示,需要刷新后在界面显示变化
if res[0]==2:
# Tk().wm_withdraw()
# messagebox.showinfo("白棋获胜","恭喜白棋一方获胜")
message_rt(u"恭喜白棋一方获胜") #赢家信息显示
pygame.display.update()
pygame.time.wait(1000)
break #游戏结束,停止下面的操作
elif res[0]==1:
# Tk().wm_withdraw()
# messagebox.showinfo("黑棋获胜","恭喜黑棋一方获胜")
message_rt(u"恭喜黑棋一方获胜") #赢家信息显示
pygame.display.update()
pygame.time.wait(1000)
break #游戏结束,停止下面的操作
#获取鼠标的坐标,调用函数find_pos,判断是否可以落子
x,y=pygame.mouse.get_pos()
x,y=find_pos(x,y)
pygame.draw.rect(screen,[0,229,238],[x-22,y-22,44,44],2,1)
#鼠标左键表示落子,tm用来延时的,因为每次循环时间间隔很断,容易导致明明只按了一次左键,却被多次获取,认为我按了多次
keys_pressed=pygame.mouse.get_pressed() #获取鼠标按键信息
if keys_pressed[0] and tm ==0:
flag=True
if check_over_pos(x,y,over_pos):
if len(over_pos)%2==0:
over_pos.append([[x,y],black_color])
else:
over_pos.append([[x,y],white_color])
#鼠标左键的延时作用
if flag:
tm +=1
if tm%20==0: #延迟时间设定20ms
flag=False
tm=0
for val in over_pos:
pygame.draw.circle(screen,val[1],val[0],20,0)
pygame.display.update()
程序打包为exe:
准备.ico图标和上面py文件,cmd输入指令,然后执行完成后找到对应exe保存路径即可。
1人点赞
技术