贪吃蛇游戏 C 语言 VC++6.0 制作
2018-8-13,sjl 原创作品
较粗略的游戏设计思路
蛇移动:
1. 游戏介绍
2. 开始游戏:
生成蛇的生存区域,
生成 1 节蛇,
生成 1 份食物,
循环如下进程:
画地图、食物、蛇
3. 游戏结束
初始方向,随机,
玩家修改方向,
判断蛇头触碰到什么:
食物,吃掉,分数加 1,蛇长加 1,
自己的某一节身体,断节,游戏结束
生活区域外空间,无法生存,游戏结束
吃得太饱,生存空间容不下,游戏结束
游戏效果图
1
详细的易于理解的游戏源代码
//time()
//srand(), rand(), exit()
/********** Some comments are hidden **********/
# include
# include //system("cls"), Sleep()
# include //kbhit(), getch()
# include
# include
# define MAP_RANGE 12 //map range
# define SNAKE_LENGTH (MAP_RANGE - 2) * (MAP_RANGE - 2) //snake length
# define SNAKE_DEFAULT_VALUE 13 //snake array default value
/********** structures **********/
typedef struct Map
{
int point[MAP_RANGE][MAP_RANGE];
}MAP;
typedef struct Point
{
int x;
int y;
}POINT_XY;
typedef struct SNode
{
POINT_XY body[SNAKE_LENGTH-2];
POINT_XY head;
POINT_XY tail;
int len;
}SNAKE;
typedef struct Food
{
POINT_XY point;
}FOOD;
/********** buildBorder **********/
void buildBorder(MAP * map)
{
int x, y;
2
for (x=0; xpoint[0][x] = -1;
map->point[MAP_RANGE-1][x] = -1;
}
for (y=1; ypoint[y][0] = -1;
map->point[y][MAP_RANGE-1] = -1;
}
}
/********** initialize **********/
void initialize(POINT_XY * oldTail, char * dir, MAP * map, SNAKE * snake,
FOOD * food, int * score, int * speed)
{
int x, y, i;
int tmp;
oldTail->x = oldTail->y = 0;
*dir = 'a';
//initialize map contents
for (y=0; ypoint[y][x] = 0;
buildBorder(map);
//initialize contents of snake
for (i=0; ibody[i].x = SNAKE_DEFAULT_VALUE;
snake->body[i].y = SNAKE_DEFAULT_VALUE;
}
snake->len = 1;
//initialize position of snake head and tail
tmp = MAP_RANGE - MAP_RANGE / 3 + 1;
snake->head.x = tmp;
3
snake->head.y = tmp;
snake->tail = snake->head;
//initialize food position
food->point.x = MAP_RANGE / 4;
food->point.y = MAP_RANGE / 4;
//initialize score and speed
*score = 0;
*speed = 10;
}
/********** gameTips **********/
void gameTips(int * gameStats)
{
char choose = 'z';
//game tips
printf("-> Greedy Snake\n");
printf("-> The rules, as you now.\n");
printf("-> Control keys: a d w s\n");
printf("-> More control: 'q' to quit.\n");
printf("-> Goal: eat more, life longer.\n");
printf("-> Play? (space /others)");
//as a start play button
do
{
choose = getch();
if (choose == 'q')
exit(0);
}while(choose != ' ');
*gameStats = 1;
}
/********** createFood **********/
void createFood(SNAKE * snake, FOOD * food)
{
int x, y;
int i;
int inBody; //double not, means build
4
do
{
inBody = 0;
x = 1 + (rand() % (MAP_RANGE-2)); //random from 1 to 10
y = 1 + (rand() % (MAP_RANGE-2));
//not in body,
//but if young enough and no gowth body, we do not consider this
for (i=0; i < snake->len - 2; i++)
if (snake->body[i].x == x && snake->body[i].y == y)
inBody++;
//not in head and tail
if (!inBody && (snake->tail.x != x && snake->tail.y != y)
&& (snake->head.x != x && snake->head.y != y))
break;
}while(1);
food->point.x = x;
food->point.y = y;
}
/********** eatFood **********/
void eatFood(int snakeLen, int * score, int * speed)
{
//update score
*score += (snakeLen / 10 + 1);
//update speed
if (snakeLen % 10 == 0)
*speed += 10;
}
/********** growthUp **********/
void growthUp(SNAKE * snake, POINT_XY * oldTail)
{
//if it is food, snake growth up
snake->len++;
if (snake->len > 2)
snake->body[snake->len-3] = snake->tail;
5
snake->tail.x = oldTail->x;
snake->tail.y = oldTail->y;
}
/********** judgeTouch **********/
void judgeTouch(int * gameStats, SNAKE * snake, POINT_XY * oldTail,
FOOD * food, int * score, int * speed)
{
int i;
//if get out of border, stop game
if (snake->head.x == 0 || snake->head.y == 0
|| snake->head.x == MAP_RANGE-1 || snake->head.y == MAP_RANGE-1)
*gameStats = 0;
//if touch food, eat it, growth up, and create another one
if (snake->head.x == food->point.x && snake->head.y == food->point.y)
{
eatFood(snake->len, score, speed);
growthUp(snake, oldTail);
//if a giant snake filled the whole map, not place to set food
if (snake->len == SNAKE_LENGTH)
{
*gameStats = 0;
food->point.x = 0;
food->point.y = 0;
printf("You did it!\n");
}
else
createFood(snake, food);
}
//if eat snake own
for (i=0; ilen-2; i++)
if (snake->head.x == snake->body[i].x
&& snake->head.y == snake->body[i].y)
*gameStats = 0;
if (snake->len > 1 && snake->head.x == snake->tail.x
&& snake->head.y == snake->tail.y)
*gameStats = 0;
}
6
/********** snakeMove **********/
void snakeMove(int * gameStats, POINT_XY * oldTail, SNAKE * snake,
char * dir, FOOD * food, int * score, int * speed)
{
int i;
int len = snake->len;
int growth = 0;
//get old tail position
oldTail->x = snake->tail.x;
oldTail->y = snake->tail.y;
//move body and tail
if (snake->len > 2)
{
snake->tail = snake->body[len-3];
for (i=len-3; i>0; i--)
snake->body[i] = snake->body[i-1];
snake->body[0] = snake->head;
}
else if (snake->len == 2)
snake->tail = snake->head;
//move head
//if press key to choose direction, modify dir
if (kbhit())
*dir = getch();
switch (*dir)
{
case 'a': snake->head.x--; break;
case 'd': snake->head.x++; break;
case 'w': snake->head.y--; break;
case 's': snake->head.y++; break;
case 'q': exit(0); break;
default: break;
}
if (snake->len == 1)
snake->tail = snake->head;
//guess head touch what
judgeTouch(gameStats, snake, oldTail, food, score, speed);
7
}
/********** updateMap **********/
void updateMap(MAP * map, POINT_XY snakeHead, POINT_XY oldTail, FOOD food)
{
//remove old tail
map->point[oldTail.y][oldTail.x] = 0;
//add snake head to map
map->point[snakeHead.y][snakeHead.x] = 2;
//add food to map, while food is present
if (food.point.x != 0 && food.point.y != 0)
map->point[food.point.y][food.point.x] = 1;
}
/********** showOnScreen **********/
void showOnScreen(MAP map, int score, int speed)
{
int x, y;
for (y=0; y