C Programming Reference >> C Games Programming Tutorials >>
Snake 1.0equisite Knowledege
27/05/06 - 5361 Views - Ratings :    4.13 of 5 / 53 Votes
Level - Intermediate
Here you will learn how to create a game called Snake through C . Snake can be surely decribe as one of the best games of all time.Though simple in concept this game is very addictive and has ability to mesmerize the players. Concept is to create a snake which move around a given screen according to user input. It eats objects randomly emerging on screen and if succesfull in eating them it becomes larger in size and gains score. The snake dies ie. game is over when it either hits an obstacle or hit its own body. Designing Snake game in C is relatively easy to program and beginners can give it a shot, if they undestand carry on otherwise read the basic tutorials first and then come back to design your own snake game using C. Read last section for source code & executable to see the power of this tutorial.
Compiler Used - Dev C++ 4.9.9.2
Graphic Library Used - WINBGIm (All Instruction of Setup Included in tutorial)
Operating System Used - Windows XP Professional
Contents -
1. Requirements
2. Getting Started
3. Coding Main
4. Creating a Graphic Window
5. Game Data
6. Screen Intilization
7. Game Engine
8. Moving Snake
9. Taking Input
10. Game Physics
11. Fianl Words
12. What Next?
1. Requirements
From Programming point of view i am assuming you have some knowledge of C and we will build this program from scratch for better understanding . If you absolute beginner check this out if you dont understand go through basic tutorials first.
But before you start you need some tools.
First you must install Free Devc++ IDE .
Next download these library files and paste them in their respective folder. Path should modified according to your installation path.
graphics.h (Download to C:\Dev-Cpp\include), Overwrite the original one
libbgi.a (Download to C:\Dev-Cpp\include)
Make sure file name and path are correct. You dont need them to play game after compilation but you do need them during compilation.
Thats all now you are ready, lets get this show on the road.
Back To Top
2. Getting Started
Go to Start >> Programs >> BloodShed Dev C++ >> Dev C++ (Path can be diffrent if change during installation).
Goto Menu - File >> New >> Project
Choose Empty Project , Click C++ Project (We will use C Concepts but graphic library we use is designed for C++) and Write Snake in name textbox as shown in screen shot below.

Then Save screen appears use same name Snake to save -
Now press Alt+p to open project option. In project option goto parameter tab where you shall feed information about graphics library to linker. In linker multi text box write the following command (be precisely exact) -
-lbgi
-lgdi32
-lcomdlg32
-luuid
-loleaut32
-lole32
Your project option screen should look like this -
Press Ok.
Now press Ctrl+N, A Message Box will appear asking to add new file to project click Yes.

Press Ctrl + S to save the new file and name it Snake_Code -
.
Finally your screen should look like this -
Back To Top
3. Coding Main
First thing a program should do is to include header files and code main. Main act as entry point of program and is the first function called by your program, value it returns is used by operating system. Only header we will be needing at present is graphics.h. Including unnecessary header files increase the size of the code and compile time. Next we create an parameterless int returning main with no code at present in the source file Snake_Main. Your Code should look like this -
#include "graphics.h"
int main ()
{
return 0;
} |
Back To Top
4. Creating A Graphics Window
Before using any graphic function we must create a window in which these graphic functions would display this output. Creting graphics window is a resource intensive operation and should be performed only once in the program to enchance the speed of program which is a very essential need in games programming in which FPS (Frame Rate Per Second) should be as high as possible.
We use a WINBGIm graphic library function intiwindow defined as -
int initwindow(int width, int height, const char* title="Windows BGI", int left=0, int top=0, bool dbflag=false, closeflag=true);
Its has only 2 neccesary parameters width and height rest are optional and have default value if not specify. But they can be very useful in specializing your graphics window according to your need.
Parameters means -
width - width of your window.
height - height of your window.
title - title of your window to be displayed in title bar.
left - left starting postion of the window.
top - top strating position of the window
dbflag - Enables/Disable double buffering
closeflag - Wether thier is a close button on window title bar.
Now we create the game window in our code as follow -
#include <graphics.h>
int main ()
{
initwindow(1018, 736,"Snake 1.0"); // Create the Snake Window, paramter value is optimize for mode 1024 * 740
getch (); // Holds the window for a while
closegraph (); // This close down the graphics
return 0;
}
|
Heres a screenshot of what you will obtain -
Back To Top
5. Game Data
Now we create data your game needs . In this game we need following data -
We need a int variable to record score intialized to 0.
We need a int variable to control game speed intialized to a fixed value depending upon difficulty.
We need a structure to store the snake information which have following data -
Length of Snake as int variable initialize to minimum length .
Snakes Head X Coordinate as int variable intialized to starting position.
Snake Heads Y Coordinate as int variable intialized to starting position.
Snake Head Increment Direction as int variable intialized to starting position.
Snakes Tails X Coordinate as int variable intialized to starting position.
Snake Tails Y Coordinate as int variable intialized to starting position
Snake Tail Increment Direction as int variable intialized to starting position.
2 int arrays to store xcoordinate & ycoordinate of postions at which there is a bend in snake movement due to change in direction by the user.
In the end we create a variable called Snake of above Structure type.
We also create function called intigamedata to intialize all our game data once on the starting of game.
Also note that there can be only 4 direction of snake movement which can be quantize in int values as follow -
1 - Left
2 - Right
3 - Up
4 - Down
Any other direction value if present will be ignored.
Now accomodating storage our code becomes -
// Header Files
#include <graphics.h>
// Macros
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
//Game Data
int score; //Keeps the count of game score
int gamedelay;//Lower the game delay faster is the game speed.
struct Snake_Data {
int length;
int head_x; // Stores Head X Coordinate
int head_y; // Stores Head Y Coordinate
int head_dir; // Stores Head Direction
int tail_x; // Stores Tail X Coordinat
int tail_y; // Stores Tail Y Coordinat
int tail_dir; // Stores Tail Direction
int bend_x [1000]; //Stores X Bend Coordinate Declare it big enough to accomodate maximum bends
int bend_y[1000]; // Stores Y Bend Coordinate Declare it big enough to accomodate maximum bends
} Snake; // Declares a variable of the structure
// User - Defined functions -
void initgamedata ( ) //Snakes starting coordinate if you modify any one make sure also modify dependent values
{
int i;
Snake.length = 100;
Snake.head_x = 200;
Snake.head_y = 200;
Snake.head_dir = RIGHT;
Snake.tail_x = Snake.head_x- Snake.length;
Snake.tail_y = Snake.head_y;
Snake.tail_dir = RIGHT;
for (int i = 0; i <1000;i++) // There is no bend initally
{
Snake.bend_x[i] = 0;
Snake.bend_y[i] = 0;
}
score = 0;
gamedelay = 1000; // Should be change according to game speed need.
}
// Main Function
int main ()
{
initwindow(1018, 736,"Snake 1.0"); // Create the Snake Window with value is optimize for mode 1024 * 768
initgamedata ();
getch (); // Holds the window for a while
closegraph (); // This close down the graphics
return 0;
}
|
Back To Top
6. Screen Initialization
Now we create a function which intializes the game screen to intial positon.
We draw the boundary wall to which if snake collides game is over.
We also draw a score box which will display value of score.
And Last we draw snake to its intial postion.
This function is also called once by the main program in starting of the game.
We also introduce a header file stdio.h to use sprintf.
We use a function called initscreen called in main to do this job for us and now our C source code becomes - .
// Header Files
#include <graphics.h>
#include <stdio.h>
// Macros
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
//Game Data
int score; //Keeps the count of game score
int gamedelay;//Lower the game delay faster is the game speed.
struct Snake_Data {
int length;
int head_x; // Stores Head X Coordinate
int head_y; // Stores Head Y Coordinate
int head_dir; // Stores Head Direction
int tail_x; // Stores Tail X Coordinat
int tail_y; // Stores Tail Y Coordinat
int tail_dir; // Stores Tail Direction
int bend_x [1000]; //Stores X Bend Coordinate Declare it big enough to accomodate maximum bends
int bend_y[1000]; // Stores Y Bend Coordinate Declare it big enough to accomodate maximum bends
} Snake; // Declares a variable of the structure
// User - Defined functions -
void initscreen ( ) //Draws Intial Screen.
{
int i;
char scorestring [100];
//Draw Boundary
setcolor (4);
line (10,10,10,700);
line (1008,10,1008,700);
line (10,700,1008,700);
line (10,10,1008,10);
//Write Score on scree
sprintf (scorestring, "Score : %d", score);
outtextxy (20,710, scorestring);
//Draw Intial Snake Body
for (int i = Snake.length; i>0;i--) //This part should be redesigned for change of code of intial values { putpixel (Snake.head_x-i,Snake.head_y,15); }
}
void initgamedata ( ) //Snakes starting coordinate if you modify any one make sure also modify dependent values
{
int i;
Snake.length = 100;
Snake.head_x = 200;
Snake.head_y = 200;
Snake.head_dir = RIGHT;
Snake.tail_x = Snake.head_x- Snake.length;
Snake.tail_y = Snake.head_y;
Snake.tail_dir = RIGHT;
for (int i = 0; i <1000;i++) // There is no bend initally
{
Snake.bend_x[i] = 0;
Snake.bend_y[i] = 0;
}
score = 0;
gamedelay = 1000; // Should be change according to game speed need.
}
// Main Function
int main ()
{
initwindow(1018, 736,"Snake 1.0"); // Create the Snake Window with value is optimize for mode 1024 * 768
initgamedata ();
initscreen ();
getch (); // Holds the window for a while
closegraph (); // This close down the graphics
return 0;
}
|
Here is a screen shot of what we have developed so far together -
Back To Top
7. Game Engine
This is most important function in our program. Its job is to bring together various parts of our game under on roof and combine them to produce our ulitmate snake game.
All game processing will be done in this game engine this function is called by main once and it retains control of the execution till the game ends.
It has three important parts -
1. Game Progression - Moves the snake
2. User Input - Effects the game on basis of user input.
3. Game Physics - It calculates the outcome of situation and implement games logic such as increasing score, declaring game over etc.
Our Game Engine is basically an infinite while loop which runs forever. It breaks only when the game is over and when it breaks game exits.
The game engine also controls game speed by introducing delay of time between two loops this has a severe effect on your FPS. You want game to fast enough to playable and not slow enough to be challenging. The FPS is decided by your game engine but may also be affected by hardware processing power and efficiency of algoritm and mostly on graphic capability of your graphic card and its driver.
Also now we dont have any need of getch and closegraph in main because control of program will never reach them.
Though Game Engines internal part are not implemented and nothing is done by it, how its is implemented is shown in our code below -
// Header Files
#include <graphics.h>
#include <stdio.h>
// Macros
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
//Game Data
int score; //Keeps the count of game score
int gamedelay;//Lower the game delay faster is the game speed.
struct Snake_Data {
int length;
int head_x; // Stores Head X Coordinate
int head_y; // Stores Head Y Coordinate
int head_dir; // Stores Head Direction
int tail_x; // Stores Tail X Coordinat
int tail_y; // Stores Tail Y Coordinat
int tail_dir; // Stores Tail Direction
int bend_x [1000]; //Stores X Bend Coordinate Declare it big enough to accomodate maximum bends
int bend_y[1000]; // Stores Y Bend Coordinate Declare it big enough to accomodate maximum bends
} Snake; // Declares a variable of the structure
// User - Defined functions -
void gameengine ()//Soul of our game.
{
while (1)
{
delay (1000);
}
}
void initscreen ( ) //Draws Intial Screen.
{
int i;
char scorestring [100];
//Draw Boundary
setcolor (4);
line (10,10,10,700);
line (1008,10,1008,700);
line (10,700,1008,700);
line (10,10,1008,10);
//Write Score on scree
sprintf (scorestring, "Score : %d", score);
outtextxy (20,710, scorestring);
//Draw Intial Snake Body
for (int i = Snake.length; i>0;i--) //This part should be redesigned for change of code of intial values { putpixel (Snake.head_x-i,Snake.head_y,15); }
}
void initgamedata ( ) //Snakes starting coordinate if you modify any one make sure also modify dependent values
{
int i;
Snake.length = 100;
Snake.head_x = 200;
Snake.head_y = 200;
Snake.head_dir = RIGHT;
Snake.tail_x = Snake.head_x- Snake.length;
Snake.tail_y = Snake.head_y;
Snake.tail_dir = RIGHT;
for (int i = 0; i <1000;i++) // There is no bend initally
{
Snake.bend_x[i] = 0;
Snake.bend_y[i] = 0;
}
score = 0;
gamedelay = 1000; // Should be change according to game speed need.
}
// Main Function
int main ()
{
initwindow(1018, 736,"Snake 1.0"); // Create the Snake Window with value is optimize for mode 1024 * 768
initgamedata ();
initscreen ();
gameengine ();
return 0;
}
|
Back To Top
8. Move Snake -
Now we design a function which moves your snake on the basis of data stored in the structure Snake. We want this function to be most efficient as its algoritm determines the FPS of your Snake game heavily. We shall try to make the calculation as low as possible but still strong enough to provide all the desired function.
As you know in a snake game as head of the snake moves forward the whole body follows so what we have to do move the snkae on screen in minimum possible steps is -
Put a new snake color pixel in the next head position and increment old the head positon to new head postion. New head position is determined by mathematical calculation from old head postion using value stored in head movement direction.
Put a new background color pixel in the last tail position and increment old the tail positon to new tail postion. New tail position is determined by mathematical calculation from old tail postion using value stored in tail movement direction.
The function name we use is movesnake and is shown in code below -
// Header Files
#include <graphics.h>
#include <stdio.h>
// Macros
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
//Game Data
int score; //Keeps the count of game score
int gamedelay;//Lower the game delay faster is the game speed.
struct Snake_Data {
int length;
int head_x; // Stores Head X Coordinate
int head_y; // Stores Head Y Coordinate
int head_dir; // Stores Head Direction
int tail_x; // Stores Tail X Coordinat
int tail_y; // Stores Tail Y Coordinat
int tail_dir; // Stores Tail Direction
int bend_x [1000]; //Stores X Bend Coordinate Declare it big enough to accomodate maximum bends
int bend_y[1000]; // Stores Y Bend Coordinate Declare it big enough to accomodate maximum bends
} Snake; // Declares a variable of the structure
// User - Defined functions -
void movesnake () //Moves The Snake Across the Screen
{
//Move the Head
if (Snake.head_dir == LEFT)
{
Snake.head_x --;
}
if (Snake.head_dir == RIGHT)
{
Snake.head_x ++;
}
if (Snake.head_dir == UP)
{
Snake.head_y --;
}
if (Snake.head_dir == DOWN)
{
Snake.head_y ++;
}
putpixel (Snake.head_x, Snake.head_y,15);
//Move the Tail
putpixel (Snake.tail_x, Snake.tail_y,0);
if (Snake.tail_dir == LEFT)
{
Snake.tail_x --;
}
if (Snake.tail_dir == RIGHT)
{
Snake.tail_x ++;
}
if (Snake.tail_dir == UP)
{
Snake.tail_y --;
}
if (Snake.tail_dir == DOWN)
{
Snake.tail_y ++;
}
}
void gameengine ()//Soul of our game.
{
while (1)
{
movesnake ();
delay (5);
}
}
void initscreen ( ) //Draws Intial Screen.
{
int i;
char scorestring [100];
//Draw Boundary
setcolor (4);
line (10,10,10,700);
line (1008,10,1008,700);
line (10,700,1008,700);
line (10,10,1008,10);
//Write Score on scree
sprintf (scorestring, "Score : %d", score);
outtextxy (20,710, scorestring);
//Draw Intial Snake Body
for (int i = Snake.length; i>0;i--) //This part should be redesigned for change of code of intial values
{
putpixel (Snake.head_x-i,Snake.head_y,15);
}
}
void initgamedata ( ) //Snakes starting coordinate if you modify any one make sure also modify dependent values
{
int i;
Snake.length = 100;
Snake.head_x = 200;
Snake.head_y = 200;
Snake.head_dir = RIGHT;
Snake.tail_x = Snake.head_x- Snake.length;
Snake.tail_y = Snake.head_y;
Snake.tail_dir = Snake.head_dir;
for (int i = 0; i <1000;i++) // There is no bend initally
{
Snake.bend_x[i] = 0;
Snake.bend_y[i] = 0;
}
score = 0;
gamedelay = 1000; // Should be change according to game speed need.
}
// Main Function
int main ()
{
initwindow(1018, 736,"Snake 1.0"); // Create the Snake Window with value is optimize for mode 1024 * 768
initgamedata ();
initscreen ();
gameengine ();
return 0;
}
|
Simlutaneous screen shot below shows the snake in motion -
Back To Top
9. User Input
Now we design a function which takes the user input from keyboard .
We use a inbuilt library function in WINBGIm kbhit ( ) which returns true if there is character in the input buffer and false otherwise.
IF there is a character then we use getch ( ) function to extract that character and match it with valid inputs to move the snake in that direction under a condition that the current snake moving direction is not exactly opposite to inout because snake cannot overun itself by making a 180 degree turn.
We have following keys defined -
Up arrow - Make the snake head move in up direction.. Does not work if snake is moving in downward direction
Down arrow - Make the snake head move in down direction.. Does not work if snake is moving in upward direction
Right arrow - Make the snake head move in right direction.. Does not work if snake is moving in left direction
Left arrow - Make the snake head move in left direction.. Does not work if snake is moving in right direction.
Also this function puts the value in the bent arrays at respective coordinate so that when the snake tail approaches that coordinate it changes direction. For this purpose this function also maintains a 2 static variable i and j which holds the current input index value and output index value of the arrays. For the same purpose we also introduce a code in this function to change in direction of tail.
We also introduce a new data parameter bent_dir which stores the direction of Bent this is neccesary to implent logic as along with coordinates of change we also want to know the dirction of change.
Below is the C Source Code we developed till now -
// Header Files
#include <graphics.h>
#include <stdio.h>
// Macros
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
//Game Data
int score; //Keeps the count of game score
int gamedelay;//Lower the game delay faster is the game speed.
struct Snake_Data {
int length;
int head_x; // Stores Head X Coordinate
int head_y; // Stores Head Y Coordinate
int head_dir; // Stores Head Direction
int tail_x; // Stores Tail X Coordinat
int tail_y; // Stores Tail Y Coordinat
int tail_dir; // Stores Tail Direction
int bend_x [1000]; //Stores X Bend Coordinate Declare it big enough to accomodate maximum bends
int bend_y [1000]; //Stores Y Bend Coordinate Declare it big enough to accomodate maximum bends
int bend_dir [1000]; // Stores Bend direction when tail reaches that X Coordinate
} Snake; // Declares a variable of the structure
// User - Defined functions -
void userinput ()// This Function changes the direction of motion of snake according to input.
{
static int i = 0;
if ( i > 1000) i = 0; // Makes the bend array a circular queue
static int j = 0;
if ( j > 1000) j = 0;
char input;
if (kbhit ())
{
input = getch ();
//Change Respective Return value to our MACRO Direction Code Value
if (input == 80) input = DOWN;
if (input == 72) input = UP;
if (input == 75) input = LEFT;
if (input == 77) input = RIGHT;
//Change head direction based on logic
if (input == LEFT && Snake.head_dir != RIGHT && Snake.head_dir != LEFT)
{
Snake.head_dir = LEFT;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = LEFT;
i++;
}
if (input == RIGHT && Snake.head_dir != LEFT && Snake.head_dir != RIGHT)
{
Snake.head_dir = RIGHT;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = RIGHT;
i++;
}
if (input == UP && Snake.head_dir != DOWN && Snake.head_dir != UP)
{
Snake.head_dir = UP;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = UP;
i++;
}
if (input == DOWN && Snake.head_dir != UP && Snake.head_dir != DOWN)
{
Snake.head_dir = DOWN;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = DOWN;
i++;
}
}
//Code to change the y direction at respective time
if (Snake.tail_x == Snake.bend_x [j] && Snake.tail_y == Snake.bend_y [j])
{
Snake.tail_dir = Snake.bend_dir [j];
j++;
}
}
void movesnake ()
{
//Move the Head
if (Snake.head_dir == LEFT)
{
Snake.head_x --;
}
if (Snake.head_dir == RIGHT)
{
Snake.head_x ++;
}
if (Snake.head_dir == UP)
{
Snake.head_y --;
}
if (Snake.head_dir == DOWN)
{
Snake.head_y ++;
}
putpixel (Snake.head_x, Snake.head_y,15);
//Move the Tail
putpixel (Snake.tail_x, Snake.tail_y,0);
if (Snake.tail_dir == LEFT)
{
Snake.tail_x --;
}
if (Snake.tail_dir == RIGHT)
{
Snake.tail_x ++;
}
if (Snake.tail_dir == UP)
{
Snake.tail_y --;
}
if (Snake.tail_dir == DOWN)
{
Snake.tail_y ++;
}
}
void gameengine ()//Soul of our game.
{
while (1)
{
movesnake ();
userinput ();
delay (5);
}
}
void initscreen ( ) //Draws Intial Screen.
{
int i;
char scorestring [100];
//Draw Boundary
setcolor (4);
line (10,10,10,700);
line (1008,10,1008,700);
line (10,700,1008,700);
line (10,10,1008,10);
//Write Score on scree
sprintf (scorestring, "Score : %d", score);
outtextxy (20,710, scorestring);
//Draw Intial Snake Body
for (int i = Snake.length; i>0;i--) //This part should be redesigned for change of code of intial values
{
putpixel (Snake.head_x-i,Snake.head_y,15);
}
}
void initgamedata ( ) //Snakes starting coordinate if you modify any one make sure also modify dependent values
{
int i;
Snake.length = 100;
Snake.head_x = 200;
Snake.head_y = 200;
Snake.head_dir = RIGHT;
Snake.tail_x = Snake.head_x- Snake.length;
Snake.tail_y = Snake.head_y;
Snake.tail_dir = Snake.head_dir;
for (int i = 0; i <1000;i++) // There is no bend initally
{
Snake.bend_x[i] = 0;
Snake.bend_y[i] = 0;
Snake.bend_dir[i] = 0;
}
score = 0;
gamedelay = 1000; // Should be change according to game speed need.
}
// Main Function
int main ()
{
initwindow(1018, 736,"Snake 1.0"); // Create the Snake Window with value which is optimize for mode 1024 * 768
initgamedata ();
initscreen ();
gameengine ();
return 0;
}
|
Here is a mulitple scale down screen shot of showing snake movements with bend due to user input.
Back To Top
10. Game Physiscs
This is going to be last function we are going to design in this tutorial. This is the last missing part of our game engine. It does the logic and physics of the our ultimate snake Game designed in C. This function does following task -
1. Create a food for snake to eat at random valid position.
2. Ends the game if the snake hit the boundary.
3. Ends the game if the snake hits own body.
4. If food succesfully eaten it increases the score and size of the snake.
We call this function game physics.
It also many game factors such as number of simultaneous food produce and the size of snake to be increased when it succesfully eat the food.
Note in the code below that we also introduce a new header time.h for library function srand and rand to produce random food.
To distribute load on function gamephysics we create a subfunction which return a random value using a sophisticated method of producing a random number between the two parameters passed to it. It is called randomvalue.
Also the logic used to determine wether food is eaten is simple. If the next pixel to which the snake is going to enter is of colour of food score incremetnation, Size of Snake Incrementation.
Also the logic used to determine collison is also same. If the next pixel to which the snake is going to enter is of colour of snake itself its a collison and game is over.
Now Final Code Of Our C Snake Game Becomes -
// Header Files
#include <graphics.h>
#include <stdio.h>
// Macros
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
//Game Data
int score; //Keeps the count of game score
int gamedelay;//Lower the game delay faster is the game speed.
struct Snake_Data {
int length;
int head_x; // Stores Head X Coordinate
int head_y; // Stores Head Y Coordinate
int head_dir; // Stores Head Direction
int tail_x; // Stores Tail X Coordinat
int tail_y; // Stores Tail Y Coordinat
int tail_dir; // Stores Tail Direction
int bend_x [1000]; //Stores X Bend Coordinate Declare it big enough to accomodate maximum bends
int bend_y [1000];
int bend_dir [1000]; // Stores Bend direction when tail reaches that X Coordinate
} Snake; // Declares a variable of the structure
// User - Defined functions -
int randomvalue (int starting, int ending) // Return a random int value between end and starting parameters
{
static int previous = 0;
int answer;
if (previous <0) previous = 0;
int difference = starting - ending;
time_t t;
srand((unsigned) time(&t));
for (int i = 0; i <previous;i++) rand ();
answer = (rand () % difference);
previous++;
return answer;
}
void gamephysics ()
{
static int foodcount = 0;//Keep Count of food
int futurex, futurey, futurepixel;
int i;
char scorestring [100];
if (foodcount < 500) //Adds a food if no food is present and upto maximum 500 food
{
int valid = 0;
int foodx;
int foody;
while (!valid)
{
foodx = randomvalue (15,1003);
foody = randomvalue (15,695);
if (getpixel (foodx,foody)!= 15)
{
putpixel (foodx,foody,2);
foodcount++;
valid = 1;
}
}
}
//Boundary Collision Check -
if (Snake.head_x <= 10 || Snake.head_x >= 1008 || Snake.head_y <= 10 || Snake.head_y >= 700)
{
outtextxy (499,345, "Game Over");
delay (3000);
exit (1);
}
//Get future value of head in int variable futurex and futurey and calculate the logic
futurex = Snake.head_x;
futurey = Snake.head_y;
if (Snake.head_dir == LEFT)
{
futurex --;
}
if (Snake.head_dir == RIGHT)
{
futurex ++;
}
if (Snake.head_dir == UP)
{
futurey --;
}
if (Snake.head_dir == DOWN)
{
futurey ++;
}
futurepixel = getpixel(futurex,futurey);
if (futurepixel == 2)//Food Eaten
{
foodcount --; //Reduce count
score++; //Increase Score
setcolor (0);//Rewrite Score
setfillstyle (0,0);
bar (11,701,1007, 735);
setcolor (4);
sprintf (scorestring, "Score : %d", score);
outtextxy (20,710, scorestring);
//Increase the size of snake by 100 pixel you can put as much as you want
if (Snake.tail_dir == UP)
{
for (i = 0; i<101;i++) putpixel (Snake.tail_x,Snake.tail_y+i,15);
Snake.tail_y +=100;
}
if (Snake.tail_dir == DOWN)
{
for (i = 0; i<101;i++) putpixel (Snake.tail_x,Snake.tail_y-i,15);
Snake.tail_y -=100;
}
if (Snake.tail_dir == LEFT)
{
for (i = 0; i<101;i++)
putpixel (Snake.tail_x+i,Snake.tail_y,15);
Snake.tail_x +=100;
printf ("LEFT");
}
if (Snake.tail_dir == RIGHT)
{
for (i = 0; i<101;i++)
putpixel (Snake.tail_x-i,Snake.tail_y,15);
Snake.tail_x -=100;
printf ("RIGHT");
}
}
if (futurepixel == 15)
{
outtextxy (499,345, "Game Over");
delay (3000);
exit (1);
}
}
void userinput () //Process User Input and maps it into game
{
static int i = 0;
if ( i > 1000) i = 0; // Makes the bend array a circular queue
static int j = 0;
if ( j > 1000) j = 0;
char input;
if (kbhit ())
{
input = getch ();
//Change Respective Return value to our MACRO Direction Code Value
if (input == 80) input = DOWN;
if (input == 72) input = UP;
if (input == 75) input = LEFT;
if (input == 77) input = RIGHT;
//Change head direction based on logic
if (input == LEFT && Snake.head_dir != RIGHT && Snake.head_dir != LEFT)
{
Snake.head_dir = LEFT;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = LEFT;
i++;
}
if (input == RIGHT && Snake.head_dir != LEFT && Snake.head_dir != RIGHT)
{
Snake.head_dir = RIGHT;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = RIGHT;
i++;
}
if (input == UP && Snake.head_dir != DOWN && Snake.head_dir != UP)
{
Snake.head_dir = UP;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = UP;
i++;
}
if (input == DOWN && Snake.head_dir != UP && Snake.head_dir != DOWN)
{
Snake.head_dir = DOWN;
Snake.bend_x [i] = Snake.head_x;
Snake.bend_y [i] = Snake.head_y;
Snake.bend_dir [i] = DOWN;
i++;
}
}
//Code to change the y direction at respective time
if (Snake.tail_x == Snake.bend_x [j] && Snake.tail_y == Snake.bend_y [j])
{
Snake.tail_dir = Snake.bend_dir [j];
j++;
}
}
void movesnake ()
{
//Move the Head
if (Snake.head_dir == LEFT)
{
Snake.head_x --;
}
if (Snake.head_dir == RIGHT)
{
Snake.head_x ++;
}
if (Snake.head_dir == UP)
{
Snake.head_y --;
}
if (Snake.head_dir == DOWN)
{
Snake.head_y ++;
}
putpixel (Snake.head_x, Snake.head_y,15);
//Move the Tail
putpixel (Snake.tail_x, Snake.tail_y,0);
if (Snake.tail_dir == LEFT)
{
Snake.tail_x --;
}
if (Snake.tail_dir == RIGHT)
{
Snake.tail_x ++;
}
if (Snake.tail_dir == UP)
{
Snake.tail_y --;
}
if (Snake.tail_dir == DOWN)
{
Snake.tail_y ++;
}
}
void gameengine ()//Soul of our game.
{
while (1)
{
movesnake ();
userinput ();
gamephysics ();
delay (5);
}
}
void initscreen ( ) //Draws Intial Screen.
{
int i;
char scorestring [100];
//Draw Boundary
setcolor (4);
line (10,10,10,700);
line (1008,10,1008,700);
line (10,700,1008,700);
line (10,10,1008,10);
//Write Score on scree
sprintf (scorestring, "Score : %d", score);
outtextxy (20,710, scorestring);
//Draw Intial Snake Body
for (int i = Snake.length; i>0;i--) //This part should be redesigned for change of code of intial values
{
putpixel (Snake.head_x-i,Snake.head_y,15);
}
}
void initgamedata ( ) //Snakes starting coordinate if you modify any one make sure also modify dependent values
{
int i;
Snake.length = 100;
Snake.head_x = 200;
Snake.head_y = 200;
Snake.head_dir = RIGHT;
Snake.tail_x = Snake.head_x- Snake.length;
Snake.tail_y = Snake.head_y;
Snake.tail_dir = Snake.head_dir;
for (int i = 0; i <1000;i++) // There is no bend initally
{
Snake.bend_x[i] = 0;
Snake.bend_dir[i] = 0;
}
score = 0;
gamedelay = 1000; // Should be change according to game speed need.
}
// Main Function
int main ()
{
initwindow(1018, 736,"Snake 1.0"); // Create the Snake Window with value is optimize for mode 1024 * 768
initgamedata ();
initscreen ();
gameengine ();
return 0;
}
|
Here is a final screenshot of the game -
Back To Top
11. Final Words
I Know what you must be thinking "Thats a Gigantic Code for a simple snake program i used to play on my mobile ".
Is it difficult than you assumed, isnt it. Well one reason for its difficulty is it is build from scratch ie. very basic.
This tutorial teaches you some very important programming concepts such as user input and collison Detection and these will be used extensively in games programming.
If you finished this tutorial easily congratulate yourself because only a good c programmer could have done that.
If you got overwhelmed by it, dont worry study some more game tutorials and within days things will start making sense.
Well code has been tested several time and 100% functional if you still experience problem we are always there for you contanct.
Its 337 Lines of pure C Code!!! Enjoy It, Tinker with It and let your imagination run wild and do come back for more.
Back To Top
12. Whats Next ?
This is the first version of game and needs improvement. We will be getting back to it as soon as we can.
You have permission to copy this game executable and source code and modify it, Improve it, anything you want.
You can even publish this content on your website, we just ask you to pop us a mail and place a small link to us if you find this stuff worthy enough to be a part of your website!!!
If you have improved our Version of game contanct us and we will publish it on our website with proper credit given to you.
For All those programmers excited to get thier hands dirty heres where you can start -
1. Introducing Menu
2. 2-Player Game
3.Difficulty levels
4. Trendy Colours
5. Enhanced Portability
6. 3-D Snake Game
7. Super Powers
8. Sound Effects
9. Background music and much more....
Next Version of Game will have this and much more. Contribute your share, get credited for it and become world famous ;-)
Now get started with this source code and executable file -
Source Code
Executable
Back To Top
Reader Comments -
| Saptarshi Dey
|
good algorithm. i was searching for exactly this type...
|
| Faisal
|
Hello i have a little bit problem with this, i using the Dev 4.9.9.2 and also save graphics.h and libbgi.a in the include folder of dev cpp. but when i going to compile this first code in upper page. But its give the error " cannot find -lbgi" , "Id returned 1 exit status". So what i gonna do for this. Please tell me to resolve this problem Thanks mail at (faisalzahid@hotmail.com)
|
| stam
|
Dude, you have an error in your tutorial. All else is great, but the libbgi.a file has to be in C:Dev-Cpplib not in "include".
Thx for the tutorial!
|
| majid
|
good .................................................................................................................................................................
|
| Allen
|
cool nice job man i think i can learn the basics of C in your code Good Job Keep up the good work
|
| caramel
|
hey there is something wrong with your graphics.h can you figure it out pls?! :)
|
| salgur
|
Hey, Really helpful stuff. just tried/ported it with/to liballeg. great.
|
| sumit
|
it was just the one i was looking for......................very good
|
| boomboom
|
useless because it wont run and no food at all
|
| anu yun???`
|
what??? nano daw??/
|
| ak
|
i cant run this this game why????
|
| karthi
|
please send aprogram
|
|