emmm……这篇主要是介绍一个小小的用代码做出来的贪吃蛇,这对于一个新手的我来说可是费了好大一股劲,其实对于贪吃蛇来说,它本身的特性就决定了它适合用链表来做,emmm……但我不会,所以对于新手的我,我用了一种相似的方法,通过记录蛇的每一个身体点的坐标来操作蛇的移动。以下,我会用源代码的形式简单介绍。
首先,我们需要构造整个图形的边框架构,所以我们要构造如下的二维数组
char map[12][12]=
{"***********",
"*xxxxH *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"***********"};//initialize the picture
我们还需要考虑随机放置蛇的食物,这里要用到rand()函数以下展示代码
void put_money(void)//put the money randomly
{
int x=0,y=0;
srand((unsigned int)time(0));
while(map[x][y]=='*'||map[x][y]==snake_body||map[x][y]==snake_head)
{
x = rand()%10 + 1;
y = rand()%10 + 1;
}
map[x][y] = '$';
}
然后我们需要描每个蛇的身体的坐标,定义为snake_x,snake_y,分别为一数组
int snake_x[max_length]={1,2,3,4,5};
int snake_y[max_length]={1,1,1,1,1};
当然,我们打好了整个字符边框之后还要懂得将它们输出
void output(void)// output the picture
{
int i =0;
while(i<12)
{
printf("%s\n",map[i]);
i++;
}
}
然后以下便是重头戏,也就是贪吃蛇的重点(贪吃蛇的移动):
首先判断贪吃蛇不会撞到墙的情况,我们有‘w’‘s’‘a’‘d’四个键来判断贪吃蛇的运动,思考,我们如果按了’s’键,那么蛇头会和它下方的空格交换位置,然后每一个都与它前面的交换位置,那么我们先定义蛇头的移动,
switch (c) //move the snake head
{
case 'w': snakeHeadMove(0,-1); break;
case 's': snakeHeadMove(0,1); break;
case 'a': snakeHeadMove(-1,0); break;
case 'd': snakeHeadMove(1,0); break;
}
void snakeHeadMove(int m,int n)// move the snake head
{
snake_x[snake_length]=snake_x[snake_length-1]+m;
snake_y[snake_length]=snake_y[snake_length-1]+n;
}
上述的snake_length是蛇头将要移动的下一个的方向,而snake_length-1就是现在蛇头的坐标,然后将蛇头的坐标一个一个往前推:
void snakemove(void)//move the snake
{
int i,j;
char ins;
for(i=snake_length;i > 0;i--)
{
ins=map[snake_y[i]][snake_x[i]];
map[snake_y[i]][snake_x[i]]=map[snake_y[i-1]][snake_x[i-1]];
map[snake_y[i-1]][snake_x[i-1]]=ins;//move
}
for(j=0;j<=snake_length;j++)//change the ordinate of snake
{
snake_x[j]=snake_x[j+1];
snake_y[j]=snake_y[j+1];
}
snake_x[snake_length]=0;
snake_y[snake_length]=0;
}
上述由于我们将数组的长度调到了snake_length+1,因为蛇头和前面的坐标置换了,所以我们要将所有的坐标前移并将最后的蛇头前一个坐标,也就是snake_length设置(0,0)
我们已经考虑了蛇的移动,然后我们需要考虑蛇是否会撞墙,也就是如果简单地走动,蛇才执行上述的操作,但是吃到东西后,或撞墙,我们也要考虑。
首先,考虑撞墙,刚刚我们移动是让蛇头先和它要移动的方向的空格交换位置,所以移动,现在,我们采用类似的方法,首先,将蛇头的下一个位置标出来,如果它是墙的字符然后就结束死掉
然后,我们考虑吃掉食物的情况,当蛇头将要移动的位置坐标为食物,将其改为蛇的身体,然后与蛇头交换位置,同时蛇的长度加一,蛇的坐标增加一个食物的坐标的位置,然后重新放置食物
int gameover(void)
{
int i,j,mid;
char ins;
if(map[snake_y[snake_length]][snake_x[snake_length]]==snake_body||map[snake_y[snake_length]][snake_x[snake_length]]=='*')
return 1;//return 1 if snake is dead
else if(map[snake_y[snake_length]][snake_x[snake_length]]=='$')//eat the money
{
mid = snake_length;
map[snake_y[mid]][snake_x[mid]] = snake_body;//put 'x' in the front of head
ins = map[snake_y[mid-1]][snake_x[mid-1]];
map[snake_y[mid-1]][snake_x[mid-1]] = map[snake_y[mid]][snake_x[mid]];
map[snake_y[mid]][snake_x[mid]] = ins;//change the position of snakehead and 'x'
snake_length++;//the length of snake add 1
put_money();//put money
output();
return 0;
}
else
{
snakemove();// move the snake
output();
return 0;
}
}
以下是整个的源代码:
/*WHILE not ÓÎÏ·½áÊø DO
ch£½µÈ´ýÊäÈë
CASE ch DO
¡®A¡¯:×óÇ°½øÒ»²½£¬break
¡®D¡¯:ÓÒÇ°½øÒ»²½£¬break
¡®W¡¯:ÉÏÇ°½øÒ»²½£¬break
¡®S¡¯:ÏÂÇ°½øÒ»²½£¬break
END CASE
If
Ç°½øÒ»²½ = *
Êä³ö Game Over!!!
END WHILE
Ç°½øÒ»²½ = ÉíÌå
Êä³ö Game Over!!!
END WHILE
Else
Êä³ö×Ö·û¾ØÕó
END WHILE
Êä³ö Game Over!!!
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define max_length 50
#define snake_body 'x'
#define snake_head 'H'
void output(void);
void put_money(void);
void snakeHeadMove(int m,int n);
int gameover(void);
void snakemove(void);
char map[12][12]=
{"***********",
"*xxxxH *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"* *",
"***********"};//initialize the picture
int snake_length=5;
int snake_x[max_length]={1,2,3,4,5};
int snake_y[max_length]={1,1,1,1,1};
int main()
{
int i=0;
char input,c;
put_money();
output();//output the picture
while(!input)
{
c = getch();//read the botton
switch (c) //move the snake head
{
case 'w': snakeHeadMove(0,-1); break;
case 's': snakeHeadMove(0,1); break;
case 'a': snakeHeadMove(-1,0); break;
case 'd': snakeHeadMove(1,0); break;
}
input = gameover();
if(input)
break;
/*if(gameover()) break;//judge if game is over
while(getchar() != '\n')//cancel the '\n' when to entry the botton
break;*/
}
printf("Game over!!!");
}
void output(void)// output the picture
{
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
int i =0;
while(i<12)
{
printf("%s\n",map[i]);
i++;
}
}
void put_money(void)//put the money randomly
{
int x=0,y=0;
srand((unsigned int)time(0));
while(map[x][y]=='*'||map[x][y]==snake_body||map[x][y]==snake_head)
{
x = rand()%10 + 1;
y = rand()%10 + 1;
}
map[x][y] = '$';
}
void snakeHeadMove(int m,int n)// move the snake head
{
snake_x[snake_length]=snake_x[snake_length-1]+m;
snake_y[snake_length]=snake_y[snake_length-1]+n;
}
int gameover(void)
{
int i,j,mid;
char ins;
if(map[snake_y[snake_length]][snake_x[snake_length]]==snake_body||map[snake_y[snake_length]][snake_x[snake_length]]=='*')
return 1;//return 1 if snake is dead
else if(map[snake_y[snake_length]][snake_x[snake_length]]=='$')//eat the money
{
mid = snake_length;
map[snake_y[mid]][snake_x[mid]] = snake_body;//put 'x' in the front of head
ins = map[snake_y[mid-1]][snake_x[mid-1]];
map[snake_y[mid-1]][snake_x[mid-1]] = map[snake_y[mid]][snake_x[mid]];
map[snake_y[mid]][snake_x[mid]] = ins;//change the position of snakehead and 'x'
snake_length++;//the length of snake add 1
put_money();//put money
output();
return 0;
}
else
{
snakemove();// move the snake
output();
return 0;
}
}
void snakemove(void)//move the snake
{
int i,j;
char ins;
for(i=snake_length;i > 0;i--)
{
ins=map[snake_y[i]][snake_x[i]];
map[snake_y[i]][snake_x[i]]=map[snake_y[i-1]][snake_x[i-1]];
map[snake_y[i-1]][snake_x[i-1]]=ins;//move
}
for(j=0;j<=snake_length;j++)//change the ordinate of snake
{
snake_x[j]=snake_x[j+1];
snake_y[j]=snake_y[j+1];
}
snake_x[snake_length]=0;
snake_y[snake_length]=0;
}
上述的操作由于一直按回车比较麻烦所以我用了getch()函数,它内置在conio.h头文件,但它不在标准库,如果不嫌麻烦也可用:
while(!input)
{
c = getchar();//read the botton
switch (c) //move the snake head
{
case 'w': snakeHeadMove(0,-1); break;
case 's': snakeHeadMove(0,1); break;
case 'a': snakeHeadMove(-1,0); break;
case 'd': snakeHeadMove(1,0); break;
}
input = gameover();
if(input) break;//judge if game is over
while(getchar() != '\n')//cancel the '\n' when to entry the botton
break;
}
然后我用了清屏的system,也可不用,可以去掉那4行代码,就是会不停的输出
emmm……上述就是我差不多的学做贪吃蛇的一些小小的小经验,也就是自顶向下了,但愿对想做的人有些帮助。
如果想创新可以试试放置不同的食物,然后这些食物会对贪吃蛇有加速、变长几秒、头身分离、放置围墙等等,还可以让蛇迟到自己不会死,而是减短长度,当然,有条件和能力的同学可以试试。