I made a simple C++ snake game, and I want some advice from you: what is good, what I have to improve. One main problem is that flipping (which you'll notice if you play it).
#include <conio.h>
#include <ctime>
#include <iostream>
#include "windows.h"
const int width = 60;
const int height = 15;
double diff=0.5;
class Snake
{
public:
Snake();
void color(int choosecolor);
void create_map(char map[][height]);
void credits();
void difficulty();
void game_over(int score);
void generate_food(char map[][height],int & food_x,int & food_y);
bool invalid_snake(char map[][height],int snake_position[][height]);
bool is_food(char map[][height],int food_x,int food_y);
bool is_food_pgame(char map[][height], char mapfood[][height]);
void movement(char map[][height],int snake_position[][height],int eating);
void options();
void pause();
bool poison_snake(char map[][height],int snake_parts[][height], int x1, int x2, int y1, int y2);
void poison_game();
void rules();
void show_map(char map[][height],int score);
void start_game();
private:
int check[width][height];
char keyboard = 'n';
int lenght;
};
int main()
{
char selection;
start:
Snake object;
srand(time(0));
std::cin >> selection;
if(selection=='1')
{
system("cls");
object.start_game();
}
else if(selection=='2')
{
system("cls");
object.poison_game();
}
else if(selection=='3')
{
object.options();
system("cls");
goto start;
}
else if(selection=='4') system("exit");
else
{
system("cls");
goto start;
}
return 0;
}
void Snake::color(int choosecolor)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), choosecolor);
}
void Snake::create_map(char map[][height])
{
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
if(i==0 || i==height-1) map[j][i]=char(178);
if(i>0 && i<height-1) map[j][i]=' ';
if(j==0 || j==width-1) map[j][i]=char(178);
}
}
}
void Snake::credits()
{
char selection;
system("cls");
while(true)
{
std::cout << std::endl;
std::cout << " Lead programmer: contact.istrate " << std::endl;
std::cout << " Designer: contact.istrate " << std::endl;
std::cout << " Testers: contact.istrate " << std::endl << std::endl;
std::cout << " Go back <1> ";
std::cin >> selection;
if(selection=='1') return;
else system("cls");
}
}
void Snake::difficulty()
{
char selection;
system("cls");
while(true)
{
std::cout << std::endl;
std::cout << " CURRENT DIFFICULTY" << std::endl;
if(diff==1) std::cout << " Easy" << std::endl << std::endl;
else if(diff==0.5) std::cout << " Normal" << std::endl << std::endl;
else if(diff==0.2) std::cout << " Hard" << std::endl << std::endl;
else if(diff==0.1) std::cout <<" Super hard" << std::endl << std::endl;
else if(diff==0.03) std::cout <<" Impossible" << std::endl << std::endl;
std::cout << " CHOOSE DIFFICULTY" << std::endl;
std::cout << " Easy <1>" << std::endl;
std::cout << " Normal <2>" << std::endl;
std::cout << " Hard <3>" << std::endl;
std::cout << " Super hard <4>" << std::endl;
std::cout << " Impossible <5>" << std::endl << std::endl;
std::cout << " Go back <6>" << std::endl;
std::cin >> selection;
if(selection=='1') //there are 5 ready difficulties
{
diff=1;
system("cls");
}
else if(selection=='2')
{
diff=0.5;
system("cls");
}
else if(selection=='3')
{
diff=0.2;
system("cls");
}
else if(selection=='4')
{
diff=0.1;
system("cls");
}
else if(selection=='5')
{
diff=0.03;
system("cls");
}
else if(selection=='6') return;
else system("cls");
}
}
void Snake::game_over(int score)
{
std::cout << std::endl;
char selection; int i;
std::cout << " \nGAME OVER!";
std::cout << std::endl << std::endl;
std::cout << "Do you want to play again ? [y/n] ";
std::cin >> selection;
if(selection=='y')
{
system("cls");
start_game();
}
else
{
system("cls");
main();
}
}
void Snake::generate_food(char map[][height],int & food_x,int & food_y)
{
int i,j;
food_x=(rand()%(width-2))+1;
food_y=(rand()%(height-2))+1;
for(j=1;j<width-1;j++)
{
for(i=1;i<height-1;i++)
{
if(map[j][i]!=char(233) && map[j][i]!=char(254))
{
map[food_x][food_y]='*';
return;
}
else
{
food_x=(rand()%(width-2))+1;
food_y=(rand()%(height-2))+1;
i=1;
j=1;
}
}
}
}
bool Snake::invalid_snake(char map[][height],int snake_parts[][height])
{
int x,y,c=0;
for(x=0;x<width;x++)
for(y=0;y<height;y++)
{
if((x==0 || x==width-1 || y==0 || y==height-1) && map[x][y]==char(254))
c=1;
if(check[x][y]==1 && map[x][y]==char(254))
c=1;
}
if(c==1) return true;
else return false;
}
bool Snake::is_food(char map[][height],int food_x,int food_y)
{
int x,y,c=0;
for(x=1;x<width-1;x++)
for(y=1;y<height-1;y++)
if(map[x][y]==char(254) && x==food_x && y==food_y)
c=1;
if(c==1) return true;
else return false;
}
void Snake::movement(char map[][height],int snake_position[][height],int eating)
{
int i,x,y;
for(i=lenght;i>0;i--)
{
if(i==lenght)
{
for(x=1;x<width-1;x++)
{
for(y=1;y<height-1;y++)
{
if(snake_position[x][y]==i && map[x][y]== char(233))
{
if(eating==0)
{
map[x][y]=' '; snake_position[x][y]=0;
x=width-2;
y=height-2;
}
else if(eating==1)
{
map[x][y]= char(233); snake_position[x][y]=lenght+1;
lenght++;
x=width-2;
y=height-2;
}
}
}
}
}
else if(i>1 && i<lenght)
{
for(x=1;x<width-1;x++)
{
for(y=1;y<height-1;y++)
{
if(snake_position[x][y]==i && map[x][y]== char(233))
{
snake_position[x][y]=i+1;
x=width-2;
y=height-2;
}
}
}
}
else if(i==1)
{
for(x=1;x<width-1;x++)
{
for(y=1;y<height-1;y++)
{
if(snake_position[x][y]==i && map[x][y]==char(254))
{
movecheck:
if(kbhit())
{
if(GetAsyncKeyState(VK_UP)) keyboard = 'u';
else if(GetAsyncKeyState(VK_DOWN)) keyboard = 'd';
else if(GetAsyncKeyState(VK_LEFT)) keyboard = 'l';
else if(GetAsyncKeyState(VK_RIGHT)) keyboard = 'r';
}
if(keyboard!='u' && keyboard!='d' && keyboard!='l' && keyboard!='r')
{
map[x][y]=char(233); snake_position[x][y]=i+1;
if(snake_position[x-1][y]==i+2)
{
map[x+1][y]=char(254); snake_position[x+1][y]=1;
return;
}
else if(snake_position[x+1][y]==i+2)
{
map[x-1][y]=char(254); snake_position[x-1][y]=1;
return;
}
else if(snake_position[x][y+1]==i+2)
{
Sleep(50);
map[x][y-1]=char(254); snake_position[x][y-1]=1;
return;
}
else if(snake_position[x][y-1]==i+2)
{
Sleep(50);
map[x][y+1]=char(254); snake_position[x][y+1]=1;
return;
}
}
else if (keyboard=='u')
{
if(snake_position[x][y-1]==0)
{
map[x][y]= char(233); snake_position[x][y]=i+1;
map[x][y-1]=char(254); snake_position[x][y-1]=1;
return;
}
else
{
keyboard='n';
goto movecheck;
}
}
else if(keyboard=='d')
{
if(snake_position[x][y+1]==0)
{
map[x][y]= char(233); snake_position[x][y]=i+1;
map[x][y+1]=char(254); snake_position[x][y+1]=1;
return;
}
else
{
keyboard='n';
goto movecheck;
}
}
else if(keyboard=='l')
{
if(snake_position[x-1][y]==0)
{
map[x][y]= char(233); snake_position[x][y]=i+1;
map[x-1][y]=char(254); snake_position[x-1][y]=1;
return;
}
else
{
keyboard='n';
goto movecheck;
}
}
else if(keyboard=='r')
{
if(snake_position[x+1][y]==0)
{
map[x][y]= char(233); snake_position[x][y]=i+1;
map[x+1][y]=char(254); snake_position[x+1][y]=1;
return;
}
else
{
keyboard='n';
goto movecheck;
}
}
}
}
}
}
}
}
void Snake::options()
{
char selection;
system("cls");
while(true)
{
system("cls");
std::cout << std::endl;
std::cout << " Options" << std::endl << std::endl;
std::cout << " Choose dificulty <1>" << std::endl;
std::cout << " Rules <2>" << std::endl;
std::cout << " Credits <3>" << std::endl << std::endl;
std::cout << " Go back <4>" << std::endl << std::endl;
std::cin >> selection;
if(selection=='1') difficulty();
else if(selection=='2') rules();
else if(selection=='3') credits();
else if(selection=='4') return;
else system("cls");
}
}
void Snake::pause()
{
char c;
std::cout << std::endl;
std::cout << "Game paused. Press 'p' to return. ";
std::cin >> c;
if(c=='p') return;
}
bool Snake::poison_snake(char map[][height],int snake_parts[][height], int x1, int x2, int y1, int y2)
{
int c = 0;;
int x,y;
for(x=0;x<width;x++)
for(y=0;y<height;y++)
if(((x==x1 && y==y1) || (x==x2 && y==y2)) && map[x][y]==char(254)) c=1;
if(c==1) return true;
else return false;
}
void Snake::rules()
{
system("cls");
std::cout << " \nSNAKE GAME \nThe goal is to eat as much food as you can without hit the walls or snake tail. \nYou can move your snake using arrows keys. HAVE FUN !\n\n\n";
std::cout << " \nPOISON CHALLENGE \nThere are 10 food items on the table. 2 of them are poisoned!!\nTo win you have to eat all 8 healty foods. GOOD LUCK !\n\n";
std::cout << "\npress 1 to return\n";
char selection;
std::cin >> selection;
if(selection==1) return;
else system("cls");
}
void Snake::show_map(char map[][height],int score)
{
int x=width;
int y=height;
int i,j;
color(155);
for(i=0;i<y;i++)
for(j=0;j<x;j++)
{
if(j<(x-1)) std::cout << map[j][i];
if(j==(x-1)) std::cout << map[j][i] << std::endl;
}
color(7);
std::cout << std::endl;
std::cout << "Your score: " << score;
}
Snake::Snake()
{
std::cout << std::endl << std::endl;
std::cout << "\tMENU" << std::endl << std::endl;
std::cout << " Snake game <1>" << std::endl;
std::cout << " Poison challenge <2>" << std::endl;
std::cout << " Options <3>" << std::endl;
std::cout << " Exit <4>" << std::endl << std::endl;
}
bool Snake::is_food_pgame(char map[][height], char mapfood[][height])
{
int c =0;
for(int x=0;x<width;x++)
for(int y=0;y<height;y++)
if(mapfood[x][y]=='*' && map[x][y]==char(254)) c=1;
if(c==1) return true;
else return false;
}
void Snake::start_game()
{
char map[width][height];
int snake_position[width][height];
int i, j, food_x, food_y, x, y, score=0;
int eating;
create_map(map);
generate_food(map,food_x,food_y);
for(y=1;y<height;y++)
{
for(x=1;x<width;x++)
{
snake_position[x][y]=0;
}
}
map[27][10]= char(254);
map[26][10]= char(233);
map[25][10]= char(233);
map[24][10]= char(233);
snake_position[24][10]=4;
snake_position[25][10]=3;
snake_position[26][10]=2;
snake_position[27][10]=1;
system("cls");
show_map(map,score);
lenght=4;
while(true)
{
eating=0;
Sleep(diff*400);
if(kbhit())
{
keyboard=getch();
if(keyboard=='p') pause();
goto movemake;
}
movemake:
{
for(x=1;x<width-1;x++)
for(y=1;y<height-1;y++)
if(map[x][y]== char(233)) check[x][y]=1;
else check[x][y]=0;
if(is_food(map,food_x,food_y)==true)
{
eating=1;
score=score+1;
movement(map,snake_position,eating);
generate_food(map,food_x,food_y);
}
else movement(map,snake_position,eating);
if(invalid_snake(map,snake_position)==true) goto gameEnd;
else goto LoopEnd;
}
LoopEnd:
{
system("cls");
show_map(map,score);
}
}
gameEnd:
{
game_over(score);
return;
}
}
void Snake::poison_game()
{
char map[width][height]; char mapfood[width][height];
int snake_position[width][height];
int i, j, food_x, food_y, poison_x1=0, poison_y1, poison_x2, poison_y2, x, y, score=0;
int eating, win = 8;
bool p;
create_map(map);
int c=0;
while(c<8)
{
food_x=(rand()%(width-2))+1;
food_y=(rand()%(height-2))+1;
if(map[food_x][food_y]==' ')
{
mapfood[food_x][food_y] = '*';
map[food_x][food_y] = '*';
c+=1;
}
}
c=0;
while(c<2)
{
food_x=(rand()%(width-2))+1;
food_y=(rand()%(height-2))+1;
if(map[food_x][food_y]==' ')
{
map[food_x][food_y] = '*';
if(poison_x1 == 0)
{
poison_x1 = food_x;
poison_y1 = food_y;
}
else
{
poison_x2 = food_x;
poison_y2 = food_y;
}
c+=1;
srand(time(0));
}
}
for(y=1;y<height;y++)
for(x=1;x<width;x++)
snake_position[x][y]=0;
map[27][10]= char(254);
map[26][10]= char(233);
map[25][10]= char(233);
map[24][10]= char(233);
snake_position[24][10]=4;
snake_position[25][10]=3;
snake_position[26][10]=2;
snake_position[27][10]=1;
system("cls");
show_map(map,99);
lenght=4;
while(true)
{
eating=0;
Sleep(diff*400);
if(kbhit())
{
keyboard=getch();
if(keyboard=='p') pause();
goto movemake;
}
movemake:
{
for(x=1;x<width-1;x++)
for(y=1;y<height-1;y++)
if(map[x][y]== char(233)) check[x][y]=1;
else check[x][y]=0;
movement(map,snake_position,eating);
if(invalid_snake(map,snake_position)==true)
{
std::cout << "\n\nGAME OVER ! You lose.\n";
std::cout << "\n Play again ? [y/n]\n";
char selection;
std::cin >> selection;
if(selection=='y') poison_game();
else
{
system("cls");
main();
}
return;
}
else if(poison_snake(map,snake_position,poison_x1,poison_x2,poison_y1,poison_y2)==true)
{
color(42);
std::cout << "\n\nYou got poisoned!\n";
color(7);
std::cout << "\n Play again ? [y/n]\n";
char selection;
std::cin >> selection;
if(selection=='y') poison_game();
else
{
system("cls");
main();
}
return;
}
else if(is_food_pgame(map,mapfood)==true) win--;
else if(win==0)
{
std::cout << std::endl << std::endl;
color(156);
std::cout << " Congrats !! YOU WON.\n";
color(7);
Sleep(4000);
system("cls");
main();
}
else
{
system("cls");
show_map(map,win);
}
}
}
}