I wrote a Snake Game in C++ and I have practiced some OOP approaches on windows 7.
What I need:
- advice how to improve code
- Most important how to made what Snake on
CollisionCheck
method do different "things" for example if snake eats Fruit snake will grow by one. if Snake eats self or wall .game collapse etc/ - Any ideas how to add functional what you can make maps in notepad and import into the game?
Source.cpp
// Source.cpp : Defines the entry point for the console application.
//
#include <conio.h>
#include <iostream>
#include "stdafx.h"
#include"Snake.h"
using namespace std;
int main()
{
Snake snake(20, 20);
Fruit fruit(10,10);
Wall wall(15, 15);
int i = 0;
while (i < 800) {
++i;
snake.Move();
fruit.Draw();
wall.Draw();
if (snake.CollisionCheck(&fruit))break;
Sleep(100);
}
std::cout << " END GAME! "<<std::endl;
cout << snake.SnakeLength();
return 0;
}
Snake.h
#pragma once
#include <iostream>
#include <vector>
#include "Box.h"
#include <conio.h>
using namespace std;
#define MAX_SNAKE_SIZE 500
class Snake
{
public:
Snake(int StartX, int StartY);
~Snake();
void ShowSelf();
void TurnRigth();
void TurnLeft();
void TurnUp();
void TurnDown();
void AddBox(); //adds element at the end of the snake
void Move();
bool CollisionCheck(Obstacle*object);
int SnakeLength() { return box.size(); };
private:
int x;
int y;
char dir;//current direction of snake
vector<Box> box;//no dinamic array because sweet pain
int length;
};
Snake.cpp
#include "stdafx.h"
#include "Snake.h"
#include <windows.h>
#include <conio.h>
//#define DEBUG
enum Object
{
BOX = 0,
FRUIT=1,
WALL=2
};
Snake::Snake(int StartX,int StartY)
{
x = StartX;
y = StartY;
length = 1;
Box obj1(x,y);
//obj1.SetSymbol('S');
box.push_back(obj1);
}
Snake::~Snake()
{
#ifdef DEBUG
for (int i = 0; i < box.size(); i++)
{
Box temp = box[i];
temp.ShowCord();
}
#endif
}
void Snake::ShowSelf()
{
for (unsigned int i = 0; i < box.size(); i++)
{
box[i].Draw();
}
}
void Snake::TurnRigth()
{
dir = 'd';
}
void Snake::TurnLeft()
{
dir = 'a';
}
void Snake::TurnUp()
{
dir = 'w';
}
void Snake::TurnDown()
{
dir = 's';
}
void Snake::AddBox()
{
int size = box.size();
Box temp(box[size-1].GetX(), box[size-1].GetY());
box.push_back(temp);
}
void Snake::Move()
{
system("cls");
//allows Snake to move
for (int i = box.size()-1; i>0; i--)
{
box[i].SetCord(box[i - 1].GetX(), box[i - 1].GetY());
}
//check what kind of button was pressed
char tempdir = dir;
if(_kbhit())dir = _getch();
if (dir == 'w') {
if (tempdir == 's') { //stops snake move backwards
box[0].MoveDown();
dir = tempdir;
}
else box[0].MoveUp();
}
else if (dir == 'd') {
if (tempdir == 'a') { //stops snake move backwards /
box[0].MoveLeft();
dir = tempdir;
}
else box[0].MoveRigth();
}
else if (dir == 's') {
if (tempdir == 'w') { //stops snake move backwards
box[0].MoveUp();
dir = tempdir;
}
else box[0].MoveDown();
}
else if (dir == 'a') {
if (tempdir == 'd') { //stops snake move backwards
box[0].MoveRigth();
dir = tempdir;
}
else box[0].MoveLeft();
}
for (unsigned int i = 0; i < box.size(); i++) //draw Snake
{
box[i].Draw();
}
}
bool Snake::CollisionCheck(Obstacle *object) //hiting magick appiers
{
int boxX = box[0].GetX(); int boxY = box[0].GetY();
//check if snake ate self or not
for (int i = 1; i < box.size(); ++i)
{
if ((box[0].GetX() == box[i].GetX()) && (box[0].GetY() == box[i].GetY())) { return true; }
}
//check if it hitten anything else is hitted
if ((object->GetX() == box[0].GetX())&&(object->GetY() == box[0].GetY()))
{
int obstacle = object->onCollision();
if (obstacle == FRUIT) { //deletes old glyph //spawns object at new coord
this->AddBox();
return false;
}
/*else if (obstacle == BOX)
{
return 0;
}*/
else if (obstacle == WALL)
{
return 0;
}
}
return false;
}
Box.h where all potentional elements of game is (walls,Fruit,snake elements)
#pragma once
#include <iostream>
#include <conio.h>
#include <iostream>
#include <windows.h>
class Obstacle
{
public:
Obstacle(int x, int y);
void SetX(int x) { this->x = x; };
void SetY(int y) { this->y = y; };
int GetX() { return x; };
int GetY() { return y; };
void Draw();
void Erase();
void NewSpawn();//Spawns Obstacle at new coords
virtual int onCollision();//check if hited or not
void SetSymbol(char symbol) { this->symbol = symbol; };
protected:
char symbol;
int x;
int y;
};
class Box :public Obstacle
{
public:
Box(int x, int y) :Obstacle(x, y) { this->SetSymbol('o'); };
void SetCord(int x, int y);
void MoveUp();
void MoveDown();
void MoveRigth();
void MoveLeft();
int onCollision()override;
};
class Fruit :public Obstacle
{
public:
Fruit(int x, int y) :Obstacle(x, y) { this->SetSymbol('F'); };
int onCollision ()override;
};
class Wall :public Obstacle
{
public:
Wall(int x, int y) :Obstacle(x, y) { this->SetSymbol('#'); };
int onCollision()override;
};
Box.cpp
#include "stdafx.h"
#include "Box.h"
#include <stdlib.h>
#include"time.h"
enum Object
{
BOX = 0,
FRUIT = 1,
WALL = 2
};
//place symbol at specific coords in console
void gotoxy(int x, int y)
{
COORD c = { x, y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
void Box::SetCord(int x, int y)
{
this->x = x;
this->y = y;
}
void Box::MoveUp()
{
y--;
}
void Box::MoveDown()
{
++y;
}
void Box::MoveRigth()
{
x++;
}
void Box::MoveLeft()
{
x--;
}
int Box::onCollision()
{
return BOX;
}
Obstacle::Obstacle(int x, int y)
{
this->x = x;
this->y = y;
}
void Obstacle::Erase()
{
gotoxy(x, y);
std::cout << " ";
}
void Obstacle::Draw()
{
gotoxy(x, y);
std::cout << symbol;
}
void Obstacle::NewSpawn()
{
srand(time(NULL));//need to fix that
x = rand() % 80;
y = rand() % 23;
}
int Obstacle::onCollision()
{
return BOX;
}
int Fruit::onCollision()
{
this->Erase();
this->NewSpawn();
return FRUIT;
}
int Wall::onCollision()
{
return WALL;
}