python網(wǎng)絡(luò)編程之五子棋游戲
一.本案例基于UDP的socket編程方法來制作五子棋程序,網(wǎng)絡(luò)五子棋采用C/S架構(gòu),分為服務(wù)器端和客戶端,游戲時服務(wù)端首先啟動,當(dāng)客戶端啟動連接后,服務(wù)器端可以走棋,輪到自己棋才可以在棋盤上落子,同時下方標(biāo)簽會顯示對方走起信息,服務(wù)器端用戶可以通過“退出游戲”按鈕可以結(jié)束游戲;
1.數(shù)據(jù)通信協(xié)議
網(wǎng)絡(luò)五子棋游戲設(shè)計的難點(diǎn)在于對方進(jìn)行通信,這里使用面向非連接的Socket編程,Socket編程用于C/S開發(fā),在這類應(yīng)用中,客戶端和服務(wù)器端通常需要先建立連接,然后發(fā)送和接收數(shù)據(jù),交互完成后需要斷開連接,本章采用基于UDP的Socket編程實現(xiàn),這里雖然兩臺計算機(jī)不分主次,但涉及時候假設(shè)一臺作為服務(wù)器端,等待其他方加入,其他想加入必須輸入服務(wù)器端主機(jī)的IP;
下面展示一些 數(shù)據(jù)通信協(xié)議代碼。
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': #連接服務(wù)器請求 print('client 連接服務(wù)器!') label1["text"]='client連接服務(wù)器成功,請你走棋!' elif a[0]=='exit': print('client 對方退出!') label1["text"]='client對方退出,游戲結(jié)束!' 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.判斷輸贏的算法
本游戲關(guān)鍵技術(shù)就是判斷輸贏的算法,對于算法實現(xiàn)大致可以分為以下幾個部分:
(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("網(wǎng)絡(luò)五子棋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 #發(fā)送消息 def sendMessage(pos): global s s.sendto(pos.encode(),(host,port)) #退出函數(shù) def callexit(event): pos="exit|" sendMessage(pos) os._exit(0) #走棋函數(shù) 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"] = '對方退出!游戲結(jié)束!' 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"] = "服務(wù)器走的位置" + 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() #創(chuàng)建UDP s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) port=8000 host='localhost' pos='join|' sendMessage(pos) startNewThread() root.mainloop()
2.數(shù)據(jù)通信協(xié)議源代碼:
下面展示一些 數(shù)據(jù)通信協(xié)議源代碼。
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': #連接服務(wù)器請求 print('client 連接服務(wù)器!') label1["text"]='client連接服務(wù)器成功,請你走棋!' elif a[0]=='exit': print('client 對方退出!') label1["text"]='client對方退出,游戲結(jié)束!' 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.服務(wù)器端源代碼
客戶端源代碼如下:
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() #走棋函數(shù) def callpos(event): global turn global Myturn if Myturn==-1: #第一次確認(rèn)自己的角色 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("服務(wù)器走的位置",pos) label1["text"]="服務(wù)器走的位置"+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 #發(fā)送消息 def sendMessage(pos): global s global addr s.sendto(pos.encode(),addr) #退出函數(shù) 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:#接受客戶端發(fā)送的消息 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':#連接服務(wù)器的請求 print('client 連接服務(wù)器!') label1["text"]='client連接服務(wù)器成功,請你走棋!' elif a[0]=='exit': print('client對方退出!') label1["text"]='client對方退出,游戲結(jié)束!' 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("網(wǎng)絡(luò)五子棋v2.0-服務(wù)器端") 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="服務(wù)器端...") label1.pack() button1=Button(root,text="退出游戲") button1.bind("<Button-1>",callexit) button1.pack() #創(chuàng)建UDP SOCKET s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) s.bind(('localhost',8000)) addr=('localhost',8000) startNewThread() root.mainloop()
運(yùn)行結(jié)果展示:
所有的都在這里了。
更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,也分享給大家:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- python Socket網(wǎng)絡(luò)編程實現(xiàn)C/S模式和P2P
- python神經(jīng)網(wǎng)絡(luò)編程實現(xiàn)手寫數(shù)字識別
- python網(wǎng)絡(luò)編程socket實現(xiàn)服務(wù)端、客戶端操作詳解
- Python網(wǎng)絡(luò)編程之使用TCP方式傳輸文件操作示例
- python網(wǎng)絡(luò)編程 使用UDP、TCP協(xié)議收發(fā)信息詳解
- python socket網(wǎng)絡(luò)編程之粘包問題詳解
- Python網(wǎng)絡(luò)編程使用select實現(xiàn)socket全雙工異步通信功能示例
- Python網(wǎng)絡(luò)編程之TCP套接字簡單用法示例
- Python網(wǎng)絡(luò)編程 Python套接字編程
- Python網(wǎng)絡(luò)編程之ZeroMQ知識總結(jié)
相關(guān)文章
python實現(xiàn)在windows下操作word的方法
這篇文章主要介紹了python實現(xiàn)在windows下操作word的方法,涉及Python操作word實現(xiàn)打開、插入、轉(zhuǎn)換、打印等操作的相關(guān)技巧,非常具有實用價值,需要的朋友可以參考下2015-04-04Python pandas 列轉(zhuǎn)行操作詳解(類似hive中explode方法)
這篇文章主要介紹了Python pandas 列轉(zhuǎn)行操作詳解(類似hive中explode方法),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-05-05Python3實現(xiàn)簡單可學(xué)習(xí)的手寫體識別(實例講解)
下面小編就為大家?guī)硪黄狿ython3實現(xiàn)簡單可學(xué)習(xí)的手寫體識別(實例講解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10