点击查看象棋小游戏系列目录导航
流程图依旧需要:
吃子的条件是啥呢?
1、当前自己的棋子有被选中(select_chess 不为空)·
2、鼠标点击了对方的棋子
3、按照吃子规则,对方的棋子可吃
4、按照吃子规则,对方的棋子在位置上可以被吃。
比如说,车只能吃与它相邻的上下左右的对方棋子,不能吃斜角或其它位置的棋子,这就是位置上可以被吃。
if event.type == MOUSEBUTTONDOWN:
if event.button == 1:# 按下鼠标左键
#print(event.pos)
selected = is_chess_clicked(chess_list,event)
#print(selected)
if selected is not None:
# 本次点击点击到了棋子
if selected.state == ChessPieces.CHOOSED_STATE:
pass
elif selected.state == ChessPieces.ACTIVE_STATE:
if player_role == selected.role:
# 当前用户点击自己的棋子
# 重复点击了多次自己的某一个棋子
# 或例子:
# 先点击了自己的车,又点击了自己的马
select_chess = selected
selected.state = ChessPieces.ACTIVE_STATE
else:
# 当前用户点击别人的棋子
# 选定自己要吃的对方的子
if select_chess is not None:
# 判断是否可以吃该子
if select_chess.eat(selected,event.pos,chess_list):
select_chess = None
# ‘将’ 可以吃 其它所有
# 是否可吃需要满足两个条件
# 1、是否满足该子的行走规律
# 2、是否满足该子的吃子规律
def eat(self,enemy_chess,pos,chess_list):
if can_eat(self.type,enemy_chess.type):
# 吃子规则判断可吃
if self.move(pos):
# 将select_chess 移动到选定位置
# 并将被吃子状态修改为死亡状态
self.rect.left = enemy_chess.rect.left
self.rect.top = enemy_chess.rect.top
enemy_chess.state = DEAD_STATE
return True
else:
print('点击位置不在范围内,无法吃子')
return False
# 吃子规则
# 这个规则我们可以自己随便写
# 我的规则是 值大的可以吃值小的 兵可以吃将,炮可以吃全部,不过炮翻山才可以吃
JIANG_TYPE = 11
SHI_TYPE = 12
XIANG_TYPE = 13
CHE_TYPE = 14
MA_TYPE = 15
PAO_TYPE = 16
ZU_TYPE = 17
def can_eat(typea,typeb):
if typea in (JIANG_TYPE,PAO_TYPE):
return True
elif typea in (SHI_TYPE,XIANG_TYPE,MA_TYPE,CHE_TYPE):
if typea <= typeb:
return True
elif typea == ZU_TYPE:
if typeb == JIANG_TYPE or typeb == ZU_TYPE:
return True
return False
那我们有不同的吃子的方法,那我们就可以修改它对应的 move 方法,比如说 ‘炮’、
def eat(self,enemy_chess,pos,chess_list):
if can_eat(self.type,enemy_chess.type):
if self.can_move_and_eat(enemy_chess,pos,chess_list):
self.rect.left = enemy_chess.rect.left
self.rect.top = enemy_chess.rect.top
enemy_chess.state = DEAD_STATE
enemy_chess.rect.left = -100
enemy_chess.rect.top = -100
return True
else:
print('点击位置不在范围内,无法吃子')
return False
def can_move_and_eat(self,enemy_chess,pos,chess_list):
# 首先判断,pos 和当前棋子是否在同一行或同一列
# 然后判断,两个棋子之间有几个棋子
if self.rect.left -10 < enemy_chess.rect.left < self.rect.left + 50:
# 说明在同一列
count = 0
for each in chess_list:
if self.rect.left -10 < each.rect.left < self.rect.left + 50 \
and min(self.rect.center[1],enemy_chess.rect.center[1]) < \
each.rect.center[1] < max(self.rect.center[1],enemy_chess.rect.center[1]):
count+=1
if count==1:
return True
elif self.rect.top -10 < enemy_chess.rect.top < self.rect.top +50:
# 说明在同一行
count = 0
for each in chess_list:
if self.rect.top -10 < each.rect.top < self.rect.top +50 and \
min(self.rect.center[0], enemy_chess.rect.center[0]) < \
each.rect.center[0] < max(self.rect.center[0], enemy_chess.rect.center[0]):
count += 1
if count==1:
return True
return False
验证横坐标在 x 范围内,纵坐标在 y 范围内,并且棋子状态为 Active 的棋子个数,如果只有一个,那就构成炮翻山的条件,否则无法吃子。
添加判赢机制
那么,怎么样才算赢呢?当棋盘上某方的状态为 active 的棋子为 0 的时候,就有一方获胜了。
# 判断游戏是否结束
# 方法,计算棋盘上存活的棋子数量,如果为零就,停止
black_count = 0
red_count = 0
for each in chess_list:
# 这个地方
if each.state == ChessPieces.ACTIVE_STATE or each.state == ChessPieces.HIDDEN_STATE:
if each.role == ChessPieces.BLACK_ROLE:
black_count +=1
else:
red_count+=1
if black_count == 0:
# 红方胜利
draw_text('红方胜利!',RED,(width//2,height//2))
elif red_count ==0:
# 黑方胜利
draw_text('黑方胜利',BLACK,(width//2,height//2))