【问题标题】:How to move a chess piece with a numpy array?如何用 numpy 数组移动棋子?
【发布时间】:2021-10-14 17:42:53
【问题描述】:

所以在过去的几天里,我一直试图让我的国际象棋引擎在一个 numpy 数组中工作。我已经在字符串基础中创建了这整个东西,但它不起作用,因为整体带有 numpy 数组。我已经在 pygame 中构建了这个。所以我使用的是最新版本的 numpy 和 pygame。 代码:

import sys
import numpy as np
import pygame as p

BOARD_WIDTH = 512
BOARD_HEIGHT = 512
DIMENSION = 8  # dimensions of a chess board are 8x8
SQ_SIZE = 512 // DIMENSION
MAX_FPS = 60  # for animations later on
screen = p.display.set_mode((BOARD_WIDTH, BOARD_HEIGHT))
IMAGES = {}
class GameState():
    def __init__(self):
        # board is 8x8 2D List, each element of the list has 2 characters
        # initial character == colour (b,w)
        # second character == piece
        # R == rook, N == knight, B == bishop, Q == Queen, K == king, P == pawn
        # -- == empty space
        self.board = [
            ["bR", "bN", "bB", "bQ", "bK", "bB", "bN", "bR"],
            ["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp"],
            ["wR", "wN", "wB", "wQ", "wK", "wB", "wN", "wR"]
        ]

        self.lookup = {
            "--": 0,
            "wK": 1, "wQ": 2, "wR": 3, "wB": 4, "wN": 5, "wp": 6,
            "bK": 7, "bQ": 8, "bR": 9, "bB": 10, "bN": 11, "bp": 12
        }
        self.compute_board = np.array([[self.lookup[p] for p in row] for row in self.board])
        print(self.compute_board)

        self.whiteToMove = True
        self.moveLog = []

    def makeMove(self, move):
        self.compute_board[move.start_row][move.start_col] == 0
        self.compute_board[move.end_row][move.end_col] = move.piece_moved
        self.moveLog.append(move)
        print(self.moveLog)
        self.whiteToMove = not self.whiteToMove


class Move:
    # in chess, fields on the board are described by two symbols, one of them being number between 1-8 (which is corresponding to rows)
    # and the second one being a letter between a-f (corresponding to columns), in order to use this notation we need to map our [row][col] coordinates
    # to match the ones used in the original chess game
    ranks_to_rows = {"1": 7, "2": 6, "3": 5, "4": 4,
                 "5": 3, "6": 2, "7": 1, "8": 0}
    rows_to_ranks = {v: k for k, v in ranks_to_rows.items()}
    files_to_cols = {"a": 0, "b": 1, "c": 2, "d": 3,
                 "e": 4, "f": 5, "g": 6, "h": 7}
    cols_to_files = {v: k for k, v in files_to_cols.items()}

    def __init__(self, start_square, end_square, compute_board):
        self.start_row = start_square[0]
        self.start_col = start_square[1]
        self.end_row = end_square[0]
        self.end_col = end_square[1]
        self.piece_moved = compute_board[self.start_row][self.start_col]
        self.piece_captured = compute_board[self.end_row][self.end_col]

    def getChessNotation(self):
        return self.getRankFile(self.start_row, self.start_col + self.getRankFile(self.end_row, self.end_col))

    def getRankFile(self, r, c):
        return self.cols_to_files[c] + self.rows_to_ranks[r]


def main():
    p.init()
    square_selected = ()  # no square is selected initially, this will keep track of the last click of the user (tuple(row,col))
    player_clicks = []  # this will keep track of player clicks (two tuples)
    gs = GameState()
    clock = p.time.Clock()
    loadImages()  # only do this once, before the while loop
    running = True

    while running:

        for e in p.event.get():
            if e.type == p.QUIT:
                p.quit()
                sys.exit()
            # mouse handler
            elif e.type == p.MOUSEBUTTONDOWN:
                location = p.mouse.get_pos()  # (x, y) location of the mouse
                col = location[0] // SQ_SIZE
                row = location[1] // SQ_SIZE
                if square_selected == (row, col) or col >= 8:  # user clicked the same square twice
                    square_selected = ()  # deselect
                    player_clicks = []  # clear clicks
                else:
                    square_selected = (row, col)
                    player_clicks.append(square_selected)  # append for both 1st and 2nd click
                if len(player_clicks) == 2:  # after 2nd click
                    move = Move(player_clicks[0], player_clicks[1], gs.compute_board)
                    # print(move.getChessNotation())
                    gs.makeMove(move)
                    square_selected = ()
                    player_clicks = []

        drawGameState(screen, gs.board)

        clock.tick(MAX_FPS)
        p.display.update()


def loadImages():
    pieces = ['wp', 'wR', 'wN', 'wB', 'wK', 'wQ', 'bp', 'bR', 'bN', 'bB', 'bK', 'bQ']
    for piece in pieces:
        IMAGES[piece] = p.transform.scale(p.image.load("images/" + piece + ".png"), (SQ_SIZE, SQ_SIZE))


# Note we can access an image by saying "IMAGES['wp']'


def drawGameState(screen, board):
    drawBoard(screen)  # draw squares on the board
    drawPieces(screen, board)


def drawBoard(screen):
    global colors
    colors = [p.Color("white"), p.Color("gray")]
    for r in range(DIMENSION):
        for c in range(DIMENSION):
            color = colors[((r + c) % 2)]
            p.draw.rect(screen, color, p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))


def drawPieces(screen, board):
    for row in range(DIMENSION):
        for column in range(DIMENSION):
            piece = board[row][column]
            if piece != "--":
                screen.blit(IMAGES[piece], p.Rect(column * SQ_SIZE, row * SQ_SIZE, SQ_SIZE, SQ_SIZE))


if __name__ == '__main__':
    main()

要加载图像,您可以使用维基百科中的图像:https://en.wikipedia.org/wiki/Chess_piece“棋子”下右侧的第一列。

问题在于这一行:self.compute_board[move.start_row][move.start_col] == 0 其中 0 表示 numpy 数组上的空白空间,用于表示碎片可以移动到的位置,但我还没有弄清楚问题所在。我试过找到type 的价值move.start_rowmove.start_col,它们都是int。我试过self.compute_board[move.start_row][move.start_col] == list(self.lookup.keys())[list(self.lookup.values()).index(0)] 给你'--' 不起作用。

但这适用于字符串版本。在Move 类中,您将所有compute_boardself.compute_board 更改为boardself.board。以及类GameState 中的makeMove 中的所有self.compute_board。还将self.compute_board[move.start_row][move.start_col] = 0 中的0 更改为'--'。并在主函数中将move = Move(player_clicks[0], player_clicks[1], gs.compute_board)中的gs.compute_board更改为gs.board

当所有这些更改都完成后,所有部件都可以移动。但是说到numpy数组我就不知道了。

self.compute_board 是我想将所有移动编码到一个 numpy 数组中的方式,因此当我运行我的国际象棋 AI 时,它不会被它必须运行的字符串所困。

我解决了逻辑工作的问题,只是当我加载图像时,我没有将它们与 compute_board 一起加载到另一块板上。我还必须改变我在板上对图像进行粘贴的方式。如果你想知道如何让我知道。

因此,如果您能帮助我,我将不胜感激,如果您需要更多信息,请告诉我。

【问题讨论】:

  • 你能给出确切的错误信息/堆栈跟踪吗?
  • 没有错误或任何事情它根本不起作用。

标签: python numpy


【解决方案1】:

这是关于我如何加载图像。

老办法:

def loadImages():
    pieces = ['wp', 'wR', 'wN', 'wB', 'wK', 'wQ', 'bp', 'bR', 'bN', 'bB', 'bK', 'bQ']
    for piece in pieces:
        IMAGES[piece] = p.transform.scale(p.image.load("images/" + piece + ".png"), (SQ_SIZE, SQ_SIZE))

新方法:

    lookup = {
    "--": 0,
    "wK": 1, "wQ": 2, "wR": 3, "wB": 4, "wN": 5, "wp": 6,
    "bK": 7, "bQ": 8, "bR": 9, "bB": 10, "bN": 11, "bp": 12
}


def loadImages():
    pieces = ['wp', 'wR', 'wN', 'wB', 'wK', 'wQ', 'bp', 'bR', 'bN', 'bB', 'bK', 'bQ']
    for piece in pieces:
        IMAGES[lookup[piece]] = p.transform.scale(p.image.load("images/" + piece + ".png"), (SQ_SIZE, SQ_SIZE))

然后我不得不改变我在棋盘上画棋子的方式。

def drawPieces(screen, board):
    for r in range(DIMENSION):
        for c in range(DIMENSION):
            piece = board[r][c]
            if piece != 0:  # not empty square
                screen.blit(IMAGES[piece], p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))

刚刚用if piece != 0 摆脱了if piece != '--,它就可以工作了。我还把drawGameState函数调用中的变量改成了gs.board改成gs.compute_board

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多