You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
SafariChess/SafariChess_backend.py

345 lines
16 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import socket
import requests
import sys
import json
class Network:
def __init__(self):
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()
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)
except socket.error as e:
print(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):
try:
msg = json.loads(self.client.recv(2048))
print(msg)
return msg
except socket.error as e:
print(e)
return e
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 ):
'''
有关信息:
1. 棋盘尺寸为7*9横向
2. 按照以下命名格式对棋盘中的棋子进行标注:
(b|r)(1|2|3|4|5|6|7)
3. 左方为蓝方对应的网络服务器中的side项目编号为0
右方为红方对应的网络服务器中的side项目编号为1
4. 网络版需要额外的类变量type, game_id, side, chessman(piece), src, dst
'''
self.board = [
['00','00','b7','00','00','00','r1','00','00'],
['00','b2','00','00','00','00','00','r3','00'],
['00','00','b4','00','00','00','r5','00','00'],
['00','00','b6','00','00','00','r6','00','00'],
['00','00','b5','00','00','00','r4','00','00'],
['00','b3','00','00','00','00','00','r2','00'],
['00','00','b1','00','00','00','r7','00','00'],
]
#用数字1-7代替棋子的强弱关系
self.moveFunctions = {
"1": self.getMseMoves,
"2": self.getEagMoves,
"3": self.getFoxMoves,
"4": self.getStdMoves,
"5": self.getStdMoves,
"6": self.getLionMoves,
"7": self.getStdMoves,
}
self.blue_trap_loc=[(2,0),(3,1),(4,0)]
self.red_trap_loc=[(3,7),(2,8),(4,8)]
self.blue_home=(3,0)
self.red_home=(3,8)
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.client = client
self.conquered=False
self.win_person=''
self.MASSACRE=False
def color(self):
return 'r' if self.red_to_move else 'b'
#网络版相关组件
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 dnldmv_server(self):
thisMovejson = self.client.receive()
thisMove = Move([thisMovejson['src']['x'],thisMovejson['src']['y']],[thisMovejson['dst']['x'],thisMovejson['dst']['y']],self.board)
return thisMove
# 判断特殊位置
def inHome(self,row,col,color):
if color=="b":
if (row,col)==self.blue_home:
return True
else:
if (row,col)==self.red_home:
return True
return False
def inWater(self,row,col):
if row in [1,2,4,5]:
if col in [3,4,5]:
return True
return False
def inTrap(self,row,col,color): #是否在color方的陷阱中
if color=="b":
if (row,col) in self.blue_trap_loc:
return True
else:
if (row,col) in self.red_trap_loc:
return True
return False
def Eliminate(self,row,col,nxt_row,nxt_col):#下一步可吃对手的棋
next_blank = self.board[nxt_row][nxt_col] == '00'
attack = self.board[nxt_row][nxt_col][0] != self.board[row][col][0] and (eval(self.board[row][col][1]) >= eval(self.board[nxt_row][nxt_col][1]) and not (eval(self.board[row][col][1]) == 7 and eval(self.board[nxt_row][nxt_col][1]) == 1 ) or eval(self.board[row][col][1])==1 and eval(self.board[nxt_row][nxt_col][1])==7)
other_in_trap = self.board[row][col][0] != self.board[nxt_row][nxt_col][0] and (self.board[nxt_row][nxt_col][0] == 'r' and self.inTrap(nxt_row,nxt_col,'b') or self.board[nxt_row][nxt_col][0] == 'b' and self.inTrap(nxt_row,nxt_col,'r'))
return next_blank or attack or other_in_trap
# 定义移动方式
#----------------------------------
# 以下为移动方式的相关规定:
# 1.下一步的可行位置以二维数组的格式进行记录。
# 2.getValidMoves返回值为下一步可行位置构成的集合。
#----------------------------------
def getAllMoves(self): #全部合法移动的集合
moves=[]
for row in range(len(self.board)):
for col in range(len(self.board[row])):
player = self.board[row][col][0]
if (player == 'r' and self.red_to_move or player == 'b' and not self.red_to_move):
self.moveFunctions[self.board[row][col][1]](row,col,moves)
return moves
def getStdMoves(self,row,col,moves):#输入当前的位置将可行路径输出给moves
directions = [(1,0),(0,1),(-1,0),(0,-1)]
enemy_color = 'b' if self.red_to_move else 'r'
for direction in directions:
new_row = row + direction[0]*1
new_col = col + direction[1]*1
if 0<=new_row<=6 and 0<=new_col<=8 :
nxt_piece = self.board[new_row][new_col]
if nxt_piece == '00' and not self.inWater(new_row,new_col) and not self.inHome(new_row,new_col,self.color()):#如果下一个位置是空的,则可以移动
moves.append(Move((row,col),(new_row,new_col),self.board))
elif nxt_piece[0]==enemy_color and not self.inWater(new_row,new_col) and not self.inHome(new_row,new_col,self.color()) and self.Eliminate(row,col,new_row,new_col):#如果是敌方棋子,且不在水里,且可以消除,则添加到可行路径中
moves.append(Move((row,col),(new_row,new_col),self.board))
return moves
def getMseMoves(self,row,col,moves):
directions = [(1,0),(0,1),(-1,0),(0,-1)]
enemy_color = 'b' if self.red_to_move else 'r'
for direction in directions:
new_row = row + direction[0]*1
new_col = col + direction[1]*1
if 0<=new_row<=6 and 0<=new_col<=8 :
nxt_piece = self.board[new_row][new_col]
if self.inHome(new_row,new_col,self.color()): continue
if nxt_piece == '00':
moves.append(Move((row,col),(new_row,new_col),self.board))
elif nxt_piece[0]==enemy_color and self.Eliminate(row,col,new_row,new_col) and not self.inWater(row,col):
moves.append(Move((row,col),(new_row,new_col),self.board))
return moves
def getEagMoves(self,row,col,moves):
#可能存在一些问题,主要是移动方式的判断以及在陷阱的判断
enemy_color = 'b' if self.red_to_move else 'r'
new_row = row
new_col = col
#U&D direction
while new_row >= 0:
nxt_piece = self.board[new_row][col]
if nxt_piece == '00' and not self.inTrap(new_row,col,enemy_color):
if not self.inHome(new_row,col,self.color()) and not self.inWater(new_row,col): moves.append(Move((row,col),(new_row,col),self.board))
else:
if self.Eliminate(row,col,new_row,col): moves.append(Move((row,col),(new_row,col),self.board))
if new_row != row: break
new_row -= 1
new_row = row
while new_row <= 6:
nxt_piece = self.board[new_row][col]
if nxt_piece == '00' and not self.inTrap(new_row,new_col,enemy_color):
if not self.inHome(new_row,col,self.color()) and not self.inWater(new_row,col): moves.append(Move((row,col),(new_row,col),self.board))
else:
if self.Eliminate(row,col,new_row,col): moves.append(Move((row,col),(new_row,col),self.board))
if new_row != row: break
new_row += 1
#L&R Direction
while new_col >= 0:
nxt_piece = self.board[row][new_col]
if nxt_piece == '00' and not self.inTrap(row,new_col,enemy_color):
if not self.inHome(row,new_col,self.color()) and not self.inWater(row,new_col): moves.append(Move((row,col),(row,new_col),self.board))
else:
if self.Eliminate(row,col,row,new_col): moves.append(Move((row,col),(row,new_col),self.board))
if new_col != col: break
new_col -= 1
new_col = col
while new_col <= 8:
nxt_piece = self.board[row][new_col]
if nxt_piece == '00' and not self.inTrap(row,new_col,enemy_color):
if not self.inHome(row,new_col,self.color()) and not self.inWater(row,new_col): moves.append(Move((row,col),(row,new_col),self.board))
else:
if self.Eliminate(row,col,row,new_col): moves.append(Move((row,col),(row,new_col),self.board))
if new_col != col: break
new_col += 1
return moves
def getFoxMoves(self,row,col,moves):
directions = [(1,0),(0,1),(-1,0),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)]
enemy_color = 'b' if self.red_to_move else 'r'
for direction in directions:
new_row = row + direction[0]*1
new_col = col + direction[1]*1
if 0<=new_row<=6 and 0<=new_col<=8 :
nxt_piece = self.board[new_row][new_col]
if nxt_piece == '00' and not self.inWater(new_row,new_col) and not self.inHome(new_row,new_col,self.color()):#如果下一个位置是空的,则可以移动
moves.append(Move((row,col),(new_row,new_col),self.board))
elif nxt_piece[0]==enemy_color and not self.inWater(new_row,new_col) and not self.inHome(new_row,new_col,self.color()) and self.Eliminate(row,col,new_row,new_col):#如果是敌方棋子,且不在水里,且可以消除,则添加到可行路径中
moves.append(Move((row,col),(new_row,new_col),self.board))
return moves
def getLionMoves(self,row,col,moves):
directions = [(1,0),(0,1),(-1,0),(0,-1)]
enemy_color = 'b' if self.red_to_move else 'r'
for direction in directions:
new_row = row + direction[0]*1
new_col = col + direction[1]*1
if 0<=new_row<=6 and 0<=new_col<=8 :
nxt_piece = self.board[new_row][new_col]
if nxt_piece == '00' and not self.inWater(new_row,new_col) and not self.inHome(new_row,new_col,self.color()):#如果下一个位置是空的,则可以移动
moves.append(Move((row,col),(new_row,new_col),self.board))
elif nxt_piece[0]==enemy_color and not self.inWater(new_row,new_col) and not self.inHome(new_row,new_col,self.color()) and self.Eliminate(row,col,new_row,new_col):#如果是敌方棋子,且不在水里,且可以消除,则添加到可行路径中
moves.append(Move((row,col),(new_row,new_col),self.board))
jump_vert_loc=[(0,3),(0,4),(0,5),(3,3),(3,4),(3,5),(6,3),(6,4),(6,5)]
jump_hori_loc=[(1,2),(1,6),(2,2),(2,6),(4,2),(4,6),(5,2),(5,6)]
enemy_mouse = enemy_color + '1'
if (row,col) in jump_vert_loc:
if row == 0:
if self.board[1][col] != enemy_mouse and self.board[2][col] != enemy_mouse:
if self.Eliminate(row,col,3,col): moves.append(Move((row,col),(3,col),self.board))
elif row == 3:
if self.board[1][col] != enemy_mouse and self.board[2][col] != enemy_mouse:
if self.Eliminate(row,col,0,col): moves.append(Move((row,col),(0,col),self.board))
if self.board[4][col] != enemy_mouse and self.board[5][col] != enemy_mouse:
if self.Eliminate(row,col,6,col): moves.append(Move((row,col),(6,col),self.board))
elif row == 6:
if self.board[4][col] != enemy_mouse and self.board[5][col] != enemy_mouse:
if self.Eliminate(row,col,3,col): moves.append(Move((row,col),(3,col),self.board))
elif (row,col) in jump_hori_loc:
if col == 2:
lea = True
for i in range(3,6):
if self.board[row][i] == enemy_mouse: lea = False
if lea and self.Eliminate(row,col,row,6): moves.append(Move((row,col),(row,6),self.board))
elif col == 6:
lea = True
for i in range(3,6):
if self.board[row][i] == enemy_mouse: lea = False
if lea and self.Eliminate(row,col,row,2): moves.append(Move((row,col),(row,2),self.board))
return moves
# 判断是否胜利
def conquer(self):
if self.board[3][0][0] == 'r' or self.board[3][8][0] == 'b':
self.conquered = True
if self.board[3][0][0] == 'r':
self.win_person = 'r'
else: self.win_person = 'b'
elif len(self.blue_pieces) == 0:
self.conquered = True
self.win_person = 'r'
elif len(self.red_pieces) == 0:
self.conquered = True
self.win_person = 'b'
elif len(self.getAllMoves()) == 0:
self.conquered = True
self.win_person = 'r' if self.color() == 'b' else 'b'
return self.conquered
#移动操作
def makeMove(self,move):#cur是当前位置nxt是下一个位置,参数传入为元组
# makeMove假设这个move一定是合法的
if self.board[move.end_row][move.end_col] != '00':
nxt_piece = self.board[move.end_row][move.end_col]
if nxt_piece[0] == 'r':
self.red_pieces.remove(int(nxt_piece[1]))
else:
self.blue_pieces.remove(int(nxt_piece[1]))
self.board[move.end_row][move.end_col] = self.board[move.start_row][move.start_col]
self.board[move.start_row][move.start_col] = '00'
if not self.isNet: self.red_to_move = not self.red_to_move
else:
#直接在这里完成两步实现看起来不可行……
#因为界面更新在main中
self.upldmv_server(move)