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修改MP3文件的方法
Jun 15 Python
shelve  用来持久化任意的Python对象实例代码
Oct 12 Python
Python random模块用法解析及简单示例
Dec 18 Python
Python实现图片尺寸缩放脚本
Mar 10 Python
python3解析库pyquery的深入讲解
Jun 26 Python
机器学习之KNN算法原理及Python实现方法详解
Jul 09 Python
tensorflow学习教程之文本分类详析
Aug 07 Python
Python实现程序判断季节的代码示例
Jan 28 Python
使用Pytorch来拟合函数方式
Jan 14 Python
python实现超级马里奥
Mar 18 Python
Python3.7安装PyQt5 运行配置Pycharm的详细教程
Oct 15 Python
10个python爬虫入门基础代码实例 + 1个简单的python爬虫完整实例
Dec 16 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
WordPress中设置Post Type自定义文章类型的实例教程
2016/05/10 PHP
Laravel模型间关系设置分表的方法示例
2018/04/21 PHP
laravel-admin 管理平台获取当前登陆用户信息的例子
2019/10/08 PHP
jquery.validate使用攻略 第一部
2010/07/01 Javascript
jquery 与NVelocity 产生冲突的解决方法
2011/06/13 Javascript
createElement与createDocumentFragment的点点区别小结
2011/12/19 Javascript
一个CSS+jQuery实现的放大缩小动画效果
2014/02/19 Javascript
多种方法实现360浏览器下禁止自动填写用户名密码
2014/06/16 Javascript
本地Bootstrap文件字体图标引入却无法显示问题的解决方法
2020/04/18 Javascript
vue之将echart封装为组件
2018/06/02 Javascript
JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法示例
2018/07/27 Javascript
Vue的双向数据绑定实现原理解析
2020/02/17 Javascript
详解JavaScript 的执行机制
2020/09/18 Javascript
[00:47]DOTA2荣耀之路6:玩不了啦!
2018/05/30 DOTA
Python常用模块用法分析
2014/09/08 Python
使用python装饰器计算函数运行时间的实例
2018/04/21 Python
Python多进程原理与用法分析
2018/08/21 Python
利用Python求阴影部分的面积实例代码
2018/12/05 Python
解决Mac下使用python的坑
2019/08/13 Python
Python的几种主动结束程序方式
2019/11/22 Python
通过实例解析Python return运行原理
2020/03/04 Python
Python爬虫工具requests-html使用解析
2020/04/29 Python
canvas离屏技术与放大镜实现代码示例
2018/08/31 HTML / CSS
雅诗兰黛旗下走天然植物路线的彩妆品牌:Prescriptives
2016/08/14 全球购物
希腊品牌鞋类销售网站:epapoutsia.gr
2020/03/18 全球购物
酒店服务与管理毕业生求职信
2013/11/02 职场文书
致裁判员加油稿
2014/02/08 职场文书
《挑山工》的教学反思
2014/02/16 职场文书
租房协议书怎么写
2014/04/10 职场文书
党的群众路线学习材料
2014/05/16 职场文书
高中课程设置方案
2014/05/28 职场文书
娱乐节目策划方案
2014/06/10 职场文书
运动会广播稿50字-100字
2014/10/11 职场文书
留学推荐信怎么写
2015/03/26 职场文书
《叶问2》观后感
2015/06/15 职场文书
Window server中安装Redis的超详细教程
2021/11/17 Redis