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