python网络编程之五子棋游戏

2020-09-29 0 953

一.本案例基于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网络编程之五子棋游戏

所有的都在这里了。

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

C++经典小游戏汇总

python经典小游戏汇总

python俄罗斯方块游戏集合

JavaScript经典游戏 玩不停

java经典小游戏汇总

javascript经典小游戏汇总

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。

遇见资源网 Python python网络编程之五子棋游戏 http://www.ox520.com/25596.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务