我的棋盘验证程序有效,但给出的结果不正确

My chess-board validation program works, but gives an incorrect result

程序应该根据存储在变量中的任意字典是否满足棋盘的标准来打印 True 或 False。标准如下: 一个有效的棋盘只有一个黑王和一个白王。每个玩家最多只能有 16 个棋子,最多 8 个棋子,并且所有棋子必须在'1a'到'8h'的有效 space 上;也就是说,一块不能在 space '9z' 上。棋子名称以 'w' 或 'b' 开头,代表白色或黑色,然后是 'pawn'、'knight'、'bishop'、'rook'、 'queen',或 'king'。此函数应检测错误何时导致棋盘不正确。

我的程序是这样的:

board = {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop',\
'5h': 'bqueen', '3e': 'wking'}
def isValidChessBoard(_board_):
    gen_num=0
    pawn_num=0
    wking_num=0
    bking_num=0
    letters=['a','b','c','d','e','f','g','h']
    pieces=['pawn','knight','bishop','rook','king','queen']
    for v in _board_.values():
        gen_num+=1
    if gen_num > 16:
        return False
    for v in _board_.values():
        if v.endswith('pawn'):
            pawn_num+=1
    if pawn_num > 8:
        return False
    for v in _board_.values():
        if v =='wking':
            wking_num+=1
        if v =='bking':
            bking_num+=1
    if wking_num!=1 or bking_num!=1:
        return False
    for k in _board_.keys():
        for i in range(1,9):
            if not k.startswith(str(i)):
                return False
    for k in _board_.keys():
        for i in letters:
            if not k.endswith(i):
                return False
    for v in _board_.values():
        if not v.startswith('b') or v.startswith('w'):
            return False
    for v in _board_.values():
        for i in pieces:
            if not v.endswith(i):
                return False
    return True

print(isValidChessBoard(board))

该词典似乎符合给定的标准。但是,每次我尝试 运行 时,程序都会打印“'False'”。

我在这里遗漏了什么吗?

在此先感谢您,如果问题太基础或太宽泛,我深表歉意。

如果您暂时将所有 return False 替换为 raise Exception 那么很容易看出哪一部分是 returning False。

这样做之后我们可以看到这部分是问题所在:

for k in _board_.keys():
    for i in range(1,9):
        if not k.startswith(str(i)):
            return False

不确定您要在那里做什么,我猜您是在尝试检查棋子的编号是否在 1 到 8 之间?使这项工作的一个小改动是:

for k in _board_.keys():
    for i in range(1,9):
        if k.startswith(str(i)):
            break
    else:
        return False

如果找到匹配项,我们会中断,但如果没有中断,那么我们 return 错误。继续,我们发现您在另外两个地方犯了这个错误。

我们也可以看出这里的逻辑不太好:

if not v.startswith('b') or v.startswith('w'):

大概应该是这样的:

if not v.startswith('b') and not v.startswith('w'):

把所有这些放在一起你得到这个:

board = {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop',\
'5h': 'bqueen', '3e': 'wking'}
def isValidChessBoard(_board_):
    gen_num=0
    pawn_num=0
    wking_num=0
    bking_num=0
    letters=['a','b','c','d','e','f','g','h']
    pieces=['pawn','knight','bishop','rook','king','queen']
    for v in _board_.values():
        gen_num+=1
    if gen_num > 16:
        raise Exception
    for v in _board_.values():
        if v.endswith('pawn'):
            pawn_num+=1
    if pawn_num > 8:
        raise Exception
    for v in _board_.values():
        if v =='wking':
            wking_num+=1
        if v =='bking':
            bking_num+=1
    if wking_num!=1 or bking_num!=1:
        raise Exception
    for k in _board_.keys():
        for i in range(1,9):
            if k.startswith(str(i)):
                break
        else:
            raise Exception
    for k in _board_.keys():
        for i in letters:
            if k.endswith(i):
                break
        else:
            raise Exception

    for v in _board_.values():
        if not v.startswith('b') and not v.startswith('w'):
            raise Exception

    for v in _board_.values():
        for i in pieces:
            if v.endswith(i):
                break
        else:
            raise Exception
    return True

print(isValidChessBoard(board))

我建议保留 raise Exceptions 直到完成,此时您只需将它们替换为 return False

问题在于循环,例如:

        for i in range(1,9):
            if not k.startswith(str(i)):
                return False

它坚持要以这些数字中的 all 开头,而不是以其中的 any 开头。循环可以替换为:

        for i in range(1,9):
            if k.startswith(str(i)):
                break
        else:
            return False

注意条件是倒置的。如果 匹配项,则它会从循环中中断。如果找到 no 个匹配项,则将执行 else 块。注意这里的缩进:elsefor 循环有关, 不是 if 块,如果 for 循环完成但未被执行,则会执行破.

有几个地方有类似的问题。

您还有一个地方需要括号:

        if not (v.startswith('b') or v.startswith('w')):

因为不带括号的原文相当于:

        if (not v.startswith('b')) or v.startswith('w'):

因为 not 的运算符优先级高于 or.

等二元布尔运算符

将这些修复放在一起得到:

board = {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop',\
'5h': 'bqueen', '3e': 'wking'}
def isValidChessBoard(_board_):
    gen_num=0
    pawn_num=0
    wking_num=0
    bking_num=0
    letters=['a','b','c','d','e','f','g','h']
    pieces=['pawn','knight','bishop','rook','king','queen']
    for v in _board_.values():
        gen_num+=1
    if gen_num > 16:
        return False
    for v in _board_.values():
        if v.endswith('pawn'):
            pawn_num+=1
    if pawn_num > 8:
        return False
    for v in _board_.values():
        if v =='wking':
            wking_num+=1
        if v =='bking':
            bking_num+=1
    if wking_num!=1 or bking_num!=1:
        return False
    for k in _board_.keys():
        for i in range(1,9):
            if k.startswith(str(i)):
                break
        else:
            return False
    for k in _board_.keys():
        for i in letters:
            if k.endswith(i):
                break
        else:
            return False
    for v in _board_.values():
        if not (v.startswith('b') or v.startswith('w')):
            return False
    for v in _board_.values():
        for i in pieces:
            if v.endswith(i):
                break
        else:
            return False
    return True

print(isValidChessBoard(board))