我还有一个问题希望能够总结我的想法。
假设我有以下3个类:
类玩家:
class Player {
private:
int positionX, positionY;
public:
void move(Board& b) {
// player changes its position on the board(move)
b.removeCharFromBoard(positionX, positionY);
positionX++;
positionY++;
// 'P' indicates a Player in the Board....
b.insertCharToBoard(positionX, positionY, 'P');
}
};
班主席:
class Board {
private:
// BOARD_C and BOARD_R are both "#define ..." for some integer number.
char board[BOARD_C][BOARD_R];
};
类GameEngine:
class GameEngine {
private:
Board* board;
public:
void playTurn(const Player& p) {
p.move(board);
}
};
你认为GameBoard的playTurn函数会用参数“board”调用Player的移动功能似乎是合理的吗? 我需要这样做才能在棋盘数据成员中标记玩家已经改变了他的位置。 它是否遵守OOP基本规则?
谢谢大家, 聚合者!
答案 0 :(得分:4)
是的,在这种情况下它似乎是合理的(在这种情况下,“我的意思是”考虑我可以猜到的GameEngine
和{{1}的语义}类及其关联/聚合关系的性质“):
Board
中的Board
对象。在这种情况下,GameEngine
可能就是您想要的,因为所有其他别名似乎只是观察者,并且板对象的生命周期绑定到unique_ptr
对象的生命周期。但是,如果需要共享所有权,请选择GameEngine
。尽量不要使用原始指针shared_ptr
和new
,因为它们会导致错误的代码; delete
类的接口上提供公共函数来修改电路板,因为Board
将无法访问其私有成员变量(和Player
碰巧是一个。)。board
s,使用#define
值来表示电路板的大小(如果您使用的是C ++ 11)。您可能还需要考虑Boost.MultiArray来创建安全二维C风格数组。答案 1 :(得分:3)
你的方法很好。 GameEngine将被用作游戏的某种控制器。多亏了它你可以过滤玩家的动作,检查这种移动是否可行,或者在特定玩家操作的情况下做其他类型的动作。
其次,对于这个解决方案,您不必将播放器连接到特定的电路板,这扩展了您在其他选项之间的可能性,例如在电路板之间轻松转移播放器。我认为你的方式很好:)
答案 2 :(得分:1)
您必须考虑应用程序的更改方式以及您希望引入的功能。从这段代码看起来它看起来不错,但是当你引入新功能时它会是什么样子?
其他解决方案是将播放器仅移动逻辑,它将更新其位置,然后您的GameEngine将根据您所有玩家的当前位置更新电路板条目。想象一段时间你会想要实现碰撞检测,然后在每个玩家更新其位置或移动之后,将发生碰撞检测并纠正这些移动,并且只有在你的板上稍后才能正确更新。
答案 3 :(得分:1)
已经说了很多话,但如果我可以添加一些东西。
将Board
(无论是private
还是Player
)传递给void Sprite::draw(RenderTarget& target, RenderStates states) const
{
if (m_texture)
{
states.transform *= getTransform();
states.texture = m_texture;
target.draw(m_vertices, 4, Quads, states);
}
}
并不是本身,并且这种设计用于多种架构(代码取自SFML 2.0):
RenderTarget
Board
是您的Board
。这里要理解的是,您将仅使用其公共接口(您有权访问)在draw()
上运行。在上面的代码中,target
是Player
上用来强制它绘制内容的方法。
将内部对象传递给更高级别类(如Board
)的整个想法可以解释为bridge OO pattern,其中可以有几个接口IBoardManipulator
的实现和几个类可以实现GameEngine
(或类似的东西)。
那就是说,我会说遵循游戏引擎的总体思路要好得多:
draw()
都会调用Board
作为实体可以使用的目标Player
。我并不是说对于一个简单的架构来说这是必需的,但是在更长的运行中,管理起来比处理每个Board
的讨厌的事情要容易得多 - 类可以对{{1}}进行。