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之关于循环的小伎俩
Oct 02 Python
Python中if __name__ == &quot;__main__&quot;详细解释
Oct 21 Python
wxPython使用系统剪切板的方法
Jun 16 Python
浅谈python中截取字符函数strip,lstrip,rstrip
Jul 17 Python
Python通过RabbitMQ服务器实现交换机功能的实例教程
Jun 29 Python
Python中datetime模块参考手册
Jan 13 Python
python2.7无法使用pip的解决方法(安装easy_install)
Apr 03 Python
Python中os模块功能与用法详解
Feb 26 Python
Python实现Wordcloud生成词云图的示例
Mar 30 Python
Python ADF 单位根检验 如何查看结果的实现
Jun 03 Python
Python unittest discover批量执行代码实例
Sep 08 Python
深入探讨opencv图像矫正算法实战
May 21 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归并排序的实现
2016/10/18 PHP
php 输出json及显示json中的中文汉字详解及实例
2016/11/09 PHP
快速解决PHP调用Word组件DCOM权限的问题
2017/12/27 PHP
用JavaScript实现UrlEncode和UrlDecode的脚本代码
2008/07/23 Javascript
jQuery EasyUI API 中文文档 - ProgressBar 进度条
2011/09/29 Javascript
转换字符串为json对象的方法详解
2013/11/29 Javascript
JavaScript函数的4种调用方法详解
2014/04/22 Javascript
JS实现OCX控件的事件响应示例
2014/09/17 Javascript
jQuery选择器全集详解
2014/11/24 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(同步显示图像位置信息)
2016/12/02 Javascript
javascript表单正则应用
2017/02/04 Javascript
从零开始搭建一个react项目开发
2018/02/09 Javascript
vue如何引入sass全局变量
2018/06/28 Javascript
微信公众号H5支付接口调用方法
2019/01/10 Javascript
vue实现的树形结构加多选框示例
2019/02/02 Javascript
使用layer.msg 时间设置不起作用的解决方法
2019/09/12 Javascript
vue 使用鼠标滚动加载数据的例子
2019/10/31 Javascript
JavaScript进阶(四)原型与原型链用法实例分析
2020/05/09 Javascript
Element Collapse 折叠面板的使用方法
2020/07/26 Javascript
Python切片用法实例教程
2014/09/08 Python
在Python下利用OpenCV来旋转图像的教程
2015/04/16 Python
Python中easy_install 和 pip 的安装及使用
2017/06/05 Python
Python中进程和线程的区别详解
2017/10/29 Python
Python实现类似比特币的加密货币区块链的创建与交易实例
2018/03/20 Python
Python3 安装PyQt5及exe打包图文教程
2019/01/08 Python
Python使用configparser读取ini配置文件
2020/05/25 Python
Python中zip函数如何使用
2020/06/04 Python
使用 css3 transform 属性来变换背景图的方法
2019/05/07 HTML / CSS
纯CSS实现颜色渐变效果(包含环形渐变、线性渐变、彩虹效果等)
2014/05/07 HTML / CSS
Debenhams爱尔兰:英国知名的百货公司
2017/01/02 全球购物
Foot Locker英国官网:美国知名运动产品零售商
2019/02/21 全球购物
农村葬礼主持词
2014/03/31 职场文书
会计系毕业求职信
2014/08/07 职场文书
组工干部演讲稿
2014/09/02 职场文书
群众路线教育实践活动总结
2014/10/30 职场文书
2015年青年志愿者工作总结
2015/05/20 职场文书