Analysis of Snake game, the body of snakes after eating food growth, so you can use a linked list to store the snake's body nodes.
ConsoleApplication1.cpp: Defines the entry point for a console application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#define GAME_WIN_WIDTH 15
#define Game_win_height 15
#define DIRECTION_UP ' W '
#define Direction_down ' s '
#define Direction_left ' a '
#define Direction_right ' d '
Defining two-dimensional vectors
struct VECTOR2
{
int x;
int y;
};
Define the greedy Snake body node
struct Node {
Node *next;
Vector2 pos;//Node Location
};
Enum Mapflag
{
NONE = 0,//NULL
Body,//Snake
FOOD,//Food
WALL//Wall
};
Enum GameState
{
SHOWSTARTBG = 1,
Start
Playing
Over
Showoverbg
};
Definition of greedy snake structure
struct Snake {
Node * HEAD; Greedy Snake head node
int currentdirection; Current Move Direction
Vector2 food;
Vector2 scenesize; Total size of background map
Vector2 offset; Snake movable range relative map offset value
int Mapbackground[game_win_width + 2][game_win_height + 2]; Background map
};
Add head node to snake
node* createheader (int x, int y, node * body) {
Node * head = new node;
Head->next = body;
head->pos.x = x;
Head->pos.y = y;
return head;
}
Data initialization for the greedy snake.
void Initsnake (snake& s) {
S.currentdirection = Direction_down;
S.food = {3,4};
S.head = CreateHeader (5, 5, NULL);
S.offset = {1,1};
S.scenesize = {game_win_width + 2, Game_win_height + 2};
memset (s.mapbackground, 0, s.scenesize.x * s.scenesize.y * sizeof (int));
for (int i = 0; i < s.scenesize.x; i++) {
S.mapbackground[i][0] = Mapflag::wall;
S.mapbackground[i][s.scenesize.y-1] = Mapflag::wall;
}
for (int i = 0; i < s.scenesize.y; i++) {
S.mapbackground[0][i] = Mapflag::wall;
S.mapbackground[s.scenesize.x-1][i] = Mapflag::wall;
}
}
//delete snake tail
void deletetail (node * head) {
do
{
if (!head->next) {
&nb sp; return;
}
if (!head->next->next) {
delete head->next;
Head->next = NULL;
}
} while (head = head =-> next);
}
Void Deletesnake (node * head) {
node* p = NULL;
while (head) {
p = head;
head = head->next;
delete p;
}
}
Node * onmove (int direction, node* head) {
Node *p = nullptr;
Switch (direction)
{
Case Direction_down:
p = CreateHeader (head->pos.x, Head->pos.y + 1, head);
Break
Case DIRECTION_UP:
p = CreateHeader (head->pos.x, head->pos.y-1, head);
Break
Case Direction_left:
p = CreateHeader (head->pos.x-1, Head->pos.y, head);
Break
Case Direction_right:
p = CreateHeader (head->pos.x + 1, head->pos.y, head);
Break
Default
Break
}
if (p) {
Deletetail (P);
}
return p;
}
Vector2 Getnextpos (Snake s) {
Node *head = S.head;
Vector2 Nextpos;
Switch (s.currentdirection)
{
Case Direction_down:
Nextpos = {head->pos.x, head->pos.y + 1};
Break
Case DIRECTION_UP:
Nextpos = {head->pos.x, head->pos.y-1};
Break
Case Direction_left:
Nextpos = {head->pos.x-1, head->pos.y};
Break
Case Direction_right:
Nextpos = {head->pos.x + 1, head->pos.y};
Break
Default
Break
}
return nextpos;
}
node* Oneatfood (Snake &s) {
Vector2 pos = Getnextpos (s);
Node * head = S.head;
---------Randomly regenerate food---------
int randomseed = 0;
int adder = 0;
int x, y;
Randomseed = LoWord (Time (0));
Adder = Randomseed << 15;
x = Randomseed = ((randomseed) * + adder)% Game_win_width;
y = (Randomseed * + adder)% Game_win_height;
s.food.x = x;
S.food.y = y;
//---------------------------------
Return CreateHeader (Pos.x, Pos.y, head);
}
BOOL Checkdir (int currentdir,int newdir) {
Switch (NEWDIR)
{
Case Direction_down:
return Currentdir!= direction_up;
Break
Case DIRECTION_UP:
return Currentdir!= Direction_down;
Break
Case Direction_left:
return Currentdir!= direction_right;
Break
Case Direction_right:
return Currentdir!= direction_left;
Break
Default
Break
}
return false;
}
BOOL Isdie (Snake s) {
Vector2 Newheadpos = Getnextpos (s);
node* head = S.head;
if (newheadpos.x < 0 | | Newheadpos.y < 0) {
return true;
}
if (s.mapbackground[newheadpos.x + s.offset.x][newheadpos.y + s.offset.y] = = Mapflag::wall) {
return true;
}
do {
if (head->pos.x = = Newheadpos.x && Head->pos.y = = newheadpos.y) {
return true;
}
while (head = Head->next);
return false;
}
BOOL Caneat (Snake s) {
Vector2 dest = Getnextpos (s);
return dest.x = = S.food.x && Dest.y = = S.food.y;
}
void Printfstartgame () {
printf ("-------------------------------------------------\ n");
printf ("-------------------------------------------------\ n");
printf ("----------\ n");
printf ("-----Press any key to start-----\ n");
printf ("----------\ n");
printf ("-------------------------------------------------\ n");
printf ("-------------------------------------------------\ n");
}
void Printfgameover () {
printf ("-------------------------------------------------\ n");
printf ("-------------------------------------------------\ n");
printf ("----------\ n");
printf ("-----Game OVER!!! -----\ n ");
printf ("----------\ n");
printf ("-------------------------------------------------\ n");
printf ("-------------------------------------------------\ n");
}
void Printgamescene (int *gamemap,snake s, vector2 Scenesize,vector2 offset) {
int Tempmap[game_win_width + 2][game_win_height + 2];
memcpy (Tempmap, Gamemap, scenesize.x * scenesize.y * sizeof (int));
Node * head = S.head;
do {
Tempmap[head->pos.x + offset.x][head->pos.y + offset.y] = mapflag::body;
while (head = Head->next);
Tempmap[s.food.x +offset.x][s.food.y + offset.y] = Mapflag::food;
for (int h = 0; h < scenesize.y; h++) {
for (int w = 0; w < scenesize.x; w++) {
Switch (Tempmap[w][h])
{
Case Mapflag::none:
printf ("");
Break
Case Mapflag::body:
printf ("*");
Break
Case Mapflag::food:
printf ("@");
Break
Case Mapflag::wall:
printf ("#");
Break
Default
Break
}
}
printf ("\ n");
}
}
void Renderscene (GameState St, Snake s) {
System ("CLS");
Switch (ST)
{
Case SHOWSTARTBG:
Printfstartgame ();
Break
Case Start:
Printfstartgame ();
Break
Case Playing:
Printgamescene ((int*) S.mapbackground, S, S.scenesize, S.offset);
Break
Case over:
Printfgameover ();
Break
Case SHOWOVERBG:
Printfgameover ();
Break
Default
Break
}
}
int main ()
{
char input;
GameState state = GAMESTATE::SHOWSTARTBG;
float speed = 2.0/1000; Step per Msecond
time_t lastframe = 0;
time_t lasemoveframe = 0;
time_t currentframe = 0;
Snake player;
while (true)
{
Lastframe = Currentframe;
Currentframe = GetTickCount64 ();
if (_kbhit ()) {
input = _getch ();
Switch (state)
{
Case GAMESTATE::SHOWSTARTBG:
Initsnake (player);
Renderscene (state, player);
state = Gamestate::start;
Lasemoveframe = Currentframe;
Break
Case Gamestate::start:
State = GameState:: playing;
Break
Case GameState::p laying:
if (Checkdir (player.currentdirection, input)) {
Player.currentdirection = input;
}
Break
Case GAMESTATE::SHOWOVERBG:
Renderscene (state, player);
state = Gamestate::over;
Break
Case Gamestate::over:
state = GAMESTATE::SHOWSTARTBG;
Break
Default
Break
}
}
if (state = = GameState::p laying && (currentframe-lasemoveframe) * speed > 1) {
Lasemoveframe = Currentframe;
if (Isdie (player)) {
state = Gamestate::over;
}
else if (caneat (player))
{
Player.head = Oneatfood (player);
}
Else
{
Player.head = OnMove (player.currentdirection, Player.head);
}
Renderscene (state, player);
}
}
return 0;
}