【问题标题】:Transforming a game to an object-oriented version将游戏转换为面向对象的版本
【发布时间】:2015-03-12 23:01:14
【问题描述】:

我编写了一个简单的控制台游戏,它允许我将我的玩家移动到一个有墙壁和空白区域的小关卡内。只需使用几个简单的函数即可完成所有操作。

我对 Python 比较陌生,但接下来我想学习 OOP,如果我想让这个游戏面向对象,我将如何继续?

我理解类和对象相当很好,但如果我不理解所有答案,请耐心等待。

这是当前的游戏:

LEVEL = [
    'xxxxxx',
    'x    x',
    'x i  x',
    'x    x',
    'x    x',
    'xxxxxx'
]


def get_block(x, y):
    """Gets a block at the given coordinates."""
    try:
        return LEVEL[y][x]
    except IndexError:
        return None


def set_block(x, y, block):
    """Sets a block at the given coordinates."""
    try:
        LEVEL[y] = LEVEL[y][:x] + block + LEVEL[y][x + 1:]
    except IndexError:
        pass


def get_player_position():
    """Gets player's position."""
    for y, row in enumerate(LEVEL):
        for x, column in enumerate(row):
            if column == 'i':
                return x, y


def set_player_position(x, y):
    """Sets player's position."""
    block = get_block(x, y)
    if block == ' ':
        px, py = get_player_position()
        set_block(px, py, ' ')
        set_block(x, y, 'i')


def main():
    """Entry point for the program."""
    cmd = ''
    while cmd.lower() not in ('quit', 'q'):
        print('\n' * 30)
        for row in LEVEL:
            print(row)
        cmd = input('Command: ').lower()
        px, py = get_player_position()
        if cmd == 'w':
            set_player_position(px, py - 1)
        elif cmd == 's':
            set_player_position(px, py + 1)
        elif cmd == 'a':
            set_player_position(px - 1, py)
        elif cmd == 'd':
            set_player_position(px + 1, py)
    print('Bye.')

if __name__ == '__main__':
    main()

【问题讨论】:

  • 您到底想做什么?如果你有一个精确的编程问题,那很好,但是一个模糊的问题,问我如何改变我的代码来做一些不同的事情,我相信,这里是题外话。
  • @AdrianHHH 我正在尝试练习 OOP,我对此非常陌生。我希望在将此代码转换为使用类(例如Player 类或Level 类?)方面获得一些帮助。我知道如果问错了地方,你能推荐任何“正确”的地方吗?
  • 查看每个 Stackoverflow 页面顶部链接的帮助页面,了解此处主题的详细信息。我不知道 Python,但网络上其他地方可能有很多教程和帮助论坛。如果您有明确的问题,请返回此处,我相信 Python 社区会很乐意提供帮助。
  • @AdrianHHH 感谢您的指导 :)

标签: python class oop object python-3.x


【解决方案1】:

您的问题非常开放,因此很难给出一个包罗万象的答案 - 所以我所做的是在您现有的代码中识别一个数据结构并将其变成一个类。

以前对全局数据结构进行操作的函数现在都是该类实例的所有公共方法,这是唯一允许在名为 _field 的私有属性中更改其中保存的数据的方法。

做这种事情是编写面向对象软件必不可少的第一步。

希望你觉得这个例子有点启发性。

class PlayingField(object):
    # Class constants
    PLAYER = 'i'
    EMPTY = ' '
    EDGE = 'x'
    DEFAULT_SIZE = 6

    def __init__(self, size=DEFAULT_SIZE):
        X, EMPTY = self.EDGE, self.EMPTY
        self._size = size
        # build playing field
        self._field = [size*X] + (size-2)*[X + (size-2)*EMPTY + X] + [size*X]
        self._set_block(2, 2, self.PLAYER)  # Initialize player's position.

    def display(self):
        print(30*'\n')
        for row in self._field:
            print(row)

    def get_player_position(self):
        """Gets player's position."""
        for y, row in enumerate(self._field):
            for x, column in enumerate(row):
                if column == self.PLAYER:
                    return x, y
        else:
            raise ValueError("Couldn't determine player's location on field")

    def set_player_position(self, x, y):
        """Sets player's position."""
        block = self._get_block(x, y)
        if block == self.EMPTY:
            px, py = self.get_player_position()
            self._set_block(px, py, self.EMPTY)
            self._set_block(x, y, self.PLAYER)


    # Private methods
    def _get_block(self, x, y):
        """Gets a block at the given coordinates."""
        try:
            return self._field[y][x]
        except IndexError:
            return None

    def _set_block(self, x, y, block):
        """Sets a block at the given coordinates."""
        try:
            self._field[y] = self._field[y][:x] + block + self._field[y][x + 1:]
        except IndexError:
            pass

def main():
    """Entry point for the program."""
    field = PlayingField()
    cmd = ''
    while cmd.lower() not in ('quit', 'q'):
        field.display()
        cmd = input('Command: ').lower()
        px, py = field.get_player_position()
        if cmd == 'w':
            field.set_player_position(px, py - 1)
        elif cmd == 's':
            field.set_player_position(px, py + 1)
        elif cmd == 'a':
            field.set_player_position(px - 1, py)
        elif cmd == 'd':
            field.set_player_position(px + 1, py)
    print('Bye.')

if __name__ == '__main__':
    main()

【讨论】:

  • 非常感谢 :) 我需要更多帮助,但我要问一个不同的问题。
  • 不客气。如果您对我的答案(我刚刚更新了一点)有任何疑问,请随时在 cmets 中这样做。我给你的一个不相关的建议是让_field 属性成为bytearray 对象的列表而不是字符串,因为前者是可变的,所以更改它们的内容会更容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
相关资源
最近更新 更多