给定棋盘上棋子的坐标,计算“安全棋子”,Python
给定国际象棋棋盘上棋子的坐标,用一组字符串表示,比如 {"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}