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程序设计入门(2)变量类型简介
Jun 16 Python
在Python中编写数据库模块的教程
Apr 29 Python
Python实现快速多线程ping的方法
Jul 15 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
Jun 02 Python
python安装Scrapy图文教程
Aug 14 Python
Python解决两个整数相除只得到整数部分的实例
Nov 10 Python
Python编程深度学习绘图库之matplotlib
Dec 28 Python
通过PYTHON来实现图像分割详解
Jun 26 Python
Python导入数值型Excel数据并生成矩阵操作
Jun 09 Python
Python通过yagmail实现发送邮件代码解析
Oct 27 Python
Python用摘要算法生成token及检验token的示例代码
Dec 01 Python
Python四款GUI图形界面库介绍
Jun 05 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
phalcon框架使用指南
2016/02/23 PHP
取得传值的函数
2006/10/27 Javascript
提示$ is not defined错误分析及解决
2013/04/09 Javascript
基于MVC3方式实现下拉列表联动(JQuery)
2013/09/02 Javascript
jQuery layui常用方法介绍
2016/07/25 Javascript
Bootstrap幻灯片轮播图支持触屏左右手势滑动的实现方法
2016/10/13 Javascript
详解Vue.js——60分钟组件快速入门(上篇)
2016/12/05 Javascript
vue2中filter()的实现代码
2017/07/09 Javascript
javascript实现最长公共子序列实例代码
2018/02/05 Javascript
karma+webpack搭建vue单元测试环境的方法示例
2018/05/24 Javascript
详解JavaScript中的强制类型转换
2019/04/15 Javascript
vue设置导航栏、侧边栏为公共页面的例子
2019/11/01 Javascript
vue-router 路由传参用法实例分析
2020/03/06 Javascript
小程序自定义导航栏兼容适配所有机型(附完整案例)
2020/04/26 Javascript
vue实现动态表格提交参数动态生成控件的操作
2020/11/09 Javascript
JavaScript canvas实现跟随鼠标移动小球
2021/02/09 Javascript
跟老齐学Python之从格式化表达式到方法
2014/09/28 Python
浅谈python中的数字类型与处理工具
2017/08/02 Python
Python中input与raw_input 之间的比较
2017/08/20 Python
Django数据库操作的实例(增删改查)
2017/09/04 Python
python 实现求解字符串集的最长公共前缀方法
2018/07/20 Python
Python3爬虫爬取百姓网列表并保存为json功能示例【基于request、lxml和json模块】
2018/12/05 Python
Python Unittest根据不同测试环境跳过用例的方法
2018/12/16 Python
Django Rest framework之权限的实现示例
2018/12/17 Python
PyCharm使用之配置SSH Interpreter的方法步骤
2019/12/26 Python
Python 解析pymysql模块操作数据库的方法
2020/02/18 Python
Python爬取网站图片并保存的实现示例
2021/02/26 Python
美国领先的低折扣旅行网站:Hotwire
2019/01/19 全球购物
Nike澳大利亚官网:Nike.com (AU)
2019/06/03 全球购物
生产部经理岗位职责
2013/12/16 职场文书
自强之星事迹材料
2014/05/12 职场文书
2014年国庆标语
2014/06/30 职场文书
幼儿园老师新年寄语2015
2014/12/08 职场文书
2016入党心得体会范文
2016/01/06 职场文书
甜美蛋糕店的创业计划书模板,拿来即用!
2019/08/21 职场文书
Keras在mnist上的CNN实践,并且自定义loss函数曲线图操作
2021/05/25 Python