ガイスターアプリ開発(6) 勝敗判定

Python でつくるガイスター、連載第 6 回です。

は駒の移動と手番の交代を実装しました。

今回は勝敗の判定と表示をしていきます。


勝敗判定

勝敗の条件を関数で定義します。

game.py
1
...
2
def win_req(taken, board, side, moved):
3
'''
4
side が勝利条件を満たすか
5
-> bool
6
7
taken : list <- [{'R': int, 'B': int}]
8
取った駒
9
board : dict <- {(int, int): Piece}
10
ゲームボード
11
side : int <- 0 | 1
12
先攻(0), 後攻(1)
13
moved : bool
14
side が今駒を動かしたか
15
'''
16
assert side == 0 or side == 1, 'game.win_req の引数 side は 0, 1 の値を取ります'
17
if not moved:
18
# 赤を4つ取らせた
19
if taken[(side+1)%2]['R'] == 4:
20
return True
21
else:
22
# 青を4つ取った
23
if taken[side]['B'] == 4:
24
return True
25
# 青が盤外に出た
26
if side == 0 and ((0, -1) in board or (5, -1) in board):
27
return True
28
if side == 1 and ((0, 6) in board or (5, 6) in board):
29
return True
30
...
31
def main(screen, font, font_small, orders, move_snd, chturn_snd):
32
...
33
# 取った駒 [{'R': int, 'B': int}]
34
_taken_pieces = [{'R': 0, 'B': 0}, {'R': 0, 'B': 0}]
35
# 勝者
36
# 0 - 先攻, 1 - 後攻
37
_winner = -1
38
...

取った駒の色とその数を変数_taken_piecesに代入して、引数に渡します。

判定のタイミングは、駒を動かし終わったときにしますので、

マウスイベントの内部です。

game.py
1
...
2
def main(screen, font, font_small, orders, move_snd, chturn_snd, win_snd):
3
...
4
while True:
5
...
6
# イベントハンドリング
7
for event in pygame.event.get():
8
...
9
# マウスクリック
10
if event.type == MOUSEBUTTONDOWN:
11
# 左
12
if event.button == 1:
13
...
14
if _square_pos in _board and _board[_square_pos].side == _turn:
15
# 駒を選択したとき
16
_selecting_pos = _square_pos
17
else:
18
# 行先を選択したとき
19
if (_selecting_pos in _board
20
and _square_pos in _board[_selecting_pos].covering_squares(_selecting_pos)):
21
# 行先が相手の駒のとき
22
if _square_pos in _board and _board[_square_pos].side != _turn:
23
_taken_pieces[_turn][_board[_square_pos].color] += 1
24
# 駒の移動
25
move_snd.play()
26
_board[_square_pos] = _board[_selecting_pos]
27
del _board[_selecting_pos]
28
# 移動完了
29
_move_finished = True
30
# 勝利判定
31
if win_req(_taken_pieces, _board, _turn, True):
32
win_snd.play()
33
_winner = _turn
34
if win_req(_taken_pieces, _board, (_turn+1)%2, False):
35
win_snd.play()
36
_winner = (_turn+1)%2
37
_selecting_pos = None
38
...

自分が駒を動かした瞬間に相手が勝つ場合(相手の悪いおばけをすべて取ったとき)もあるので、

条件分岐は2つになっています。


画面に勝者を表示

次に勝敗が決まったときに画面に結果を表示します。

表示するものを関数で定義します。

draw.py
1
...
2
def win_message(screen, font, side):
3
'''
4
勝敗の結果を知らせるメッセージを表示する
5
6
screen : pygame.display.set_mode
7
font : pygame.font.SysFont
8
フォント
9
side : int <- 0 | 1
10
'''
11
assert side == 0 or side == 1, 'draw.win_message の引数 side は 0, 1 の値を取ります'
12
_str = ('先' if side == 0 else '後') + '攻の勝ち!'
13
_text = font.render(_str, True, BLACK)
14
_margin = (DISP_SIZE-(3*SQUARE_SIZE, SQUARE_SIZE))/2
15
screen.fill(WHITE, (*_margin, 3*SQUARE_SIZE, SQUARE_SIZE))
16
screen.blit(_text, DISP_SIZE/2-(len(_str)*32/2, 32/2))
17
...

勝者が決まったときにこれを描画します。

さらに、その画面でスペースキーを押すと隠れていたすべての駒の色を表示するようにします。

game.py
1
...
2
def main(screen, font, font_small, orders, move_snd, chturn_snd, win_snd):
3
...
4
while True:
5
...
6
# 盤面
7
draw.board(screen, _board, _turn)
8
...
9
# 勝敗
10
if _winner == 0 or _winner == 1:
11
draw.win_message(screen, font, _winner)
12
...
13
# イベントハンドリング
14
for event in pygame.event.get():
15
...
16
# キー
17
if event.type == KEYDOWN:
18
...
19
# Space キー
20
if event.key == K_SPACE:
21
if _winner >= 0:
22
# 開示
23
_winner = 2
24
_turn = 2
25
...

_winner = 2は勝敗の表示を消すため、

_turn = 2はすべての駒を開示するためのものです。

draw.boardの第三引数に2を指定すると


これでガイスターが遊べるようになりました!

コードは GitHub からどうぞ。

読んでくれてありがとうございました。

では👋