C++ OOP中的正确方法。游戏示例。玩家::步行还是地图::玩家步行?

C++ OOP中的正确方法。游戏示例。玩家::步行还是地图::玩家步行?,c++,oop,class-design,C++,Oop,Class Design,让我们假设有一个游戏。有一个地图类和一个玩家类。地图存储字段,字段存储玩家。 在OOP中,这是一种正确的方法。什么时候负责玩家行走的方法是player::walk还是Map::playerWalk 关于第一个例子(Player::walk),它似乎是正确的做法,在现实生活中也是如此——它的玩家走路, 然而,它必须通过地图实例访问目的地字段,检查它是否可以走到那里,从起始字段删除它,并在目的地字段中添加它,我的印象是玩家“知道的太多了”。最终这是一个设计问题,两者都可以很好地适应OOP范式 我倾向

让我们假设有一个游戏。有一个地图类和一个玩家类。地图存储字段,字段存储玩家。 在OOP中,这是一种正确的方法。什么时候负责玩家行走的方法是player::walk还是Map::playerWalk

关于第一个例子(Player::walk),它似乎是正确的做法,在现实生活中也是如此——它的玩家走路,
然而,它必须通过地图实例访问目的地字段,检查它是否可以走到那里,从起始字段删除它,并在目的地字段中添加它,我的印象是玩家“知道的太多了”。

最终这是一个设计问题,两者都可以很好地适应OOP范式

我倾向于将方法放在语义上最有意义的类上。在这个场景中,这意味着
Player::walk
,除非地图做了一些事情使“players”移动(即在一个flippers游戏中,游戏板使球[aka'Player']移动),然后让实体调用(例如
board::movePlayer
)可能更具语义

如果选择
player::walk
设计,则应将地图实例传递给播放器。因此,您最终得到的是
Player::walk(这里有Map&Map/*更多参数,可能是方向或矢量速度?*/)

另一点要指出的是,你应该试着说得比你要求的多。这意味着,而不是:

//in Player::walk
if (map.cells[wantToWalkTo] == 0) {
    map.cells[wantToWalkTo] = this.playerId;
}
//TODO: handle failed moves
你应该这样做:

bool moved = map.moveTo(position, this); //encapsulate the logic for moving a player to a position
//TODO: handle failed moves

你的玩家实例不必“知道”所有这些事情。它可以通过接口与Map实例通信。一个人可以向外看,看到一些东西,但看不到其他东西(例如,可以看到一堵墙,但看不到墙后面的东西)。Map实例可以控制哪些是可见的,哪些不是

Python-ish伪代码:

class Player:
    def __init__(self, Map, location):
        """Create a player, and tell them what Map they live on."""
        self.Map = Map
        self.location = location

    def walk(self, destination):
        """Try to walk to the destination."""
        path = self.Map.path_visible(location, destination)

        if path:
            self.location = destination

class Map:
    def path_visible(self, location, destination):
        """Can a player at location see how to get to the destination?"""

正确的OOP方法是让map呈现某种接口,允许:

  • 检查某个字段是否为空/该字段上有什么对象
  • 在地图上放置/删除对象

  • 移动玩家的逻辑应该完全在玩家类中。所以检查玩家是否可以到达目标场,是否为空,等等。。。应该由玩家使用地图界面或其他类提供的信息来处理。举例来说,当你想让玩家穿过墙壁,走在水上或类似的东西上时,玩家在改变,而不是地图。p> 这将相当于一个“玩家”在现实生活中所拥有的知识。他们应该知道不要直接撞到墙上!你有第三种可能:一个免费函数:
    PlayerWalk(Player,Map)
    @Jarod42;虽然OOP不太可能。。。(可能是最好的,并且是不可能的,用一个真正的面向类语言,如Java和C++ java)@ Alxand ErrByvig自由函数算法是C++中非常常见的一个习语(因为这个问题被标记)。我将把它放在处理游戏逻辑的对象(即“上面没有”)中。