我怎么知道国王在棋盘上移动而不去对面的所有有效位置

How do I know all valid positions for a King to move on chess board without going to the opposite side

所以我有一个棋盘,表示为大小为 64 的数组,左上角的方格为 0,右下角的方格为 63。我有这个函数可以给出国王所有可能的移动。

current_pos = i
arr = np.array([i-9, i-8, i-7, i-1, i+1, i+7, i+8, 1+9])
return arr

.
.
.

if selected position is in arr:
    move king

其中 i 是当前国王所在的方格的编号。

如果国王不在棋盘的边缘,此方法有效。

但是如果国王在右下角,即63号,函数给出左下角56号作为国王移动的有效位置。

有什么有效的方法可以知道国王要走到另一边并且不是有效的着法吗?

我几乎所有的棋子都遇到了同样的问题,该函数允许棋子在棋盘的另一侧移动,但我认为国王的移动是最简单的问题。

这是一种使用 table 查找的方法。

代码

piece_offsets = {
    'n': [-17, -15, -10, -6, 6, 10, 15, 17],
    'b': [ -9,  -7,  9, 7],
    'r': [ -8,  -1,  8, 1],
    'q': [ -9,  -8, -7, -1, 9,  8,  7,  1],
    'k': [ -9,  -8, -7, -1, 9,  8,  7,  1]
}

sqdist = [[0 for x in range(64)] for y in range(64)]

pseudo_legal = {    
    'n': [[] for y in range(64)],
    'b': [[] for y in range(64)],
    'r': [[] for y in range(64)],    
    'q': [[] for y in range(64)],
    'k': [[] for y in range(64)],
}


def distance(sq1, sq2):
   file1 = sq1 & 7
   file2 = sq2 & 7
   rank1 = sq1 >> 3
   rank2 = sq2 >> 3
   rank_distance = abs(rank2 - rank1)
   file_distance = abs(file2 - file1)
   return max(rank_distance, file_distance)


def print_board():
    for i in range(64):
        print(f'{i:02d} ', end='')
        if (i+1)%8 == 0:
            print()


def on_board(s):
    return s >= 0 and s < 64


def init_board():    
    for sq1 in range(64):
        for sq2 in range(64):
            sqdist[sq1][sq2] = distance(sq1, sq2)
            
    for pt in ['n', 'b', 'r', 'q', 'k']:
        for s in range(64):
            for offset in piece_offsets[pt]:
                to = s + offset
                if pt in ['k', 'n']:
                    if on_board(to) and sqdist[s][to] < 4:
                        pseudo_legal[pt][s].append(to)
                else:  # sliders
                    s1 = s
                    while True:
                        to1 = s1 + offset
                        if on_board(to1) and sqdist[s1][to1] < 4:
                            pseudo_legal[pt][s].append(to1)
                            s1 = to1
                        else:
                            break


def main():
    init_board()  # build sqdist and pseudo_legal_to tables
    
    print_board()
    print()  
    
    for pt in ['n', 'b', 'r', 'q', 'k']:
        for s in [0, 63, 36]:
            print(f'pt: {pt}, from: {s}: to: {pseudo_legal[pt][s]}')
        print()
        
    # pseudo_legal_sq = pseudo_legal['b'][61]
    # print(pseudo_legal_sq)
    
    
main()

输出

00 01 02 03 04 05 06 07 
08 09 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 

pt: n, from: 0: to: [10, 17]
pt: n, from: 63: to: [46, 53]
pt: n, from: 36: to: [19, 21, 26, 30, 42, 46, 51, 53]

pt: b, from: 0: to: [9, 18, 27, 36, 45, 54, 63]
pt: b, from: 63: to: [54, 45, 36, 27, 18, 9, 0]
pt: b, from: 36: to: [27, 18, 9, 0, 29, 22, 15, 45, 54, 63, 43, 50, 57]

pt: r, from: 0: to: [8, 16, 24, 32, 40, 48, 56, 1, 2, 3, 4, 5, 6, 7]
pt: r, from: 63: to: [55, 47, 39, 31, 23, 15, 7, 62, 61, 60, 59, 58, 57, 56]
pt: r, from: 36: to: [28, 20, 12, 4, 35, 34, 33, 32, 44, 52, 60, 37, 38, 39]

pt: q, from: 0: to: [9, 18, 27, 36, 45, 54, 63, 8, 16, 24, 32, 40, 48, 56, 1, 2, 3, 4, 5, 6, 7]
pt: q, from: 63: to: [54, 45, 36, 27, 18, 9, 0, 55, 47, 39, 31, 23, 15, 7, 62, 61, 60, 59, 58, 57, 56]
pt: q, from: 36: to: [27, 18, 9, 0, 28, 20, 12, 4, 29, 22, 15, 35, 34, 33, 32, 45, 54, 63, 44, 52, 60, 43, 50, 57, 37, 38, 39]

pt: k, from: 0: to: [9, 8, 1]
pt: k, from: 63: to: [54, 55, 62]
pt: k, from: 36: to: [27, 28, 29, 35, 45, 44, 43, 37]

一维列表比二维 8x8 列表快得多,所以我喜欢您使用这种方法。

处理方法是使用 10x12 板,在底部和顶部多出 2 行,在左侧和右侧多出一列:

然后在生成移动函数中,您可以简单地检查您正在查看的方块是否在棋盘内。如果不是,则跳到循环中的下一个方块。

请在 https://www.chessprogramming.org/10x12_Board 上阅读更多相关信息。它也是一个提供国际象棋编程一般信息的好网站。