首页 > 解决方案 > 如何在 Python 上为游戏构建 20x20 板?

问题描述

我是一个初学者,正在尝试创建一个类似于 Checkers 的棋盘游戏。我需要构建一个 20x20 的板,其中行名为 1-20,列名为 AT。我已经在下面构建了电路板,但它看起来非常违反直觉,并且它们没有用数字和字母初始化。我想采用诸如“A5”之类的参数来定义玩家移动功能。

class Game:
def __init__(self):
    self._board = [[" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "],
                   [" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "]]

标签: python

解决方案


您可以定义一个具有正常数字索引(从 0 到 19)的二维列表,然后编写将诸如“A5”之类的字符串转换为这些索引的函数。__getitem__如果你把这个逻辑放在一个实现类似and的魔术方法的类中__setitem__,你可以使用这些标识符作为下标(比如board["A5"]),而不必按名称调用函数。

例如:

from typing import List, Optional, Tuple


class Board:
    def __init__(self, size: int = 20):
        self._board: List[List[Optional[str]]] = [
            [None for _ in range(size)] for _ in range(size)
        ]

    def _get_coords(self, space: str) -> Tuple[int, int]:
        assert (
            space[1:].isdecimal()
            and space[0].isalpha()
            and space[0].isupper()
        ), "Specify spaces as uppercase letter and number, eg 'A5'"
        coords = int(space[1:]) - 1, ord(space[0]) - ord("A")
        assert all(
            i in range(len(self._board)) for i in coords
        ), f"{space} is outside of the board"
        return coords

    def __getitem__(self, space: str) -> Optional[str]:
        x, y = self._get_coords(space)
        return self._board[x][y]

    def __setitem__(self, space: str, piece: str) -> None:
        x, y = self._get_coords(space)
        self._board[x][y] = piece

    def __str__(self) -> str:
        return (
            "\n".join(str(i+1).ljust(3) + " ".join(
                c if c else " " for c in row
            ) for i, row in enumerate(self._board))
            + "\n   " + " ".join(
                chr(ord("A") + c) for c in range(len(self._board))
            )
        )


if __name__ == '__main__':
    board = Board()
    board["A5"] = "O"
    board["B20"] = "X"
    print(board)

将内部保持在一个普通列表中的好处(即使你还不习惯用零索引列表来思考)是它可以更容易地编写在板上迭代的逻辑(就像__str__函数一样) -- 如果板子被存储为带有命名列的嵌套字典,那么编写这个函数会有点困难)。


推荐阅读