Какой самый эффективный способ вызвать блок кода, зависящий от состояния объекта? - PullRequest
0 голосов
/ 26 октября 2018

У меня есть большой список (30-50) игровых объектов, которые меняются между 5-7 состояниями в последовательном порядке, что радикально меняет их поведение.

Мой первоначальный наивный подход состоял в том, чтобы дать каждому игровому объекту переменную State, а затем каждая команда действия проходила бы через блок if-else, чтобы найти правильное действие, соответствующее состоянию.

Вариант 1 (наивный подход)

class Bot:
    def action(self):
        if self.state == 1:
            action1()
            if condition1_to_2():
                self.state = 2
        elif self.state == 2:
            action2()
        #...

list_of_bots = [Bot(), Bot(), ...]

for bot in list_of_bots:
    bot.action()

Но я подумал, что с 50 игровыми объектами разве этот обход if-else не займет много времени?

Не могу ли я повысить производительность, перейдя прямо к правильному коду состояния?

Единственный способ реализовать это - использовать наследование (интерфейс или подклассы) и делать каждое игровое состояние каждого игрового объекта своим собственным подклассом, уничтожая и создавая новый объект каждый раз, когда он меняет состояние.

Вариант 2 (Наследование)

class Bot:
    def action(): raise NotImplementedError

class Bot1(Bot):
    def action():
       action1()

class Bot2(Bot):
    def action():
       action2()
#...

list_of_bots = [Bot1(), Bot2(), ...]

for bot in list_of_bots:
    bot.action()

Таким образом, каждый игровой объект не должен проверять, в каком состоянии он находился на каждом такте игры, что позволяет сэкономить около 300 операций на такт.

Моя единственная проблема в том, что это похоже на излишнее количество новых классов. Есть ли более компактное, но не менее эффективное решение этой проблемы?

Я подумал, что словарь или список состояний (если они дают время доступа O (1)), но как связать список с блоком кода?

Вариант 3 (Невозможно?)

class Bot:
    def __init__(self):
       self.action_list = [action1(), action2(), ...]
       self.state = 1

    def action():
        self.action_list[self.state]

Решение должно быть сделано в raw python3 (без установки pip).

1 Ответ

0 голосов
/ 26 октября 2018

Ваш вариант 3 может работать со ссылками на функции, однако я не уверен, является ли эта структура программы наилучшей для использования.Но чтобы сохранить список ссылок на функции, вы можете сделать это следующим образом:

class Bot:
    def __init__(self, game_map):
       self.action_list = [self.action1, self.action2]  # Stores function references
       self.state = 1
       self.game_map = game_map  # Pass in game_map object that the class can use

    def action(self):
        self.action_list[self.state]()  # Calls function reference

    def action1(self):
        # Does something

    def action2(self):
        # Does something

Редактировать: я добавил пример передачи объекта game_map, который вы упомянули в комментариях.Затем вы можете использовать self.game_map везде, где в ваших действиях будут функции, которые будут теми же объектами, которые обновляет игровой контроллер, если вы каждый раз изменяете эту карту вместо создания новой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...