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.

328 lines
12 KiB

import pygame
from Managed.ChessModel import Chess,ChessColor,,,,,,,
import json
from Managed.Window import Dict_to_Abs_posi
from Managed.Mixer import Mixer
game_init_path = "./save/__init__.json"
game_save_path = "./save/save00.json"
game_load_path = "./save/save00.json"
class Container:
chess_board:dict[(int,int),Chess] = {}
selected_chess:Chess = None
RED_checkmate:Chess = None
BLACK_checkmate:Chess = None
checkmated_Team:ChessColor = None
mixer:Mixer = None
action_team_save:ChessColor = None
tip_count = 0
def __init__(self):
self.chess_sprite_group = pygame.sprite.Group()
self.load_chess_board()
self.initChessBoard()
def setMixer(self,mixer):
self.mixer = mixer
def initChessBoard(self):
"""初始化棋子图片,记录将帅位置
"""
for posi,chess in self.chess_board.items():
chess.init(posi)
self.chess_sprite_group.add(chess)
if isinstance(chess,):
if chess.color == ChessColor.RED:
self.RED_checkmate = chess
elif chess.color == ChessColor.BLACK:
self.BLACK_checkmate = chess
print("初始化棋子")
def check_and_drop_chess(self,abs_posi):
"""对当前选中的棋子落点碰撞检测,点中落点后会删除选中棋子的引用
Args:
abs_posi (tuple): 鼠标位置
Return:
True: 成功落子时返回True,并删除Container的selected_chess引用;遍历完落点数组时也会返回True
False: 自杀或应将失败都会返回False
"""
abs_x,abs_y = abs_posi
for dict_posi,drop_sprite in self.selected_chess.drop_point_dict.items():
if drop_sprite.rect.collidepoint(abs_x,abs_y):
# x,y = dict_posi
eat_flag = False
#region 应将和防自杀判定
if self.checkmated_Team: #被将军时判定是否能应将
if self.Guard(self.selected_chess,dict_posi,self.selected_chess.color):
self.tip_count =0
del self.checkmated_Team
else:
self.mixer.play("提示音")
self.tip_count+=1
if self.tip_count<6:
return False
elif not self.Guard(self.selected_chess,dict_posi,self.selected_chess.color):#判定是否为自杀
self.mixer.play("提示音")
self.tip_count+=1
if self.tip_count<6:
return False
#endregion
self.mixer.play("落子声")
if self.chess_board.__contains__(dict_posi):
eat_flag = True
chess_destroyed = self.chess_board[dict_posi]
self.updateChess(chess_destroyed,(-10,-10))
chess_destroyed.move((-10,-10))
#print(f"棋子{chess_destroyed.__class__.__name__}被吃掉了")
if chess_destroyed is self.BLACK_checkmate:
self.BLACK_checkmate = None
self.mixer.play("绝杀声")
elif chess_destroyed is self.RED_checkmate:
self.RED_checkmate = None
self.mixer.play("绝杀声")
else:
self.mixer.play("吃子声")
self.updateChess(self.selected_chess,dict_posi)
self.selected_chess.move(dict_posi)
if self.checkmate(self.selected_chess):
if self.selected_chess.color == ChessColor.BLACK:
self.checkmated_Team = ChessColor.RED
self.mixer.play("将军")
else:
self.checkmated_Team = ChessColor.BLACK
self.mixer.play("checkmate")
elif eat_flag:
self.mixer.play("吃子声")
del self.selected_chess.drop_point_dict
#print(f"棋子{self.selected_chess.__class__.__name__}落到{x}_{y}")
del self.selected_chess.drop_sprite_group
del self.selected_chess
return True
return True
def check_and_select_chess(self,posi,action_team):
"""对棋盘所有棋子碰撞检测,点中行动方的棋子的话,会为Container添加selected_chess引用
Args:
posi (_type_): 鼠标位置
action_team (_type_): 当前行动方
Returns:
True: 选中当前队伍的棋子,并为Container添加selected_chess引用
False: 没有选中当前队伍的棋子
"""
x,y =posi
for dict_posi,chess in self.chess_board.items():
dict_x,dict_y = dict_posi
if chess.rect.collidepoint(x,y):
#print(f"现在碰撞的棋子是{chess.__class__.__name__},阵营是{chess.color},正在行动的阵营是{action_team},两者是否相等:{chess.color.value == action_team.value}")
if not chess.color.value == action_team.value:
continue
if not self.selected_chess == None:
del self.selected_chess.drop_sprite_group
del self.selected_chess
#print(f"点击到棋子{chess.__class__.__name__}:({dict_x},{dict_y})")
self.selected_chess = chess
chess.onSelected(self.chess_board,self.BLACK_checkmate,self.RED_checkmate,to_checkmate = False)
return True
return False
def checkmate(self,chess:Chess):
"""判断是否将军
Args:
chess (Chess): 可能导致对方将军的棋子
Returns:
True: 能使对面将军
False: 不能使对方将军
"""
target = (self.RED_checkmate if chess.color == ChessColor.BLACK else self.BLACK_checkmate)
pre_drops = chess.onSelected(self.chess_board,self.BLACK_checkmate,self.RED_checkmate,to_checkmate = True)
for pre_drop in pre_drops:
if self.chess_board.__contains__(pre_drop) and self.chess_board[pre_drop] is target:
return True
return False
def Guard(self,chess:Chess,pre_drop,guard_team):
"""在被将军的情况下,本次行动能否应将
Args:
chess (Chess): 本次行动的棋子
pre_drop (_type_): 棋子的落点
guard_team (_type_): 防守方
Returns:
True: 落点能够应将
False: 落点不能应将
"""
result = True
ori_posi = chess.x,chess.y
destroyed_spawn = self.chess_board.__contains__(pre_drop)
temp_chess_destroyed = None
if destroyed_spawn:
temp_chess_destroyed = self.chess_board[pre_drop]
self.chess_board.pop(pre_drop)
temp_chess_destroyed.move((-10,-10))
self.updateChess(chess,pre_drop)
for _,enemy in self.chess_board.items():
if not enemy.color == guard_team:
if self.checkmate(enemy):
result = False
break
if self.chess_board.__contains__(pre_drop):
self.chess_board.pop(pre_drop)
self.chess_board[ori_posi] = chess
if destroyed_spawn:
temp_chess_destroyed.move(pre_drop)
self.updateChess(temp_chess_destroyed,pre_drop)
return result
def update_abs_posi(self):
"""更新所有棋子的屏幕坐标
"""
for posi,chess in self.chess_board.items():
abs_posi = Dict_to_Abs_posi(posi)
chess.rect.center = abs_posi
def updateChess(self,chess:Chess,new_posi):
"""更新棋盘字典
Args:
chess (Chess): 棋子对象
new_posi (tuple): 新的逻辑坐标
"""
old_posi = (chess.x,chess.y)
if self.chess_board.__contains__(old_posi):
self.chess_board.pop(old_posi)
self.chess_board[new_posi] = chess
def deleteChess(self,posi):
"""删除字典中的棋子(未使用)
Args:
posi (tuple): 棋子逻辑位置
"""
if self.chess_board.__contains__(posi):
chess = self.chess_board[posi]
self.chess_board.pop(posi)
chess.onDestroyed()
def load_chess_board(self,remake = False,filename = game_load_path):
"""从json文件中加载存档
Args:
filename (str, optional): 默认加载save00.json. Defaults to game_load_path.
"""
self.chess_board={}
self.chess_sprite_group.empty()
self.selected_chess = None
if remake:
filename = game_init_path
with open(filename, "r" ,encoding='utf-8') as file:
saved_dict:dict[str,str] = json.load(file)
for saved_key, saved_value in saved_dict.items():
if saved_key == "action_team":
self.action_team_save = ChessColor(int(saved_value))
else:
x,y = map(int, saved_key.split('_'))
class_name,chess_color = saved_value.split('_')
chess_class = globals()[class_name]
self.chess_board[(x,y)] = chess_class(ChessColor(int(chess_color)))
self.initChessBoard()
print(f"导入存档:{filename}")
def save_chess_board(self,action_team=ChessColor.RED,filename = game_save_path):
"""保存存档到json文件
Args:
filename (str, optional): 默认保存到save00. Defaults to game_save_path.
"""
with open(filename, "w",encoding='utf-8') as file:
new_dict = {"action_team":str(action_team.value)}
for key, value in self.chess_board.items():
x,y = key
new_key = f"{x}_{y}"
new_value = f"{value.__class__.__name__}_{value.color.value}"
new_dict[new_key] = new_value
json.dump(new_dict, file,indent=4,ensure_ascii=False)
print(f"保存存档:{filename}")
return True
def initMap(board):
"""自定义棋盘
"""
board:dict[(int,int),Chess] = {}
board[(0, 0)] = (ChessColor.RED)
board[(1, 0)] = (ChessColor.RED)
board[(2, 0)] = (ChessColor.RED)
board[(3, 0)] = (ChessColor.RED)
board[(4, 0)] = (ChessColor.RED)
board[(5, 0)] = (ChessColor.RED)
board[(6, 0)] = (ChessColor.RED)
board[(7, 0)] = (ChessColor.RED)
board[(8, 0)] = (ChessColor.RED)
board[(0, 3)] = (ChessColor.RED)
board[(1, 2)] = (ChessColor.RED)
board[(2, 3)] = (ChessColor.RED)
board[(4, 3)] = (ChessColor.RED)
board[(6, 3)] = (ChessColor.RED)
board[(7, 2)] = (ChessColor.RED)
board[(8, 3)] = (ChessColor.RED)
board[(0, 6)] = (ChessColor.BLACK)
board[(1, 7)] = (ChessColor.BLACK)
board[(2, 6)] = (ChessColor.BLACK)
board[(4, 6)] = (ChessColor.BLACK)
board[(6, 6)] = (ChessColor.BLACK)
board[(7, 7)] = (ChessColor.BLACK)
board[(8, 6)] = (ChessColor.BLACK)
board[(0, 9)] = (ChessColor.BLACK)
board[(1, 9)] = (ChessColor.BLACK)
board[(2, 9)] = (ChessColor.BLACK)
board[(3, 9)] = (ChessColor.BLACK)
board[(4, 9)] = (ChessColor.BLACK)
board[(5, 9)] = (ChessColor.BLACK)
board[(6, 9)] = (ChessColor.BLACK)
board[(7, 9)] = (ChessColor.BLACK)
board[(8, 9)] = (ChessColor.BLACK)
# container.chess_board = board()
# container.initChessBoard()
# container.save_chess_board("./save/__init__.json")
# if __name__ =='__main__':
# #共享单例
# container = Container()
# container.load_chess_board()
# print("导入存档:save00.json")