# Snake game with a sound system

Is there any way to improve it?

#include <iostream>
#include <windows.h>
#include"MMSystem.h"
#include <conio.h>
#include <fstream>
#include <ctime>
#include <string>
#include <string.h>

using namespace std;

/****************************************************/

/**<Stores Player's Name and Score>*/
struct player
{
string name;
int score;
};
/****************************************************/
const int mx1=1,mx2=36,my1=1,my2=20;
int D=3;
int x=(mx2+mx1)/2;
int y=(my2+my1)/2;
bool running=true;
player current;
const int Total_Players=10;
unsigned int z=0;
player high[Total_Players+1];
char MUSIC[100];

/****************************************************/
/**< Function to go to any (x,y) cordinates on console screen */
void gotoxy(int x,int y)
{
/**< A predefined data type(struct) of windows.h */
COORD point;
point.X=x;
point.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),point);
}
/***************************************************/
/**< Prints Highscore >**/
void score_print()
{
system("CLS");
running=true;
gotoxy(30,1);
cout<<"HIGH-SCORES";
for(int i=0;i<Total_Players;i++)
{
gotoxy(20,3+i+i);
cout<<i+1<<".";
gotoxy(28,3+i+i);
cout<<high[i].name;
gotoxy(52,3+i+i);
cout<<high[i].score<<endl;
}
gotoxy(20,(2*Total_Players)+3);
cout<<"Press Enter to go to main menu";
while(running)
{
if(getch()==13)
running=false;
}

}
/****************************************************/
/**< class of game */
class game
{
/**< Variables used */
char FOOD;
int food;
int X[100],Y[100],X1[100],Y1[100];
char BODY[100];
int XF,YF;
int flag;
int temp;
/****************************************************/
/**< Function Prints the Map Boundaries */
void printmap()
{
char B;
B=218;
gotoxy(mx1,my1);
cout<<B;
B=191;
gotoxy(mx2,my1);
cout<<B;
B=217;
gotoxy(mx2,my2);
cout<<B;
B=192;
gotoxy(mx1,my2);
cout<<B;
for(int i=mx1+1;i<my2;i++)
{
B=179;
gotoxy(mx1,i);
cout<<B;
gotoxy(mx2,i);
cout<<B;
}
for(int i=my1+1;i<mx2;i++)
{
B=196;
gotoxy(i,my1);
cout<<B;
gotoxy(i,my2);
cout<<B;
}
gotoxy(mx2+5,5);
cout<<"PRESS Q TO QUIT";
gotoxy(mx2+5,7);
cout<<"PRESS ENTER TO PAUSE";
}

/****************************************************/
/**< Function to read key press' */
void keypress(int &x,int &y)
{
/**<
W      UP
A+D LEFT+RIGHT
S     DOWN
*/
int M=getch();
if(M==224)
M=getch();
/**< UP  */
if((M==72||M==119)&&y!=1)
{
y=-1;
x=0;
}
/**< DOWN */
if((M==80||M==115)&&y!=-1)
{
y=1;
x=0;
}
/**< RIGHT */
if((M==77||M==100)&&x!=-1)
{
x=1;
y=0;
}
/**< LEFT */
if((M==75||M==97)&&x!=1)
{
x=-1;
y=0;
}
/**< Q - TO QUIT */
if(M==113)
{
running=false;
}
/**< I - FOR INSANE DIFFICULTY */
if(M==105)
{
/**< TOGGLE ON */
if(flag==0)
{
temp=D;
D=50;
flag=1;
}
/**< TOGGLE OFF */
else if(flag==1)
{
D=temp;
flag=0;
}
}
/**< ENTER - TO PAUSE */
if(M==13)
{
system("CLS");
gotoxy(25,5);
cout<<"PAUSED";
gotoxy(25,7);
system("PAUSE");
system("CLS");
}
}
/****************************************************/
/**< Function randomises food spawn location, updates score, increases snake length if food is eaten etc */
void Food(int x,int y)
{
/**< if food eaten( Head of snake meets food) */
if(XF==x&&YF==y)
{
F:
/**< get random coord. */
XF=rand()%(mx2-1)+(mx1+1);
YF=rand()%(my2-1)+(my1+1);
/**< to stop spawn on boundary */
if(XF==mx1||XF==mx2||YF==my1||YF==my2)
goto F;
/**< to stop spawn on snake's body */
for(int i=0;i<100;i++)
{
if(X[i]==XF&&Y[i]==YF)
goto F;
}
/**< increase score */
food++;
BODY[food-1]='o';
X[food]=X[food-1];
Y[food]=Y[food-1]+1;

}
/**< print the food */
gotoxy(XF,YF);
cout<<FOOD;
gotoxy(mx2+5,9);
cout<<"Score: "<<food;
}
/****************************************************/
/**< Function to update high-score >**/
void update_highscore()
{
fstream myfile;
getline(cin,current.name);
current.score=food;
while(current.name.length()<z)
{
current.name+=" ";
}
for(int i=0;i<Total_Players;i++)
{
if(current.score>=high[i].score)
{
for(int j=Total_Players-1;j>=i;j--)
{
high[j+1] = high[j];
}
high[i] =  current;
break;
}
}
myfile.open("bin\\score.txt");
if(myfile.is_open())
{
for(int i=0;i<Total_Players;i++)
{
myfile<<" "<<i+1<<","<<high[i].name<<","<<high[i].score<<endl;
}
myfile.close();
}
}

public:
game()
{
FOOD=153;
food=3;
XF=YF=10;
flag=0;
temp=D;
/**< initialization of all values for body and its coordinates */
for(int i=0;i<100;i++)
{
BODY[i]=' ';
X1[i]=0;
Y1[i]=-1;
X[i]=x;
Y[i]=y+i;
}
}
/*****************************************************/
/**< moves the snake's body and basically runs the game physics */
void body_move_print()
{
food=3;
system("CLS");
if(D==3)
D=500;
gotoxy(x,y);
int i=0;
int k=0;
BODY[0]=BODY[1]=BODY[2]='o';
running=true;
/**< running snake */
while(running)
{
printmap();
Sleep(D);
if(kbhit())
{
keypress(X1[0],Y1[0]);
}
gotoxy(0,0);
for(i=0;i<=food;i++)
{
X[i]+=X1[i];
Y[i]+=Y1[i];
gotoxy(X[i],Y[i]);
cout<<BODY[i];
}
for(i=3;i<food;i++)
{
if(X[0]==X[i]&&Y[0]==Y[i])
{
k=10;
break;
}
}
for(i=food;i>0;i--)
{
X1[i]=X1[i-1];
Y1[i]=Y1[i-1];
}
Food(X[0],Y[0]);
if(X[0]==mx1||X[0]==mx2||Y[0]==my1||Y[0]==my2||k==10)
{
running=false;
i=600;
while(i<1100)
{
Beep(i,50);
i+=150;
}
}
}
/**< game over */
for(i=0;i<10;i++)
{
if(kbhit())
{
if(getch()==13)
break;
}
Sleep(100);
system("CLS");
gotoxy(30,20-i);
cout<<"GAMEOVER!!";
gotoxy(30,20-i+1);
cout<<"SCORE: "<<food;
}
system("CLS");
gotoxy(30,20-i);
cout<<"GAMEOVER!!";
gotoxy(30,20-i+1);
cout<<"SCORE: "<<food;
gotoxy(30,20-i+2);
cout<<"NAME:";
update_highscore();
gotoxy(30,20-i+3);
system("PAUSE");
score_print();
}
};

/****************************************************/
/**< sets difficulty level */
void diff()
{
system("CLS");
int L;
D=3;
char D_=221;
int i=1,j=1;
for(i=0;i<D;i++)
{
gotoxy(33+i,9);
cout<<D_;
gotoxy(33,11);
cout<<"-";
gotoxy(41,11);
cout<<"+";
cout<<"\n\n     LEFT or RIGHT ARROWS to increase or decrease difficulty. Enter to select";
}
while(j)
{

if(kbhit())
{
L=getch();
if(L==224)
L=getch();
if(L==77&&D<=8)
D++;
else if(L==75&&D>1)
D--;
else if(L==13)
{
D=800-D*75;
break;
}
system("CLS");
for(i=0;i<D;i++)
{
gotoxy(33+i,9);
cout<<D_;
gotoxy(33,11);
cout<<"-";
gotoxy(41,11);
cout<<"+";
cout<<"\n\n     LEFT or RIGHT ARROWS to increase or decrease difficulty. Enter to select";
}
}
}

}

/****************************************************/
/**< high score table maker>*/
void score()
{
fstream myfile;
string X[Total_Players];
myfile.open("bin\\score.txt");
if(myfile.is_open())
{
while(!myfile.eof())
{

for(int i=0;i<Total_Players;i++)
{
getline(myfile,X[i],',');
getline(myfile,high[i].name,',');
myfile>>high[i].score;

}
}
myfile.close();
}
for(int i=0;i<Total_Players;i++)
{
if(z<high[i].name.length())
{
z=high[i].name.length();
}
}
}
/****************************************************/
/**< Sound System >**/
/**< 1. Plays the music >**/
void sound_play()
{
/**< This line plays the background music on a loop >**/
PlaySound(MUSIC, NULL, SND_ASYNC|SND_FILENAME|SND_LOOP);
}

/**< Lets you choose the song >**/
void music_select()
{
int L=0,y=5;
running=true;
system("CLS");
gotoxy(30,3);
cout<<"/**Song List**/";
gotoxy(23,5);
cout<<"1. What does the fox say - Ylvis";
gotoxy(23,7);
cout<<"2. Where my baes at - Miranda Sings";
gotoxy(23,9);
cout<<"3. Assassin's Creed Unity Theme";
gotoxy(10,11);
cout<<"*UP or DOWN to Navigate. ENTER to select. BACKSPACE to go back.*";
gotoxy(20,y);
cout<<"->";
while(running)
{
if(kbhit())
{
L=getch();
if(L==224)
L=getch();
if(L==72)
{
if(y==5)
y=9;
else
y=y-2;
}
else if(L==80)
{
if(y==9)
y=5;
else
y=y+2;
}
else if(L==13)
{
if(y==5)
{
strcpy(MUSIC,"What_Does_The_Fox_Say.wav");
sound_play();
}
else if(y==7)
{
strcpy(MUSIC,"bin\\Where_My_Baes_At.wav");
sound_play();
}
else if(y==9)
{
strcpy(MUSIC,"bin\\Assassin's_Creed_Unity_Theme.wav");
sound_play();
}
}
else if(L==8)
{
running=false;
}
system("CLS");
gotoxy(30,3);
cout<<"/**Song List**/";
gotoxy(23,5);
cout<<"1. What does the fox say - Ylvis";
gotoxy(23,7);
cout<<"2. Where my baes at - Miranda Sings";
gotoxy(23,9);
cout<<"3. Assassin's Creed Unity Theme";
gotoxy(10,11);
cout<<"*UP or DOWN to Navigate. ENTER to select. BACKSPACE to go back.*";
gotoxy(20,y);
cout<<"->";
}

}
}

/****************************************************/
/**< main menu of game */
{
start:
int L=0,y=7;
running=true;
system("CLS");
gotoxy(30,5);
cout<<"/****SNAKE****/";
gotoxy(30,7);
cout<<"*Start Game";
gotoxy(30,9);
cout<<"*Difficulty";
gotoxy(30,11);
cout<<"*Songs";
gotoxy(30,13);
cout<<"*High-score";
gotoxy(30,15);
cout<<"*Exit";
gotoxy(15,17);
cout<<"Press UP or DOWN to navigate and ENTER to select";
gotoxy(30,19);
cout<<"/*HELP*/";
gotoxy(15,21);
cout<<"*Use ARROW KEYS or W,A,S,D to move the snake.";
gotoxy(15,22);
cout<<"*Q to pause.";
gotoxy(15,23);
gotoxy(27,y);
cout<<"->";
while(running)
{
if(kbhit())
{
L=getch();
if(L==224)
L=getch();
if(L==72)
{
if(y==7)
y=15;
else
y=y-2;
}
else if(L==80)
{
if(y==15)
y=7;
else
y=y+2;
}
else if(L==13)
{
if(y==7)
running=false;
else if(y==9)
{
diff();
goto start;
}
else if(y==11)
{
music_select();
goto start;
}
else if(y==13)
{
score_print();
goto start;
}
else if(y==15)
{
system("CLS");
exit(0);
}
}
system("CLS");
gotoxy(30,5);
cout<<"/****SNAKE****/";
gotoxy(30,7);
cout<<"*Start Game";
gotoxy(30,9);
cout<<"*Difficulty";
gotoxy(30,11);
cout<<"*Songs";
gotoxy(30,13);
cout<<"*High-score";
gotoxy(30,15);
cout<<"*Exit";
gotoxy(15,17);
cout<<"Press UP or DOWN to navigate and ENTER to select";
gotoxy(30,19);
cout<<"/*HELP*/";
gotoxy(15,21);
cout<<"*Use ARROW KEYS or W,A,S,D to move the snake.";
gotoxy(15,22);
cout<<"*Q to pause.";
gotoxy(15,23);
gotoxy(27,y);
cout<<"->";
}
}
}

/****************************************************/

int main()
{
/**<Initializing the song for first run >**/
strcpy(MUSIC,"bin\\What_Does_The_Fox_Say.wav");
sound_play();

start:
score();
srand(time(0));
game GAME;
GAME.body_move_print();
goto start;
getch();
return 0;
}

• Also, there's (almost) always room for improvement. Is there anything specific you're looking for? Your current statement isn't wrong, but performance/memory/maintainability improvements aren't the same and improving one can make the other worse. – Mast Jun 16 '15 at 9:04
• Thanks for telling me @Mast . Yeah .. I did find a problem in the performance. It lags a little if I'm not running it straight out of the IDE – Devang Jayachandran Jun 16 '15 at 9:06
• I'll update the question as soon as possible – Devang Jayachandran Jun 16 '15 at 9:06
• @DevangJayachandran: As a side not. By placing the code here you are also placing it under the CC license (see the link at the bottom of the page). The cost of us doing a review is that you let everybody use your code. – Martin York Jun 16 '15 at 14:53
• I don't mind that. :P – Devang Jayachandran Jun 16 '15 at 15:15

There are many improvements that could be applied to this code. As it stands, it has several issues or "code smells":

• Use of global data: You are using C++, which supports Object-Oriented programming, and you also already make use of classes in your program, so why declare a bunch of global data when all that could very easily be properly scoped into classes or functions?

• Very weak names for global variables: To further aggravate the issue of the globals, some are declared with ludicrous names, such as x, y and D. Those will not only clash with other names you might want to declare, but also convey no meaning or information. The more visible is the scope of a variable, the better and more descriptive its name should be. Loop counter variables are commonly named i, j and k because they have tiny scopes (and for historical reasons, also).

• Magic numbers: Your code is swamped with magic numbers, which makes it very hard to understand and create a mental model of the thing.

• Using namespace: Very questionable practice to say the least. Read more about it here.

• Use of goto: In main(), where a simple for(;;) or while would do. That goto also threads over the declaration of GAME, which is a usage style full or caveats and not well known by most programmers. A 'traditional' loop would be much clearer. There are other instances too that seem to exist because you've failed to better divide the code into functions.

• Lack of spacing makes it very hard to read: Compare this:

if(X[0]==mx1||X[0]==mx2||Y[0]==my1||Y[0]==my2||k==10)


To a more spaced equivalent:

if (X[0] == mx1 || X[0] == mx2 || Y[0] == my1 || Y[0] == my2 || k == 10)


My opinion, but I think the issues mentioned above makes it hard to review the code in more detail. So my suggestion would be that you first fix those issues and then post a followup question to get more reviews. Bet of luck to you.

• There is no goto above game.. That's making it public – Devang Jayachandran Jun 17 '15 at 15:48
• @DevangJayachandran There is a goto that jumps over the initialization of an instance of the game class inside 'main'. That's what I meant. – glampert Jun 17 '15 at 15:54
• Where exactly do u mean? – Devang Jayachandran Jun 17 '15 at 15:58
• Aah! Works fine in mingw – Devang Jayachandran Jun 17 '15 at 15:59
• @DevangJayachandran GOTO is still considered harmful. Even when not considering all other points against it, it's not idiomatic C++. – Mast Jun 18 '15 at 11:30