赞
踩
import pygame
import sys
import random
import time
pygame.init()
WIDTH, HEIGHT = 1000, 800 # 增加宽度以显示棋谱
ROWS, COLS = 8, 8
SQUARE_SIZE = HEIGHT // COLS # 修改方格大小以适应新高度
RED = (255, 0, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
GREY = (128, 128, 128)
YELLOW = (255, 215, 0)
GREEN = (0, 255, 0) # 添加GREEN颜色定义
class Piece:
PADDING = 15
OUTLINE = 2
def __init__(self, row, col, color): self.row = row self.col = col self.color = color self.king = False if self.color == RED: self.direction = -1 else: self.direction = 1 self.x = 0 self.y = 0 self.calc_pos() def calc_pos(self): self.x = SQUARE_SIZE * self.col + SQUARE_SIZE // 2 self.y = SQUARE_SIZE * self.row + SQUARE_SIZE // 2 def make_king(self): self.king = True def draw(self, win): radius = SQUARE_SIZE // 2 - self.PADDING pygame.draw.circle(win, GREY, (self.x, self.y), radius + self.OUTLINE) pygame.draw.circle(win, self.color, (self.x, self.y), radius) if self.king: pygame.draw.circle(win, YELLOW, (self.x, self.y), radius // 2) def move(self, row, col): self.row = row self.col = col self.calc_pos() def __repr__(self): return str(self.color)
class Board:
def init(self):
self.board = []
self.red_left = self.white_left = 12
self.red_kings = self.white_kings = 0
self.create_board()
def draw_squares(self, win): win.fill(BLACK) for row in range(ROWS): for col in range(row % 2, COLS, 2): pygame.draw.rect(win, WHITE, (row * SQUARE_SIZE, col * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)) def move(self, piece, row, col): self.board[piece.row][piece.col], self.board[row][col] = self.board[row][col], self.board[piece.row][piece.col] piece.move(row, col) if row == ROWS - 1 or row == 0: piece.make_king() if piece.color == WHITE: self.white_kings += 1 else: self.red_kings += 1 def get_piece(self, row, col): return self.board[row][col] def create_board(self): for row in range(ROWS): self.board.append([]) for col in range(COLS): if col % 2 == ((row + 1) % 2): if row < 3: self.board[row].append(Piece(row, col, WHITE)) elif row > 4: self.board[row].append(Piece(row, col, RED)) else: self.board[row].append(0) else: self.board[row].append(0) def draw(self, win): self.draw_squares(win) for row in range(ROWS): for col in range(COLS): piece = self.board[row][col] if piece != 0: piece.draw(win) def remove(self, pieces): for piece in pieces: self.board[piece.row][piece.col] = 0 if piece != 0: if piece.color == RED: self.red_left -= 1 else: self.white_left -= 1 def winner(self): if self.red_left <= 0: return WHITE elif self.white_left <= 0: return RED return None def get_valid_moves(self, piece): moves = {} left = piece.col - 1 right = piece.col + 1 row = piece.row # 向前和向后移动的代码 moves.update(self._traverse_left(row - 1, max(row - 3, -1), -1, piece.color, left)) moves.update(self._traverse_right(row - 1, max(row - 3, -1), -1, piece.color, right)) moves.update(self._traverse_left(row + 1, min(row + 3, ROWS), 1, piece.color, left)) moves.update(self._traverse_right(row + 1, min(row + 3, ROWS), 1, piece.color, right)) jump_moves = {k: v for k, v in moves.items() if v} if jump_moves: return jump_moves # 如果没有跳吃的移动,只允许往前移动一格 normal_moves = {} if piece.color == RED or piece.king: if row - 1 >= 0: if left >= 0 and self.board[row - 1][left] == 0: normal_moves[(row - 1, left)] = [] if right < COLS and self.board[row - 1][right] == 0: normal_moves[(row - 1, right)] = [] if piece.color == WHITE or piece.king: if row + 1 < ROWS: if left >= 0 and self.board[row + 1][left] == 0: normal_moves[(row + 1, left)] = [] if right < COLS and self.board[row + 1][right] == 0: normal_moves[(row + 1, right)] = [] return normal_moves def _traverse_left(self, start, stop, step, color, left, skipped=[]): moves = {} last = [] for r in range(start, stop, step): if left < 0: break current = self.board[r][left] if current == 0: if skipped and not last: break elif skipped: moves[(r, left)] = last + skipped else: moves[(r, left)] = last if last: if step == -1: row = max(r - 3, 0) else: row = min(r + 3, ROWS) moves.update(self._traverse_left(r + step, row, step, color, left - 1, skipped=last)) moves.update(self._traverse_right(r + step, row, step, color, left + 1, skipped=last)) break elif current.color == color: break else: last = [current] left -= 1 return moves def _traverse_right(self, start, stop, step, color, right, skipped=[]): moves = {} last = [] for r in range(start, stop, step): if right >= COLS: break current = self.board[r][right] if current == 0: if skipped and not last: break elif skipped: moves[(r, right)] = last + skipped else: moves[(r, right)] = last if last: if step == -1: row = max(r - 3, 0) else: row = min(r + 3, ROWS) moves.update(self._traverse_left(r + step, row, step, color, right - 1, skipped=last)) moves.update(self._traverse_right(r + step, row, step, color, right + 1, skipped=last)) break elif current.color == color: break else: last = [current] right += 1 return moves def get_all_pieces(self, color): pieces = [] for row in self.board: for piece in row: if piece != 0 and piece.color == color: pieces.append(piece) return pieces def can_enemy_capture(self, piece): enemy_color = WHITE if piece.color == RED else RED directions = [(-1, -1), (-1, 1), (1, -1), (1, 1)] for dr, dc in directions: enemy_row, enemy_col = piece.row + dr, piece.col + dc jump_row, jump_col = piece.row - dr, piece.col - dc if 0 <= enemy_row < ROWS and 0 <= enemy_col < COLS and 0 <= jump_row < ROWS and 0 <= jump_col < COLS: enemy_piece = self.get_piece(enemy_row, enemy_col) if enemy_piece != 0 and enemy_piece.color == enemy_color: if self.get_piece(jump_row, jump_col) == 0: return True return False
class Game:
def init(self, win):
self._init()
self.win = win
self.moves_log = []
self.font = pygame.font.SysFont(‘Arial’, 24)
def update(self): self.board.draw(self.win) self.draw_valid_moves(self.valid_moves) self.draw_moves_log() pygame.display.update() def _init(self): self.selected = None self.board = Board() self.turn = RED self.valid_moves = {} self.moves_log = [] self.has_captured = False # 增加捕获标志变量 def reset(self): self._init() def select(self, row, col): piece = self.board.get_piece(row, col) if piece != 0 and piece.color == self.turn: self.selected = piece self.valid_moves = self.board.get_valid_moves(piece) if any(self.valid_moves.values()): # 如果有跳吃的移动 self.valid_moves = {k: v for k, v in self.valid_moves.items() if v} # 只保留跳吃的移动 return True return False def _move(self, row, col): piece = self.board.get_piece(row, col) if self.selected and (row, col) in self.valid_moves: self.log_move(self.selected, row, col, self.valid_moves[(row, col)]) self.board.move(self.selected, row, col) skipped = self.valid_moves[(row, col)] if skipped: self.board.remove(skipped) self.has_captured = True # 设置捕获标志 self.update() # 更新显示 time.sleep(1) # 停顿一秒 if self.has_captured: # 如果第一步捕获了对方的棋子 # 如果新的位置还能跳吃,就继续跳吃 while self.selected and self.board.get_valid_moves(self.selected): new_valid_moves = self.board.get_valid_moves(self.selected) jump_moves = {k: v for k, v in new_valid_moves.items() if v} if jump_moves: self.valid_moves = jump_moves self.update() # 更新显示 time.sleep(1) # 停顿一秒 return True # 允许玩家选择新的跳吃位置 else: break self.has_captured = False # 重置捕获标志 self.change_turn() else: return False return True def undo_move(self, row, col): piece = self.board.get_piece(row, col) self.board.move(piece, self.selected.row, self.selected.col) def draw_valid_moves(self, moves): for move in moves: row, col = move pygame.draw.circle(self.win, BLUE, (col * SQUARE_SIZE + SQUARE_SIZE // 2, row * SQUARE_SIZE + SQUARE_SIZE // 2), 15) def draw_moves_log(self): pygame.draw.rect(self.win, BLACK, (WIDTH - 200, 50, 200, HEIGHT - 100)) # 清除棋谱区域 for i, move in enumerate(self.moves_log[-20:]): # 只显示最后20个记录 color = RED if i % 2 == 0 else WHITE move_text = self.font.render(move, True, color) self.win.blit(move_text, (WIDTH - 200, 50 + i * 30)) # 在棋谱位置上滚动显示 def draw_winner(self, winner): win_text = f"{winner} Wins!" end_text = "Game Over" self.moves_log.append(win_text) self.moves_log.append(end_text) self.update() while True: # 增加无限循环等待用户关闭窗口 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() def change_turn(self): self.valid_moves = {} if self.turn == RED: self.turn = WHITE else: self.turn = RED def log_move(self, piece, row, col, skipped): start_pos = piece.row * 8 + piece.col + 1 end_pos = row * 8 + col + 1 move_notation = f"{start_pos:02d}-{end_pos:02d}" if skipped: move_notation = f"{start_pos:02d}" for skip in skipped: move_notation += f"x{skip.row * 8 + skip.col + 1:02d}" move_notation += f"x{end_pos:02d}" self.moves_log.append(move_notation) def winner(self): return self.board.winner()
def get_row_col_from_mouse(pos):
x, y = pos
row = y // SQUARE_SIZE
col = x // SQUARE_SIZE
return row, col
FPS = 60
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(‘Checkers’)
def draw_menu(win):
win.fill(BLACK)
font = pygame.font.SysFont(‘Arial’, 60)
text1 = font.render(‘1. Human vs Human’, True, WHITE)
text2 = font.render(‘2. Human vs AI’, True, WHITE)
text3 = font.render(‘3. AI vs AI’, True, WHITE)
win.blit(text1, (200, 200))
win.blit(text2, (200, 300))
win.blit(text3, (200, 400))
pygame.display.update()
def ai_move(game):
valid_moves = {}
for piece in game.board.get_all_pieces(game.turn):
moves = game.board.get_valid_moves(piece)
if moves:
valid_moves[piece] = moves
if valid_moves: max_jump_moves = {piece: moves for piece, moves in valid_moves.items() if any(moves.values())} if max_jump_moves: piece = random.choice(list(max_jump_moves.keys())) move = random.choice(list(max_jump_moves[piece].keys())) else: piece = random.choice(list(valid_moves.keys())) move = random.choice(list(valid_moves[piece].keys())) game.log_move(piece, move[0], move[1], valid_moves[piece][move]) game.board.move(piece, move[0], move[1]) if valid_moves[piece][move]: game.board.remove(valid_moves[piece][move]) game.has_captured = True # 设置捕获标志 game.update() # 更新显示 time.sleep(1) # 停顿一秒 if game.has_captured: # 如果第一步捕获了对方的棋子 # 如果AI的棋子可以继续跳吃 while piece and game.board.get_valid_moves(piece): new_valid_moves = game.board.get_valid_moves(piece) jump_moves = {k: v for k, v in new_valid_moves.items() if v} if jump_moves: next_move = random.choice(list(jump_moves.keys())) game.log_move(piece, next_move[0], next_move[1], jump_moves[next_move]) game.board.move(piece, next_move[0], next_move[1]) game.board.remove(jump_moves[next_move]) game.update() # 更新显示 time.sleep(1) # 停顿一秒 else: break game.has_captured = False # 重置捕获标志 game.change_turn()
def main():
run = True
clock = pygame.time.Clock()
mode = None
while run: clock.tick(FPS) if mode is None: draw_menu(WIN) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_1: mode = "HUMAN_HUMAN" elif event.key == pygame.K_2: mode = "HUMAN_AI" elif event.key == pygame.K_3: mode = "AI_AI" continue game = Game(WIN) while run: clock.tick(FPS) if game.winner() != None: winner_color = "White" if game.winner() == WHITE else "Red" game.draw_winner(winner_color) break for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.MOUSEBUTTONDOWN: pos = pygame.mouse.get_pos() row, col = get_row_col_from_mouse(pos) if game.select(row, col): piece = game.selected if (row, col) in game.valid_moves: game._move(row, col) if mode == "AI_AI" or (mode == "HUMAN_AI" and game.turn == WHITE): ai_move(game) game.update() pygame.quit() sys.exit()
if name == “main”:
main()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。