diff --git a/SafariChess_Gamev1.0.py b/SafariChess_Gamev1.0.py index 8ea1d08..2a20cd4 100644 --- a/SafariChess_Gamev1.0.py +++ b/SafariChess_Gamev1.0.py @@ -11,6 +11,7 @@ it handle user input and GUI import colorsys import json +from multiprocessing import connection import pygame as pg import sys import socket @@ -34,10 +35,41 @@ SIZE = 64 IMAGES = {} bias_top = 100 #棋盘的上边距 bias_left = 100 #棋盘的左边距 - +#网络道具 +client = None +networkMsg = None +server = None +port = None +addr = None +connection = None #网络版更新需要注意多线程的问题? #尝试写一个函数分配一个新线程供监听 +def startNewThread(target): + thread = Thread(target=target) + thread.daemon =True + thread.start() +def listenFromServer(): + global networkMsg + try: + while True: + recvMsg = client.recvfrom(1024).decode('utf-8') + if len(recvMsg) != 0: + networkMsg = json.loads(recvMsg) + except socket.error as e: + print(e) + return e +def startNetworkServices(): + global client,server,port,addr,connection + client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server = '127.0.0.1' + port = 50005 + addr = (server,port) + connection = client.connect(addr) + startNewThread(target=listenFromServer) + +def jsonAnalysis(networkMsg): + pass #等待敌人移动 def loadImages():#加载图片,a,b双方分别有象狮豹狼狐鹰鼠七个角色 @@ -200,7 +232,6 @@ def MainMenu(): button_3 = Button(bt3,(350,450)) button_4 = Button(bt4,(350,500)) mode = -1 - p1,p2 = 0,0 run = True while run: mainClock.tick(60) @@ -238,38 +269,26 @@ def MainMenu(): -def main(mode,p1,p2,network = None): - NewPlayerMessage = '' #来自对手的信息 - if mode == 2: - network=backend.Network() - #p1 = input("Enter your name: ") - p1 = 'player1' - myPlayerData = { - 'type': 0, # game state type ? - 'msg': { - 'name': player1 - } - } - network.send(myPlayerData) - print("Waiting for other player...") - NewPlayerMessage = network.receive() - print() - p2 = NewPlayerMessage['counterpart_name'] +def main(mode): + global networkMsg + networkMsg = None pg.init() screen = pg.display.set_mode((BOARD_WIDTH + MOVE_LOG_PANEL_WIDTH, BOARD_HEIGHT)) - pg.display.set_caption("Safafi Chess Game") + pg.display.set_caption("Safari Chess Game") clock = pg.time.Clock() screen.fill(pg.Color("white")) loadImages() drawBoard(screen) - isOnline = bool(network != None) - game_state=backend.GameState(isNet=isOnline,MySide=True if not isOnline else bool(NewPlayerMessage['side']),game_id=NewPlayerMessage['game_id'],client=network) + isOnline = bool(mode == 2) + game_state=backend.GameState() + #* cancelled args: MySide=True if not isOnline else bool(NewPlayerMessage['side']),game_id=NewPlayerMessage['game_id'] valid_moves=game_state.getAllMoves() running = True + other_joined = False mademove = False game_over = False - square_selected = ()#刚开始没有选择任何一个棋子 - click_queue = []#点击队列,记录第一次点击和第二次点击位置,方便移动棋子 + square_selected = () #刚开始没有选择任何一个棋子 + click_queue = [] #点击队列,记录第一次点击和第二次点击位置,方便移动棋子 pg.display.update() startGamePage(mode) @@ -319,7 +338,36 @@ def main(mode,p1,p2,network = None): clock.tick(60) pg.display.flip() elif mode == 2: + startNetworkServices() + myPlayerData = { + 'type': 0, # game state type ? + 'msg': { + 'name': 'myName' + } + } + login_packet = json.dumps(myPlayerData) + if (sys.version[:1] == '3'): + login_packet = login_packet.encode('utf-8') + lastNetworkMsg = networkMsg + client.send(login_packet) while running: + if lastNetworkMsg != networkMsg:#handle + print('get new msg: ',networkMsg) + lastNetworkMsg = networkMsg #networkMsg中保存当前字典 + if 'status' in networkMsg.keys(): + if networkMsg['status'] == 1: + print('Waiting for another player to connect') + + + elif 'src' and 'dst' in networkMsg.keys(): + if other_joined == False: + other_joined = True + print('Game start 2 play!') + else: + theMove = backend.Move([networkMsg['src']['x'],networkMsg['src']['y']],[networkMsg['dst']['x'],networkMsg['dst']['y']],game_state.board) + game_state.makeMove(theMove) + game_state.exchange() + for e in pg.event.get(): #接下来处理游戏中的事件 if e.type == pg.QUIT: @@ -358,24 +406,23 @@ def main(mode,p1,p2,network = None): #? 但是考虑到ui刷新问题,故仍尝试在main中写 #ShowGameState(screen,game_state,valid_moves,square_selected) if mademove: - mademove = False - game_state.updateEnemy()#思路变成:定时对敌方进行扫描,若收到更新相关包则进行局面更新。 + mademove = False + #思路变成:定时对敌方进行扫描,若收到更新相关包则进行局面更新。 + ShowGameState(screen,game_state,valid_moves,square_selected) if game_state.conquer(): showGameOverText(screen,"player "+game_state.win_person+" wins") game_over = True - clock.tick(60) + clock.tick(10) pg.display.flip() if __name__ == '__main__': print("Loading...") print("Initialing game...") - mode = MainMenu() - player1='player1' - network = None #前后端通信接口 - player2='player2' - main(mode,player1,player2,network) + #mode = MainMenu() + mode = 2 + main(mode) \ No newline at end of file diff --git a/SafariChess_backend.py b/SafariChess_backend.py index 33e2394..bcc9fbf 100644 --- a/SafariChess_backend.py +++ b/SafariChess_backend.py @@ -4,74 +4,134 @@ import requests import sys import json from threading import Thread +from queue import Queue #multithreading? + + +class Move: + def __init__(self,start_loc,end_loc,board): + self.start_row = start_loc[0] + self.start_col = start_loc[1] + self.end_row = end_loc[0] + self.end_col = end_loc[1] + self.nxt_piece = board[self.end_row][self.end_col] + self.cur_piece = board[self.start_row][self.start_col] + self.attack = self.nxt_piece != '00' + self.moveID = self.start_row + self.start_col*10 + self.end_row *100 +self.end_col * 1000 #Hash + def __eq__(self, __o: object) -> bool: + if isinstance(__o, Move): + return self.moveID == __o.moveID + return False def startNewThread(target): thread = Thread(target=target) thread.daemon = True thread.start() class Network: - def __init__(self): + def __init__(self,isNet=False): #注意:这里是否在传引用? self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server = "127.0.0.1" self.port = 50005 self.addr = (self.server, self.port) - self.msg = self.connect() - + #self.game_state = game_state #考虑将game_state接入Network以方便修改 + global msg_from_serv + thread = Thread(target = self.receive())#开线程始终监听 + thread.setDaemon(True) + thread.start() #专用数据接收线程 + + def getPos(self): return self.pos - + def connect(self): try: self.client.connect(self.addr) #return self.client.recv(2048).decode() except: pass - + def send(self, msg): try: packet = json.dumps(msg) if (sys.version[:1] == '3'): packet = packet.encode('utf-8') - #return self.client.recv(2048).encode() self.client.send(packet) print("send complete") + return self.client.recv(2048).encode() except socket.error as e: print(e) + return e def post(self, data): #using requests lib, data is json headers = {'Content-Type': 'application/json'} response = requests.post(url='http://localhost',data=data) return response - def receive(self): + def receive(self): #写成持续监听模式 try: - recvMsg = self.client.recv(2048).decode('utf-8') - msg = json.loads(recvMsg) - print('receiver got: ', msg) - return msg + while True: + recvMsg = self.client.recv(2048).decode('utf-8') + if len(recvMsg) != 0: + msg_from_serv = json.loads(recvMsg) + self.dataDealer(msg_from_serv) except socket.error as e: print(e) return e + + def dataDealer(self, msg_json): #根据相关数据对棋盘状态进行更新 + if 'status' in msg_json.keys(): + #处理相关特殊情况 + if msg_json['status'] == '1': + print('Waiting 4 the other player...') + + + elif 'src' and 'dst' in msg_json.keys(): #侦测到移动 + theMove = Move([msg_json['src']['x'],msg_json['src']['y']],[msg_json['dst']['x'],msg_json['dst']['y']],self.game_state.board) + self.game_state.makeMove(theMove,toUpload = False) + self.game_state.exchange() + + + def dataReceiver(self): + try: + while True: + msg = self.client.recv(2048).decode('utf-8') + if len(msg) != 0: self.dataDealer(json.loads(msg)) + + except socket.error as e: + print(e) + return e + + def tell_move(self, move: Move): + thisMove = { + 'type': 1, + 'msg':{ + "game_id": self.game_id, + "side": int(self.red_to_move), + "chessman": move.cur_piece, + "src": { + "x": move.start_row, + "y": move.start_col + }, + "dst": { + "x": move.end_row, + "y": move.end_col + } + } + } + self.client.send(thisMove) + + def login(self,myName): + myPlayerData = { + 'type': 0, # game state type ? + 'msg': { + 'name': myName + } + } + self.client.send(myPlayerData) +class GameState: -class Move: - def __init__(self,start_loc,end_loc,board): - self.start_row = start_loc[0] - self.start_col = start_loc[1] - self.end_row = end_loc[0] - self.end_col = end_loc[1] - self.nxt_piece = board[self.end_row][self.end_col] - self.cur_piece = board[self.start_row][self.start_col] - self.attack = self.nxt_piece != '00' - self.moveID = self.start_row + self.start_col*10 + self.end_row *100 +self.end_col * 1000 #Hash - def __eq__(self, __o: object) -> bool: - if isinstance(__o, Move): - return self.moveID == __o.moveID - return False -class GameState: - def __init__(self, isNet = False, MySide = True, - game_id = None, client:Network = None ): + def __init__(self): ''' 有关信息: 1. 棋盘尺寸为7*9(横向) @@ -107,51 +167,17 @@ class GameState: self.blue_pieces=[7,6,5,4,3,2,1] self.red_pieces=[7,6,5,4,3,2,1] #红方(右)先行 - self.isNet = isNet - self.game_id = game_id - self.red_to_move=MySide - self.MySide = MySide - self.client = client + self.red_to_move=True self.conquered=False self.win_person='' self.MASSACRE=False + self.isStarted = False def color(self): return 'r' if self.red_to_move else 'b' def exchange(self): - self.red_to_move = not self.red_to_move - #网络版相关组件 - def upldmv_server(self,move): - thisMove = { - 'type': 1, - 'msg':{ - "game_id": self.game_id, - "side": int(self.red_to_move), - "chessman": move.cur_piece, - "src": { - "x": move.start_row, - "y": move.start_col - }, - "dst": { - "x": move.end_row, - "y": move.end_col - } - } - } - self.client.send(thisMove) - def __updateOther__(self):#! 注意:考虑使用多线程执行该函数。 - #print('waiting 4 other player 2 act...') - thisMovejson = self.client.receive() - if not thisMovejson or thisMovejson['side'] == int(self.MySide): - return - print('passing checkpoint') - if 'chessman' in thisMovejson.keys(): #正常移动过程 - thisMove = Move([thisMovejson['src']['x'],thisMovejson['src']['y']],[thisMovejson['dst']['x'],thisMovejson['dst']['y']],self.board) - self.makeMove(thisMove,toUpload=False) - self.exchange() - - def updateEnemy(self): - startNewThread(self.__updateOther__)#测试多线程更新…… + self.red_to_move = not self.red_to_move + # 判断特殊位置 def inHome(self,row,col,color): if color=="b": @@ -347,7 +373,7 @@ class GameState: return self.conquered #移动操作 - def makeMove(self,move,toUpload = True):#cur是当前位置,nxt是下一个位置,参数传入为元组 + def makeMove(self,move):#cur是当前位置,nxt是下一个位置,参数传入为元组 # makeMove假设这个move一定是合法的 # 为什么添加toUpload?防止使用makeMove更新己方棋盘时,把敌方棋盘错误上传,导致“棋子消失”。 if self.board[move.end_row][move.end_col] != '00': @@ -360,8 +386,5 @@ class GameState: self.board[move.start_row][move.start_col] = '00' self.red_to_move = not self.red_to_move #由于使用多线程,考虑让另一个线程去更新red_to_move - if self.isNet and toUpload: - #因为界面更新在main中,考虑在main中执行相关指令。 - self.upldmv_server(move) diff --git a/__pycache__/SafariChess_Classes.cpython-39.pyc b/__pycache__/SafariChess_Classes.cpython-39.pyc index fc2a4cd..741f421 100644 Binary files a/__pycache__/SafariChess_Classes.cpython-39.pyc and b/__pycache__/SafariChess_Classes.cpython-39.pyc differ diff --git a/__pycache__/SafariChess_backend.cpython-39.pyc b/__pycache__/SafariChess_backend.cpython-39.pyc index 699ae39..88bb442 100644 Binary files a/__pycache__/SafariChess_backend.cpython-39.pyc and b/__pycache__/SafariChess_backend.cpython-39.pyc differ