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

221 lines
10 KiB

3 years ago
class GameState:
def __init__(self):
'''
有关信息
1. 棋盘尺寸为7*9横向
2. 按照以下命名格式对棋盘中的棋子进行标注
(b|r)(1|2|3|4|5|6|7)
3.
'''
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'],
]
3 years ago
#用数字1-7代替棋子的强弱关系
3 years ago
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)
3 years ago
#蓝方(左)先行
self.red_to_move=False
3 years ago
self.conquered=False
self.MASSACRE=False
3 years ago
self.color = 'r' if self.red_to_move else 'b'
3 years ago
# 判断特殊位置
3 years ago
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
3 years ago
def inWater(self,row,col):
if row in [1,2,4,5]:
if col in [3,4,5]:
return True
return False
3 years ago
3 years ago
def inTrap(self,row,col,color):
3 years ago
if color=="b":
3 years ago
if (row,col) in self.blue_trap_loc:
return True
else:
if (row,col) in self.red_trap_loc:
return True
return False
3 years ago
3 years ago
def Eliminate(self,row,col,nxt_row,nxt_col):#下一步可吃对手的棋
return self.board[nxt_row][nxt_col] == '00' or 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)
3 years ago
3 years ago
# 定义移动方式
#----------------------------------
# 以下为移动方式的相关规定:
# 1.下一步的可行位置以二维数组的格式进行记录。
# 2.getValidMoves返回值为下一步可行位置构成的集合。
#----------------------------------
def getAllMoves(self): #全部合法移动的集合
3 years ago
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
3 years ago
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 :
3 years ago
nxt_piece = self.board[new_row][new_col]
3 years ago
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))
3 years ago
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))
3 years ago
return moves
3 years ago
3 years ago
def getMseMoves(self,row,col,moves):
3 years ago
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 :
3 years ago
nxt_piece = self.board[new_row][new_col]
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))
3 years ago
return moves
3 years ago
def getEagMoves(self,row,col,moves):
3 years ago
#可能存在一些问题,主要是移动方式的判断以及在陷阱的判断
enemy_color = 'b' if self.red_to_move else 'r'
moveNum_row = -6
moveNum_col = -8
new_row = row
new_col = col
while(moveNum_row <= 6 ):
new_row = row + moveNum_row
if 0<=new_row<=6:
nxt_piece = self.board[new_row][col]
if nxt_piece == '00':
moves.append(Move((row,col),(new_row,new_col),self.board))
3 years ago
elif nxt_piece[0]==enemy_color and not self.inWater(new_row,col) and not self.inHome(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))
3 years ago
else :
break
moveNum_row += 1
while(moveNum_row <= 8):
new_col = col + moveNum_col
if 0 <= new_col <= 8:
nxt_piece = self.board[row][new_col]
if nxt_piece == '00' and not self.inWater(row,new_col) and not self.inHome(row,new_col,self.color):
moves.append(Move((row,col),(new_row,new_col),self.board))
3 years ago
elif nxt_piece[0]==enemy_color and self.Eliminate(row,col,new_row,new_col):
moves.append(Move((row,col),(new_row,new_col),self.board))
3 years ago
else :
break
moveNum_col += 1
return moves
3 years ago
def getFoxMoves(self,row,col,moves):
3 years ago
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 :
3 years ago
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))
3 years ago
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))
3 years ago
return moves
3 years ago
def getLionMoves(self,row,col,moves):
3 years ago
directions = ((-1, 0), (0, -1), (1, 0), (0, 1))
enemy_color = "b" if self.red_to_move else "r"
for direction in directions:
for i in range(1, 2):
end_row = row + direction[0] * 1
end_col = col + direction[1] * 1
if 0 <= end_row <= 6 and 0 <= end_col <= 8: # check for possible moves only in boundaries of the board
3 years ago
end_piece = self.board[end_row][end_col]
if end_piece == "--" and not self.inWater(end_row,end_col) and self.moveNotOwnDen(end_row,end_col,enemy_color): # empty space is valid and Not in Water
3 years ago
moves.append(Move((row, col), (end_row, end_col), self.board))
3 years ago
elif end_piece == "--" and self.inWater(end_row,end_col):
jump_row = end_row - row #Vertical jump
jump_col = end_col - col #Horizontal jump
if jump_row != 0 and self.jumpConditions(row,col,end_row,end_col,jump_row,jump_col,enemy_color):
3 years ago
moves.append(Move((row, col), (end_row+(3*jump_row), end_col), self.board))
3 years ago
elif jump_col != 0 and self.jumpConditions(row,col,end_row,end_col,jump_row,jump_col,enemy_color):
3 years ago
moves.append((end_row, end_col+(2*jump_col)))
3 years ago
elif end_piece[0] == enemy_color and not self.inWater(end_row,end_col) and self.canAttack(row, col, end_row, end_col): # capture enemy piece
3 years ago
moves.append(Move((row, col), (end_row, end_col), self.board))
3 years ago
break
else: # friendly piece
break
else: # off board
break
3 years ago
# 判断是否胜利
def conquer(self):
if self.board[3][0][0] == 'r' or self.board[3][8][0] == 'b':
self.conquered = True
return self.conquered
#移动操作
def makeMove(self,move):#cur是当前位置nxt是下一个位置,参数传入为元组
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'
self.red_to_move = not self.red_to_move
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