python网络编程之五子棋游戏


Posted in Python onMay 14, 2020

一.本案例基于UDP的socket编程方法来制作五子棋程序,网络五子棋采用C/S架构,分为服务器端和客户端,游戏时服务端首先启动,当客户端启动连接后,服务器端可以走棋,轮到自己棋才可以在棋盘上落子,同时下方标签会显示对方走起信息,服务器端用户可以通过“退出游戏”按钮可以结束游戏;

1.数据通信协议

网络五子棋游戏设计的难点在于对方进行通信,这里使用面向非连接的Socket编程,Socket编程用于C/S开发,在这类应用中,客户端和服务器端通常需要先建立连接,然后发送和接收数据,交互完成后需要断开连接,本章采用基于UDP的Socket编程实现,这里虽然两台计算机不分主次,但涉及时候假设一台作为服务器端,等待其他方加入,其他想加入必须输入服务器端主机的IP;

下面展示一些 数据通信协议代码

def receiveMessage():
 global s
 while True:
 global addr
 data,addr=s.recvfrom(1024)
 data=data.decode('utf-8')
 a=data.split("|")
 if not data:
 print("client has exited!")
 break
 elif a[0]=='join': #连接服务器请求
 print('client 连接服务器!')
 label1["text"]='client连接服务器成功,请你走棋!'
 elif a[0]=='exit':
 print('client 对方退出!')
 label1["text"]='client对方退出,游戏结束!'
 elif a[0]=='over':
 print('对方赢信息!')
 label1["text"]=data.split("|")[0]
 showinfo(title="提示",message=data.split("|")[1])
 elif a[0]=='move':
 print('received:',data,'from',addr)
 p=a[1].split(",")
 x=int(p[0])
 y=int(p[1])
 print(p[0],p[1])
 label1["text"]="客户端走的位置"+p[0]+p[1]
 drawOtherChess(x,y)
 s.close()

2.判断输赢的算法

本游戏关键技术就是判断输赢的算法,对于算法实现大致可以分为以下几个部分:

(1)判断X=Y轴上是否形成五子连珠;

(2)判断X=-Y轴上是否形成五子连珠;

(3)判断X轴上是否形成五子连珠;

(4)判断Y轴上是否形成五子连珠;

#输赢判断
def win_lose():
 a=str(turn)
 print("a=",a)
 for i in range(0,11):
 for j in range(0,11):
 if map[i][j]==a and map[i+1][j+1]==a and map[i+2][j+2]==a and map[i+3][j+3]==a and map[i+4][j+4]==a:
 print("x=y轴上形成五子连珠")
 return True
 for i in range(4,15):
 for j in range(0,11):
 if map[i][j]==a and map[i-1][j+1]==a and map[i-2][j+2]==a and map[i-3][j+3]==a and map[i-4][j+4]==a:
 print("x=-y轴上形成五子连珠")
 return True
 for i in range(0,15):
 for j in range(4,15):
 if map[i][j]==a and map[i][j-1]==a and map[i][j-2]==a and map[i][j-2]==a and map[i][j-4]==a:
 print("Y轴上形成了五子连珠")
 return True
 for i in range(0,11):
 for j in range(0,15):
 if map[i][j]==a and map[i+1][j]==a and map[i+2][j]==a and map[i+3][j]==a and map[i+4][j]==a:
 print("X轴形成五子连珠")
 return True
 return False

二. 源代码:

1.客户端编程代码如下:

from tkinter import *
from tkinter.messagebox import *
import socket
import threading
import os
#主程序
root=Tk()
root.title("网络五子棋v2.0--UDP客户端")
imgs=[PhotoImage(file='E:\\game\\BlackStone.gif'),PhotoImage(file='E:\\game\\WhiteStone.gif')]
turn=0
Myturn=-1
#画对方棋子
def drawOtherChess(x,y):
 global turn
 img1=imgs[turn]
 cv.create_image((x*40+20,y*40+20),image=img1)
 cv.pack()
 map[x][y]=str(turn)
 #换下一方走棋
 if turn==0:
 turn=1
 else:
 turn=0
#发送消息
def sendMessage(pos):
 global s
 s.sendto(pos.encode(),(host,port))
#退出函数
def callexit(event):
 pos="exit|"
 sendMessage(pos)
 os._exit(0)
#走棋函数
def callback(event):
 global turn
 global Myturn
 if Myturn==-1:
 Myturn=turn
 else:
 if(Myturn!=turn):
 showinfo(title="提示",message="还没轮到自己走棋")
 return
 #print("clicked at",event.x,event.y)
 x=(event.x)//40
 y=(event.y)//40
 print("clicked at",x,y,turn)
 if map[x][y]!=" ":
 showinfo(title="提示",message="已有棋子")
 else:
 img1=imgs[turn]
 cv.create_image((x*40+20,y*40+20),image=img1)
 cv.pack()
 map[x][y]=str(turn)
 pos=str(x)+','+str(y)
 sendMessage("move|"+pos)
 print("客户端走的位置",pos)
 label1["text"]="客户端走的位置"+pos
 #输出输赢信息
 if win_lose( )==True:
 if turn==0:
 showinfo(title="提示",message="黑方你赢了")
 sendMessage("over|黑方你赢了!")
 else:
 showinfo(title="提示",message="白方你赢了!")
 sendMessage("over|白方你赢了!")
 #换下一方走棋:
 if turn==0:
 turn=1
 else:
 turn=0
#画棋盘
def drawQiPan( ): #画棋盘
 for i in range(0,15):
 cv.create_line(20,20+40*i,580,20+40*i,width=2)
 for i in range(0,15):
 cv.create_line(20+40*i,20,20+40*i,580,width=2)
 cv.pack()
#输赢判断
def win_lose():
 a=str(turn)
 print("a=",a)
 for i in range(0,11):
 for j in range(0,11):
 if map[i][j]==a and map[i+1][j+1]==a and map[i+2][j+2]==a and map[i+3][j+3]==a and map[i+4][j+4]==a:
 print("x=y轴上形成五子连珠")
 return True
 for i in range(4,15):
 for j in range(0,11):
 if map[i][j]==a and map[i-1][j+1]==a and map[i-2][j+2]==a and map[i-3][j+3]==a and map[i-4][j+4]==a:
 print("x=-y轴上形成五子连珠")
 return True
 for i in range(0,15):
 for j in range(4,15):
 if map[i][j]==a and map[i][j-1]==a and map[i][j-2]==a and map[i][j-2]==a and map[i][j-4]==a:
 print("Y轴上形成了五子连珠")
 return True
 for i in range(0,11):
 for j in range(0,15):
 if map[i][j]==a and map[i+1][j]==a and map[i+2][j]==a and map[i+3][j]==a and map[i+4][j]==a:
 print("X轴形成五子连珠")
 return True
 return False

#接受消息
def receiveMessage(): #接受消息
 global s
 while True:
 data = s.recv(1024).decode('utf-8')
 a = data.split("|")
 if not data:
 print('server has exited!')
 break
 elif a[0] == 'exit':
 print('对方退出!')
 lanel1["text"] = '对方退出!游戏结束!'
 elif a[0] == 'over':
 print('对方赢信息!')
 label1["text"] = data.split("|")[0]
 showinfo(title="提示", message=data.split("|")[1])
 elif a[0] == 'move':
 print('received:', data)
 p = a[1].split(",")
 x = int(p[0])
 y = int(p[1])
 print(p[0], p[1])
 label1["text"] = "服务器走的位置" + p[0] + p[1]
 drawOtherChess(x,y)
 s.close()
#启动线程接受客户端消息
def startNewThread():
 thread=threading.Thread(target=receiveMessage,args=())
 thread.setDaemon(True)
 thread.start()
#主程序

map=[[" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "] for y in range(15)]
cv=Canvas(root,bg='green',width=610,height=610)
drawQiPan()
cv.bind("<Button-1>",callback)
cv.pack()
label1=Label(root,text="客户端...")
label1.pack()
button1=Button(root,text="退出游戏")
button1.bind("<Button-1>",callexit)
button1.pack()
#创建UDP
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
port=8000
host='localhost'
pos='join|'
sendMessage(pos)
startNewThread()
root.mainloop()

2.数据通信协议源代码:

下面展示一些 数据通信协议源代码。

def receiveMessage():
 global s
 while True:
 global addr
 data,addr=s.recvfrom(1024)
 data=data.decode('utf-8')
 a=data.split("|")
 if not data:
 print("client has exited!")
 break
 elif a[0]=='join': #连接服务器请求
 print('client 连接服务器!')
 label1["text"]='client连接服务器成功,请你走棋!'
 elif a[0]=='exit':
 print('client 对方退出!')
 label1["text"]='client对方退出,游戏结束!'
 elif a[0]=='over':
 print('对方赢信息!')
 label1["text"]=data.split("|")[0]
 showinfo(title="提示",message=data.split("|")[1])
 elif a[0]=='move':
 print('received:',data,'from',addr)
 p=a[1].split(",")
 x=int(p[0])
 y=int(p[1])
 print(p[0],p[1])
 label1["text"]="客户端走的位置"+p[0]+p[1]
 drawOtherChess(x,y)
 s.close()
#输赢判断
def win_lose():
 a=str(turn)
 print("a=",a)
 for i in range(0,11):
 for j in range(0,11):
 if map[i][j]==a and map[i+1][j+1]==a and map[i+2][j+2]==a and map[i+3][j+3]==a and map[i+4][j+4]==a:
 print("x=y轴上形成五子连珠")
 return True
 for i in range(4,15):
 for j in range(0,11):
 if map[i][j]==a and map[i-1][j+1]==a and map[i-2][j+2]==a and map[i-3][j+3]==a and map[i-4][j+4]==a:
 print("x=-y轴上形成五子连珠")
 return True
 for i in range(0,15):
 for j in range(4,15):
 if map[i][j]==a and map[i][j-1]==a and map[i][j-2]==a and map[i][j-2]==a and map[i][j-4]==a:
 print("Y轴上形成了五子连珠")
 return True
 for i in range(0,11):
 for j in range(0,15):
 if map[i][j]==a and map[i+1][j]==a and map[i+2][j]==a and map[i+3][j]==a and map[i+4][j]==a:
 print("X轴形成五子连珠")
 return True
 return False
def checkwin(x,y):
 flag=False
 count=1
 color=map[x][y]
 i=1
 #横向判断
 while color==map[x+i][y]:
 count=count+1
 i=i+1
 i=1
 while color==map[x-i][y]:
 count=count+1
 i=i+1
 if count>=5:
 flag=True
 #竖向判断
 i=1
 while color==map[x][y+i]:
 count=count+1
 i=i+1
 i=1
 while color==map[x][y-i]:
 count=count+1
 i=i+1
 if count>=5:
 flag=True
 #x=y判断
 i=1
 j=1
 while color==map[x+i][y+i]:
 count=count+1
 i=i+1
 j=j+1
 if count>=5:
 flag=True
 j=1
 i=1
 while color==map[x-i][y-i]:
 count=count+1
 i=i+1
 j=j+1
 if count>=5:
 flag=True

3.服务器端源代码

客户端源代码如下:

from tkinter import *
from tkinter.messagebox import *
import socket,threading,os
def drawQiPan():
 for i in range(0,15):
 cv.create_line(20,20+40*i,580,20+40*i,width=2)
 for i in range(0,15):
 cv.create_line(20+40*i,20,20+40*i,580,width=2)
 cv.pack()
#走棋函数
def callpos(event):
 global turn
 global Myturn
 if Myturn==-1: #第一次确认自己的角色
 Myturn=turn
 else:
 if(Myturn!=turn):
 showinfo(title="提示",message="还没轮到自己下棋")
 return
 #print("clicked at",event.x,event.y,true)
 x=(event.x)//40
 y=(event.y)//40
 print("clicked at",x,y,turn)
 if map[x][y]!=" ":
 showinfo(title="提示",message="已有棋子")
 else:
 img1=imgs[turn]
 cv.create_image((x*40+20,y*40+20),image=img1)
 cv.pack()
 map[x][y]=str(turn)
 pos=str(x)+","+str(y)
 sendMessage("move|"+pos)
 print("服务器走的位置",pos)
 label1["text"]="服务器走的位置"+pos
 #输出输赢信息
 if win_lose( )==True:
 if turn==0:
 showinfo(title="提示",message="黑方你赢了")
 sendMessage("over|黑方你赢了")
 else:
 showinfo(title="提示", message="白方你赢了")
 sendMessage("over|白方你赢了")
 #换下一方走棋
 if turn==0:
 turn=1
 else:
 turn=0
#发送消息
def sendMessage(pos):
 global s
 global addr
 s.sendto(pos.encode(),addr)
#退出函数
def callexit(event):
 pos="exit|"
 sendMessage(pos)
 os._exit(0)

#画对方棋子
def drawOtherChess(x,y):
 global turn
 img1=imgs[turn]
 cv.create_image((x*40+20,y*40+20),image=img1)
 cv.pack()
 map[x][y]=str(turn)
 #换下一方走棋
 if turn==0:
 turn=1
 else:
 turn=0

#判断整个棋盘的输赢
def win_lose():
 a=str(turn)
 print("a=",a)
 for i in range(0,11):
 for j in range(0,11):
 if map[i][j]==a and map[i+1][j+1]==a and map[i+2][j+2]==a and map[i+3][j+3]==a and map[i+4][j+4]==a:
 print("x=y轴上形成五子连珠")
 return True
 for i in range(4,15):
 for j in range(0,11):
 if map[i][j]==a and map[i-1][j+1]==a and map[i-2][j+2]==a and map[i-3][j+3]==a and map[i-4][j+4]==a:
 print("x=-y轴上形成五子连珠")
 return True
 for i in range(0,15):
 for j in range(4,15):
 if map[i][j]==a and map[i][j-1]==a and map[i][j-2]==a and map[i][j-2]==a and map[i][j-4]==a:
 print("Y轴上形成了五子连珠")
 return True
 for i in range(0,11):
 for j in range(0,15):
 if map[i][j]==a and map[i+1][j]==a and map[i+2][j]==a and map[i+3][j]==a and map[i+4][j]==a:
 print("X轴形成五子连珠")
 return True
 return False
#输出map地图
def print_map():
 for j in range(0,15):
 for i in range(0,15):
 print(map[i][j],end=' ')
 print('w')
#接受消息
def receiveMessage():
 global s
 while True:#接受客户端发送的消息
 global addr
 data,addr=s.recvfrom(1024)
 data=data.decode('utf-8')
 a=data.split("|")
 if not data:
 print('client has exited!')
 break
 elif a[0]=='join':#连接服务器的请求
 print('client 连接服务器!')
 label1["text"]='client连接服务器成功,请你走棋!'
 elif a[0]=='exit':
 print('client对方退出!')
 label1["text"]='client对方退出,游戏结束!'
 elif a[0]=='over':
 print('对方赢信息!')
 labl1["text"]==data.split("|")[0]
 showinfo(title="提示",message=data.split("1")[1])
 elif a[0]=='move':
 print('received:',data,'from',addr)
 p=a[1].split(",")
 x=int(p[0])
 y=int(p[1])
 print(p[0],p[1])
 label1["text"]="客户端走的位置"+p[0]+p[1]
 drawOtherChess(x,y)
 s.close()
def startNewThread( ):#启动新线程来接受客户端消息
 thread=threading.Thread(target=receiveMessage,args=())
 thread.setDaemon(True)
 thread.start()
root=Tk()
root.title("网络五子棋v2.0-服务器端")
imgs=[PhotoImage(file='E:\\game\\BlackStone.gif'),PhotoImage(file='E:\\game\\WhiteStone.gif')]
turn=0
Myturn=-1
map=[[" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "] for y in range(15)]
cv=Canvas(root,bg='green',width=610,height=610)
drawQiPan()
cv.bind("<Button-1>",callpos)
cv.pack()
label1=Label(root,text="服务器端...")
label1.pack()
button1=Button(root,text="退出游戏")
button1.bind("<Button-1>",callexit)
button1.pack()
#创建UDP SOCKET
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.bind(('localhost',8000))
addr=('localhost',8000)
startNewThread()
root.mainloop()

运行结果展示:

python网络编程之五子棋游戏

所有的都在这里了。

更多有趣的经典小游戏实现专题,也分享给大家:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
优化Python代码使其加快作用域内的查找
Mar 30 Python
Python面向对象编程基础解析(一)
Oct 26 Python
python利用requests库模拟post请求时json的使用教程
Dec 07 Python
python获取Pandas列名的几种方法
Aug 07 Python
Django项目中实现使用qq第三方登录功能
Aug 13 Python
Python学习笔记之Zip和Enumerate用法实例分析
Aug 14 Python
在tensorflow中实现屏蔽输出的log信息
Feb 04 Python
Python通过format函数格式化显示值
Oct 17 Python
通过Django Admin+HttpRunner1.5.6实现简易接口测试平台
Nov 11 Python
Python模拟键盘输入自动登录TGP
Nov 27 Python
jupyter notebook远程访问不了的问题解决方法
Jan 11 Python
在Windows下安装配置CPU版的PyTorch的方法
Apr 02 Python
Jupyter notebook如何修改平台字体
May 13 #Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
May 13 #Python
Django 允许局域网中的机器访问你的主机操作
May 13 #Python
Django 用户登陆访问限制实例 @login_required
May 13 #Python
Python selenium模拟手动操作实现无人值守刷积分功能
May 13 #Python
PyQt5 控件字体样式等设置的实现
May 13 #Python
Python tkinter实现简单加法计算器代码实例
May 13 #Python
You might like
PHP has encountered an Access Violation at 7C94BD02解决方法
2009/08/24 PHP
PHP MemCached高级缓存配置图文教程
2010/08/05 PHP
PHP使用观察者模式处理异常信息的方法详解
2019/09/24 PHP
PHP读取文件或采集时解决中文乱码
2021/03/09 PHP
Javascript实例教程(19) 使用HoTMetal(4)
2006/12/23 Javascript
超简单的jquery的AJAX用法
2010/05/10 Javascript
javascript下利用arguments实现string.format函数
2010/08/24 Javascript
jQuery 网易相册鼠标移动显示隐藏效果实现代码
2013/03/31 Javascript
onbeforeunload与onunload事件异同点总结
2013/06/24 Javascript
轻松创建nodejs服务器(10):处理上传图片
2014/12/18 NodeJs
jQuery Validate表单验证入门学习
2015/12/18 Javascript
基于canvas实现的绚丽圆圈效果完整实例
2016/01/26 Javascript
实现easyui的datagrid导出为excel的示例代码
2016/11/10 Javascript
js操作浏览器的参数方法
2017/01/21 Javascript
input框中自动展示当前日期yyyy/mm/dd的实现方法
2017/07/06 Javascript
分分钟学会vue中vuex的应用(入门教程)
2017/09/14 Javascript
AngularJS上传文件的示例代码
2018/11/10 Javascript
微信小程序页面间值传递的两种方法
2018/11/26 Javascript
js的各种数据类型判断的介绍
2019/01/19 Javascript
详解Vue前端对axios的封装和使用
2019/04/01 Javascript
Vue 实现监听窗口关闭事件,并在窗口关闭前发送请求
2020/09/01 Javascript
vue+Element-ui前端实现分页效果
2020/11/15 Javascript
JavaScript WeakMap使用详解
2021/02/05 Javascript
python使用xpath中遇到:到底是什么?
2018/01/04 Python
python微信公众号之关注公众号自动回复
2018/10/25 Python
我们为什么要减少Python中循环的使用
2019/07/10 Python
香港零食网购:上仓胃子
2020/06/08 全球购物
法律工作求职自荐信
2013/10/31 职场文书
企业党员一句话承诺
2014/05/30 职场文书
忠诚教育心得体会
2014/09/03 职场文书
优秀学生干部事迹材料
2014/12/24 职场文书
寻找最美乡村教师观后感
2015/06/18 职场文书
Pytorch中TensorBoard及torchsummary的使用详解
2021/05/12 Python
Grafana可视化监控系统结合SpringBoot使用
2022/04/19 Redis
Vue OpenLayer测距功能的实现
2022/04/20 Vue.js
python pandas 解析(读取、写入)CSV 文件的操作方法
2022/12/24 Python