给定棋盘上棋子的坐标,计算“安全棋子”,Python

-1 投票
2 回答
1135 浏览
提问于 2025-04-18 17:06

给定国际象棋棋盘上棋子的坐标,用一组字符串表示,比如 {"b4", "d4", "f4", "c3", "e3", "g5", "d2"}。棋盘的行用数字表示,列用字母表示。我们的目标是找出被保护的棋子数量,也就是那些后面对角线上有其他棋子的棋子数量。
我正在自学Python,已经在这个任务上花了几个小时。如果能得到一些帮助,我将非常感激。
这是我尴尬又杂乱的尝试:

def safe_pawns(pawns):
    count = 0
    cols = "abcdefgh"
    positions = {'a':[],'b':[],'c':[],'d':[],'e':[],'f':[],'g':[],'h':[]}
    for i in positions:
        for j in pawns:
            if i in j:
                positions[i].append(int(j[1]))
    for k in range(len(cols)-1):
        for l in positions[cols[k+1]]:
            if l +1 or l-1 in positions[cols[k]]:
                count +=1
    return count

2 个回答

2

我敢打赌这就是你的问题:

if l +1 or l-1 in positions[cols[k]]:

这并不是说“如果 l+1 在那个位置,或者 l-1 在那个位置”。如果你是这个意思(你几乎肯定是),你需要这样写:

if l+1 in positions[cols[k]] or l-1 in positions[cols[k]]:

(当然也有其他间接写法,比如 if {l+1, l-1}.intersection(positions[cols[k]]),但我觉得直接写出来是最明显的方法。)

1

首先,用字母来表示列会给你带来麻烦,尤其是当你开始进行数学运算的时候,因为你不能直接做 'b' - 1 这样的操作。把你的数据从像 'a1' 这样的字符串集合转换成像 (1, 1) 这样的元组集合会更简单一些。(或者你可以使用从零开始的索引,不过这部分我觉得不在这里讨论的范围内)。

其次,假设你现在有一个棋子集合 {(2, 4), (3, 3), (4, 2), (4, 4), (5, 3), (6, 4), (7, 5)}。你其实不需要那么多的循环。你可以通过一个集合表达式来获取被保护的棋子集合(我假设你是从棋盘的“底部”开始的玩家?):

{(x,y) for (x,y) in s if (x-1,y-1) in s or (x+1,y-1) in s}

你会发现这个集合的大小是6。

注意:我使用的输入转换表达式是:

s = {("abcdefg".find(let) + 1, int(num)) for let, num in pawns}

撰写回答