Issue in Snake game but not pertaining to the snake

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
Lofd123
Posts: 3
Joined: July 28th, 2020, 1:05 am

Issue in Snake game but not pertaining to the snake

Post by Lofd123 » July 28th, 2020, 1:58 am

In terms of the game, I have actually finished it already (minus making the snake move continuously in a direction without pressing the button), and upon making optimizations towards the code, I encountered numerous problems upon building the project that I could just not figure. All I simply did was move the checkAvailability function of the food over to being a body member function since the array (currently array) is accessible there, but upon doing so, I encountered 20 new problems that were not there before to begin with; a lot of them just seeming asinine as the compiler seems to be picking out problems that aren't even there. I don't know why this occurred, and I have spent some time trying to debug it to no avail before actually coming here seeking answers. I can't describe the problem to you because I don't know if something might have gone awry with Visual Studio, and whether or not the issue is only with my compiler (despite me believing in the computer is always right dogma). Instead, I'll post a screenshot here (never posted a screenshot here before so don't know if this will work) of my problem along with the code on github so we can decipher this out together.

https://github.com/Lofd123/gitsnek
Attachments
20 compiler errors.png
(54.25 KiB) Not downloaded yet

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Issue in Snake game but not pertaining to the snake

Post by albinopapa » July 28th, 2020, 4:10 am

Snake.h includes Food.h and Food.h includes Snake.h. This is called a circular dependency and C++ don't like it.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Lofd123
Posts: 3
Joined: July 28th, 2020, 1:05 am

Re: Issue in Snake game but not pertaining to the snake

Post by Lofd123 » July 28th, 2020, 4:33 am

albinopapa wrote:
July 28th, 2020, 4:10 am
Snake.h includes Food.h and Food.h includes Snake.h. This is called a circular dependency and C++ don't like it.
Thanks that seemed to fix the problem. How did you notice something like that? I personally didn't change any headers around, so I'm not sure as to why that happened. I would also like to ask you as to the portion that checks for x of a segment to be between x >=0 and x <= 780 (in the checkAvailabe and show1 function). Is there any better way for me to check if a array element has been initialized? I found that workaround for now, but I do think it is just ultimately undefined behavior, and there may be a very small chance where my program crashes because it will fall within those bounds at some point.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Issue in Snake game but not pertaining to the snake

Post by albinopapa » July 28th, 2020, 7:19 am

Code: Select all

How did you notice something like that? 
So there are a number of things that lead me to that conclusion. One, I've been learning C++ for 8 years now and have seen quite a few errors. When you get some of the errors in that PNG you uploaded and nothing really makes sense, then it is likely a circular dependency. Two, to be honest, this error is quite frequent for that game when new programmers start venturing out on their own because of the interactions between each object type ( snake and food ). Same goes for the poo game.

The best way to avoid stuff like this is think about what the responsibilities of each class should be. Does food need to know about Snake or should Snake know about Food?
Something else you can do is do collision or other interactions using a bridge class or function. For instance, Game knows about Board, Snake and Food, so you can have a
bool Game::IsColliding( Snake const& snake, Food const& food )
Then:
if( IsColliding( snake, food ) ){ ... }
Basically, this prevents Snake and Food from knowing about each other all together.
Is there any better way for me to check if a array element has been initialized?
The is no standard way that I know of to check if an object is initialized, however, the easiest way to avoid uninitialized objects is to initialize them upon construction or give them default values in the body of the class.

Code: Select all

struct Location{
    int x = 0;
    int y = 0;
};
This makes it so that every Location object you create will be default initialized to ( 0, 0 ) if you don't provide values during construction.

Code: Select all

class Snake {
	Location spot = { 0, 0 };  // Default initializes Location::x and Location::y to 0
	Color c = Colors::Green;  // Default initializes c to { 0, 255, 0 }
public:
	Snake() = default;
	Snake(int pos, int pos2, const Board& b) : spot{ pos,pos2 }, c{ 255,0,0 } {
	}
	Snake(int pos, int pos2) : spot{pos, pos2}, c(255,0,0) {}
	void show(const Board& b) const;
	Location& getSpot();
	const Location getSpot1() const;
	bool touched(const Snake& snek) const;
};
Always give default values in class body and your members will never be uninitialized.

You'll always have bounds checking at some point, so checking if snake or segments are "visible" is unavoidable.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Lofd123
Posts: 3
Joined: July 28th, 2020, 1:05 am

Re: Issue in Snake game but not pertaining to the snake

Post by Lofd123 » July 28th, 2020, 8:32 am

Thank you for your reply. I'll just have to practice more to get the nuances down. I always assumed that adding functionality like that to the Game.cpp file was bad, so I strayed away from doing that to keep the code more modular.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Issue in Snake game but not pertaining to the snake

Post by albinopapa » July 28th, 2020, 9:09 am

I always assumed that adding functionality like that to the Game.cpp file was bad, so I strayed away from doing that to keep the code more modular.
And you'd be correct, but as you have found out, making two objects know about each other is a difficult task. So instead of using Game, you could also create another class in a completely different header that handles collision between objects. That way, Game stays clean and neither Snake nor Food need to know about each other.

Imagine you need to determine intersection between two shapes. These shapes don't need to know about each other, but they also need to interact with each other. You could have a CollisionHandler class that handles collisions between the different shapes:

Code: Select all

// CollisionHandler.h
#include "Square.h"
#include "Circle.h"
#include "Triangle.h"
#include "Ray.h"

class CollisionHandler{
public:
    static bool IsIntersecting( Square const& lhs, Square const& rhs );
    static bool IsIntersecting( Square const& lhs, Circle const& rhs );
    static bool IsIntersecting( Square const& lhs, Triangle const& rhs );
    static bool IsIntersecting( Square const& lhs, Ray const& rhs );
    static bool IsIntersecting( Circle const& lhs, Square const& rhs );
    static bool IsIntersecting( Circle const& lhs, Circle const& rhs );
    static bool IsIntersecting( Circle const& lhs, Triangle const& rhs );
    static bool IsIntersecting( Circle const& lhs, Ray const& rhs );
    static bool IsIntersecting( Triangle const& lhs, Square const& rhs );
    static bool IsIntersecting( Triangle const& lhs, Circle const& rhs );
    static bool IsIntersecting( Triangle const& lhs, Triangle const& rhs );
    static bool IsIntersecting( Triangle const& lhs, Ray const& rhs );
    static bool IsIntersecting( Ray const& lhs, Square const& rhs );
    static bool IsIntersecting( Ray const& lhs, Circle const& rhs );
    static bool IsIntersecting( Ray const& lhs, Triangle const& rhs );
};

// In Game.h
#include "CollisionHandler.h" // already includes all shapes, don't need to list them again
class Game{
public:

private:
    Object ball;
    Object platform;
};

// In Game::UpdateModel
    if( CollisionHandler::IsIntersecting( ball.GetCircle(), platform.GetSquare() ) ){ ... }
By avoiding coupling, you keep things more modular.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply