黑白棋 - 又一个pygame小游戏
完善黑白棋
之前简单构建了黑白棋框架,只是渲染界面,并没有实际黑白棋运行逻辑: 如何反转棋子?
增加翻转棋子的功能
修改make_move函数,判断需要翻转的棋子,加入到list里面,然后设置一个便利flipped
鼠标点击的时候,判断是否flipped,则重新绘制draw_board
增加棋盘上的格子线
使用pygame.color函数定义一些常量
import pygame
import sys
# 游戏参数
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
BOARD_SIZE = 8
CELL_SIZE = SCREEN_HEIGHT // BOARD_SIZE
# 颜色定义
# 颜色定义
BLACK = pygame.Color('black')
WHITE = pygame.Color('white')
BLUE = pygame.Color('blue')
GREEN = pygame.Color('green')
YELLOW = pygame.Color('yellow')
def create_board():
board = [[' ' for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
board[3][44] = 'W'
board[3][45] = 'B'
board[4][46] = 'B'
board[4][47] = 'W'
return board
def draw_board(screen, board, player):
screen.fill(GREEN)
for row in range(BOARD_SIZE):
for col in range(BOARD_SIZE):
pygame.draw.rect(screen, BLUE, (col * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE))
if board[row][col] == 'W':
pygame.draw.circle(screen, WHITE,
(col * CELL_SIZE + CELL_SIZE // 2, row * CELL_SIZE + CELL_SIZE // 2),
CELL_SIZE // 2 - 4)
elif board[row][col] == 'B':
pygame.draw.circle(screen, BLACK,
(col * CELL_SIZE + CELL_SIZE // 2, row * CELL_SIZE + CELL_SIZE // 2),
CELL_SIZE // 2 - 4)
if player == 'W':
pygame.draw.circle(screen, WHITE,
(540, 80),
CELL_SIZE // 2 - 4)
else:
pygame.draw.circle(screen, BLACK,
(540, 80),
CELL_SIZE // 2 - 4)
# 绘制格子线
for i in range(BOARD_SIZE + 1):
pygame.draw.line(screen, YELLOW, (0, i * CELL_SIZE), (SCREEN_WIDTH, i * CELL_SIZE))
pygame.draw.line(screen, YELLOW, (i * CELL_SIZE, 0), (i * CELL_SIZE, SCREEN_HEIGHT))
pygame.display.flip()
def is_valid_move(board, row, col, player):
if board[row][col] != ' ':
return False
other_player = 'B' if player == 'W' else 'W'
directions = [(0, -1), (0, 1), (-1, 0), (1, 0),
(-1, -1), (-1, 1), (1, -1), (1, 1)]
for drow, dcol in directions:
r, c = row, col
r += drow
c += dcol
if (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE) and (board[r][c] == other_player):
r += drow
c += dcol
while (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE):
if board[r][c] == player:
return True
elif board[r][c] == ' ':
break
r += drow
c += dcol
return False
def make_move(board, row, col, player):
if not is_valid_move(board, row, col, player):
return False
other_player = 'B' if player == 'W' else 'W'
board[row][col] = player
directions = [(0, -1), (0, 1), (-1, 0), (1, 0),
(-1, -1), (-1, 1), (1, -1), (1, 1)]
flipped = False
for drow, dcol in directions:
r, c = row, col
r += drow
c += dcol
if (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE) and (board[r][c] == other_player):
flip_list = []
while (0 <= r < BOARD_SIZE) and (0 <= c < BOARD_SIZE):
if board[r][c] == player:
flipped = True
for flip_row, flip_col in flip_list:
board[flip_row][flip_col] = player
break
elif board[r][c] == ' ':
break
else:
flip_list.append((r, c))
r += drow
c += dcol
return flipped
def is_game_over(board):
for row in range(BOARD_SIZE):
for col in range(BOARD_SIZE):
if board[row][col] == ' ':
return False
return True
def count_pieces(board):
black_count = 0
white_count = 0
for row in range(BOARD_SIZE):
for col in range(BOARD_SIZE):
if board[row][col] == 'B':
black_count += 1
elif board[row][col] == 'W':
white_count += 1
return black_count, white_count
def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("黑白棋游戏")
clock = pygame.time.Clock()
board = create_board()
current_player = 'B'
while not is_game_over(board):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
col = mouse_x // CELL_SIZE
row = mouse_y // CELL_SIZE
if make_move(board, row, col, current_player):
current_player = 'W' if current_player == 'B' else 'B'
draw_board(screen, board, current_player)
draw_board(screen, board, current_player)
black_count, white_count = count_pieces(board)
pygame.display.set_caption(f"黑棋: {black_count} 白棋: {white_count}")
pygame.display.flip()
clock.tick(60)
black_count, white_count = count_pieces(board)
pygame.display.set_caption(f"黑棋: {black_count} 白棋: {white_count}")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if __name__ == '__main__':
main()
程序解释
make_move函数解释:
函数的输入参数包括:
• board:当前游戏棋盘的状态,是一个二维列表,表示每个位置上的棋子情况。
• row、col:玩家希望在棋盘上放置棋子的行和列索引。
• player:当前玩家的标识符,可以是'W'(白棋)或'B'(黑棋)。
函数的返回值为布尔值,表示移动是否有效。如果移动有效,会更新棋盘的状态,将当前玩家的棋子放置在指定的位置,并将被翻转的对方棋子也进行翻转。如果移动无效,不会有任何改变。
函数的主要步骤如下:
- 首先检查指定位置是否是有效的落子位置,通过调用is_valid_move函数进行判断。如果无效,则返回False表示移动无效。
- 如果移动有效,将当前玩家的棋子放置在指定位置boardrow = player。
- 接下来,遍历八个方向的偏移量,表示在该方向上搜索对方棋子是否可以被翻转。
- 对于每个方向,根据偏移量从指定位置开始向该方向前进,如果遇到对方棋子,则继续前进直到遇到空格、边界或当前玩家的棋子。
- 如果在该方向上遇到了当前玩家的棋子,将之前记录的需要翻转的对方棋子进行翻转操作,即将boardflip_row设置为当前玩家的棋子。
- 最后,返回True表示移动有效。
is_valid_move
函数的输入参数包括:
• board:当前游戏棋盘的状态,是一个二维列表,表示每个位置上的棋子情况。
• row、col:玩家希望在棋盘上放置棋子的行和列索引。
• player:当前玩家的标识符,可以是'W'(白棋)或'B'(黑棋)。
函数的返回值为布尔值,表示移动是否有效。如果移动有效,返回True;如果移动无效,返回False。
函数的主要步骤如下:
- 首先,检查指定位置上是否已经有棋子。如果该位置已经有棋子,则返回False表示移动无效。
- 确定对方玩家的标识符。如果当前玩家是白棋('W'),则对方玩家是黑棋('B');反之亦然。
- 遍历八个方向的偏移量,表示在该方向上搜索对方棋子。
- 对于每个方向,从指定位置开始向该方向前进,如果遇到对方玩家的棋子,则继续前进直到遇到空格、边界或当前玩家的棋子。
- 如果在该方向上遇到了当前玩家的棋子,说明在该方向上可以进行翻转操作,表示移动有效,返回True。
- 如果在所有方向上都没有找到可以翻转的对方棋子,则移动无效,返回False。
create_board函数:
函数的主要步骤如下:
- 创建一个二维列表 board,用于表示黑白棋盘。列表的行数和列数都为 BOARD_SIZE,每个元素初始值为 ' ',表示空格。
- 将黑棋和白棋的初始位置设置在棋盘的中心,即第3行第3列、第3行第4列、第4行第3列和第4行第4列。将这些位置上的元素分别设置为 'W' 和 'B',表示白棋和黑棋。
- 返回创建好的棋盘 board。
create_board函数创建一个初始状态的黑白棋棋盘,并返回该棋盘。每个棋子的位置由特定的字符表示,空格表示未放置棋子的位置,'W' 表示白棋,'B' 表示黑棋。
- Direction 8个方向定义:
directions列表中的元素表示了八个方向,每个元素是一个包含两个整数的元组,分别表示在行和列上的移动偏移量。下面是对每个元素所代表的方向的解释:
1. (0, -1):向左移动一列
2. (0, 1):向右移动一列
3. (-1, 0):向上移动一行
4. (1, 0):向下移动一行
5. (-1, -1):向左上方移动一行一列
6. (-1, 1):向右上方移动一行一列
7. (1, -1):向左下方移动一行一列
8. (1, 1):向右下方移动一行一列
这些方向涵盖了棋子可以进行的所有移动方向,包括水平、垂直和对角线方向。
在黑白棋游戏中,通过遍历这些方向,并在棋盘上按照相应的偏移量移动,可以判断该位置是否为有效的落子位置,并且可以在落子时翻转对方的棋子。