python网络编程之五子棋游戏

时间:2021-05-22

一.本案例基于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 socketimport threadingimport os#主程序root=Tk()root.title("网络五子棋v2.0--UDP客户端")imgs=[PhotoImage(file='E:\\game\\BlackStone.gif'),PhotoImage(file='E:\\game\\WhiteStone.gif')]turn=0Myturn=-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()#创建UDPs=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)port=8000host='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 Falsedef 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,osdef 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=0Myturn=-1map=[[" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "] 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 SOCKETs=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)s.bind(('localhost',8000))addr=('localhost',8000)startNewThread()root.mainloop()

运行结果展示:

所有的都在这里了。

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

C++经典小游戏汇总

python经典小游戏汇总

python俄罗斯方块游戏集合

JavaScript经典游戏 玩不停

java经典小游戏汇总

javascript经典小游戏汇总

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

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章