1

我正在做一个蛇游戏。我有两个班,snakefood。当我调用snake->move()它时,它需要检查没有冲突,为此它需要知道food的位置是什么,因此需要一个指向food. food有一个函数可以将它移动到一个新的随机位置 ,move->setNewPosition()它需要知道 的位置,snake以便它在移动时不会与蛇发生碰撞。为此,它需要一个指向snake.

因此,对于这两个类,我需要提供一个指向另一个必须初始化的类的指针。但是要初始化另一个类,我需要初始化另一个类,依此类推。有什么方法可以同时初始化两个需要相互指针的类?

如果不是,那么构建我的程序以允许我检查其他类的坐标的更好方法是什么?

4

6 回答 6

2

如果我没有误解你,请创建init在游戏循环开始之前调用的函数:

void initSnake()
{
   auto snake = new Snake();
   auto food = new Food();   
   snake->setFood(food);
   food->setSnake(snake);
}
于 2012-11-29T12:25:24.447 回答
1

您可以为它们定义一个基类,它具有以下方法:

virtual void setPosition(const int x, const int y)
virtual void getPosition(int &x, int &y) const

Snake 也应该使用它们,如果需要,只需覆盖它们。setPosition现在,getPosition如果您将另一个对象作为带有 type 的参数,这两个类可以直接调用对方Base

另一种方法是;在您的main()-function 或您定义蛇的任何地方:

int main()
{
    Snake* s = new Snake;
    Food* f = new Food;
    Snake->setLocation(0,0); // Wherever you want the snake to start from
}

每当你创建一个新食物时,给它蛇的位置:f->setRandomLocation(snake->getLocation())参数将是坐标,而不是放置它。

于 2012-11-29T12:27:32.057 回答
1

当他们的运动功能被调用时,他们只需要找到其他蛇和食物的位置的设施。在初始化时无需知道它们的存在!

因此,您可以拥有蛇集合和食物集合,并将对这些集合的引用传递给任何新创建的蛇和食物。只需先创建这些集合。

你可以通过另一个类来做到这一点,也许它也可以作为一个工厂。

class GameManager;

class Snake
{
    friend class GameManager;

    public:
        int getX() { return _x; }
        int getY() { return _y; }

        void setPosition(int x, y) { /* ... */ }

    private: 
        Snake(GameManager* manager, int x, int y) : _manager(manager), _x(x), _y(y) {}

        GameManager* _manager;
        int _x, _y;
};

class GameManager
{
    public: 
        const std::vector<Snake*>& Snakes() { return _snakes; }

        Snake* SpawnSnake(int x, int y) 
        {
            Snake* newSnake = new Snake(this, x, y);
            snakes.push_back(newSnake);
            return snake;
        }

    private:
        std::vector<Snake*> _snakes;
};

(只是一个例子。代码未经测试,看它是否真的编译。E&OE)

因为构造函数是私有的GameManager,所以确保所有创建的蛇都在蛇向量中找到。Snake每条蛇都可以调用_manager.Snakes()以获取包含游戏中所有其他蛇的向量,然后它可以单独查询它们的位置。这也很容易推广到支持食品。

与其他答案中建议的“构造初始化”模式相比,这具有很小的优势,因为它确保当您获得一个新Snake对象时,它实际上已经准备好使用......这个例子并不完全是 RAII,但它需要一个使其合理异常安全的最小努力。

于 2012-11-29T12:29:13.587 回答
0

一种选择是有一个Manager他们都向其发送请求的类,这将更有意义(但不能解决您的特定问题)。

不过,如果您有class Aand class B,并且每个都需要另一个,您可以执行以下操作:

A *a = new A;
B *b = new B;
// check a and b to make sure they are not NULL
a->set_b(b);
b->set_a(a);
于 2012-11-29T12:27:17.500 回答
0

嗯,不确定你的游戏是如何运作的,但我认为会有很多食物对象?

也许一个想法是创建一个Collision接受 Snake 玩家并在游戏中存储所有 Food 玩家的类。所以 Collision 构造函数可能看起来像这样

Collison(Snake &snake, Vector<Food*> &foods)
{

}

Collision 类还将有一个碰撞更新循环,您在代码中的某处调用该循环。此循环将检查蛇对象是否与食物对象碰撞。您可以做任何您想做的事情。从foods vector 更改中删除食物食物位置,无论如何。

collison.UpdateCollisions() ; 
于 2012-11-29T12:30:20.377 回答
0

我建议打破循环依赖,而不是把它锤进去:让两个移动函数都将环境(即它可以碰撞的事物的列表)作为参数。

于 2012-11-29T12:45:05.637 回答