当前位置:   article > 正文

国际跳棋python

国际跳棋python

import pygame
import sys
import random
import time

初始化Pygame

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

if name == “main”:
main()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/1006215
推荐阅读
相关标签
  

闽ICP备14008679号