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(Tornado)模拟登录小米抢手机
Nov 12 Python
python实现网站的模拟登录
Jan 04 Python
python将unicode转为str的方法
Jun 21 Python
Python的多维空数组赋值方法
Apr 13 Python
python自动发送邮件脚本
Jun 20 Python
Python 中的range(),以及列表切片方法
Jul 02 Python
django之对FileField字段的upload_to的设定方法
Jul 28 Python
Python绘制股票移动均线的实例
Aug 24 Python
Django自带日志 settings.py文件配置方法
Aug 30 Python
基于Python新建用户并产生随机密码过程解析
Oct 08 Python
python 调试冷知识(小结)
Nov 11 Python
基于python模拟TCP3次握手连接及发送数据
Nov 06 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
Http 1.1 Etag 与 Last-Modified提高php效率
2008/01/10 PHP
PHP添加Xdebug扩展的方法
2014/02/12 PHP
CI框架中集成CKEditor编辑器的教程
2014/06/09 PHP
php将csv文件导入到mysql数据库的方法
2014/12/24 PHP
php判断用户是否手机访问代码
2015/06/08 PHP
利用laravel搭建一个迷你博客实战教程
2017/08/13 PHP
jQuery的一些注意
2006/12/06 Javascript
jquery $(document).ready() 与window.onload的区别
2009/12/28 Javascript
js中的数组Array定义与sort方法使用示例
2013/08/29 Javascript
javascript省市区三级联动下拉框菜单实例演示
2015/11/29 Javascript
JS实现斐波那契数列的五种方式(小结)
2020/09/09 Javascript
[05:59]带你看看DPC的台前幕后
2021/03/11 DOTA
python开发之字符串string操作方法实例详解
2015/11/12 Python
整理Python 常用string函数(收藏)
2016/05/30 Python
Python数据分析之双色球统计单个红和蓝球哪个比例高的方法
2018/02/03 Python
pandas 快速处理 date_time 日期格式方法
2018/11/12 Python
pygame游戏之旅 创建游戏窗口界面
2018/11/20 Python
python创建与遍历List二维列表的方法
2019/08/16 Python
PyQt5事件处理之定时在控件上显示信息的代码
2020/03/25 Python
纯CSS实现预加载动画效果
2017/09/06 HTML / CSS
浅析HTML5 Landmark
2020/09/11 HTML / CSS
巴西补充剂和维生素购物网站:Natue
2019/06/17 全球购物
汽车技术服务与营销专业推荐信
2013/11/29 职场文书
高分子材料与工程专业个人求职信
2013/12/15 职场文书
临床医师专业个人自我评价
2014/01/08 职场文书
授权委托书格式模板
2014/04/03 职场文书
好习惯伴我成长演讲稿
2014/05/21 职场文书
“向国旗敬礼”主题班会活动设计方案
2014/09/27 职场文书
校园游戏活动新闻稿
2014/10/15 职场文书
白鹤梁导游词
2015/02/06 职场文书
2016春季运动会通讯稿
2015/07/18 职场文书
2016大学生求职自荐信范文
2016/01/28 职场文书
sqlserver连接错误之SQL评估期已过的问题解决
2022/03/23 SQL Server
python实现对doc、txt、xls等文档的读写操作
2022/04/02 Python
Innodb存储引擎中的后台线程详解
2022/04/03 MySQL
win10双系统怎么删除一个系统?win10电脑有两个系统删除一个的操作方法
2022/07/15 数码科技