int main (void)
{
starup();//数据初始化
while(1)
{
show();//打印画面
updateWithoutInput();//与用户输入无关的更新
updateWithInput();//与用户输入有关的更新
}
return 0;
}
说明:
a.startup()对全局变量的初始化;
b.while(1)为死循环:
每次循环进行的内容:
c show().先清屏在打印一次画面(元素:围墙,蛇头,蛇身,果子,空白);
d.updateWithoutInput()进行与输入无关的更新(判断是否吃到的果子,食物的刷新);
e.updateWithInput()进行与输入有关的更新(蛇的移动,方向的改变);
#define High 20//地图的尺寸
#define Width 30
#define SerpentNum 200//蛇长的最大值
//全局变量
int serpent_x[SerpentNum],serpent_y[SerpentNum];//蛇的坐标
int serpent_long; //蛇的长度
int canvas[High][Width]={0};//地图对应元素 0空格 1蛇 2食物 3围墙 4蛇头
int food_x,food_y;//食物的坐标
int score; //分数
char input;//方向的控制
说明:
a.对于画面上所有的元素均用两个值即可确定位置,所以每个点都(x,y)表示,但是不同于直角坐标系,(x,y)表示x行y列;
b.起始行由于以数组形式存储所以,从0行0列开始;
c.地图的打印使用的是二维数组,第一维表示列,第二维表示行,例canvas[i][j]表示i行j列;
void startup()
{
serpent_x[0]=High/2;serpent_y[0]=Width/3;//蛇的初始位置
serpent_x[1]=High/2;serpent_y[1]=Width/3+1;
serpent_long=2;
food_x=High/3;food_y=Width/3;//食物
score=0;
int i,j;
canvas[serpent_x[0]][serpent_y[0]]=4;
canvas[serpent_x[1]][serpent_y[1]]=1;
canvas[food_x][food_y]=2;
for(i=0;i
a.蛇,食物坐标可以随意设置;
b.对地图中元素的初始化:0空格 1蛇 2食物 3围墙 4蛇头;在定义时已经对二维数组进行了初始化赋0;
c.对围墙元素的初始化:使用两重循环,将行数为0和Higj-1列数为0和Width-1的点全部赋值为3;
void gotoxy(int x,int y)
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X=x;
pos.Y=y;
SetConsoleCursorPosition(handle,pos);
}
void show()//画面打印
{
gotoxy(0,0);
int i,j;
for(i=0;i
a.对于gotoxy()功能为返回某点重新打印,即相当于清屏函数system("cls"),但是不存在闪屏问题。具体原理牵扯到windows系统的操作,嗯,本人不太懂(๑• . •๑)
b.打印效果如下:
void updateWithoutInput()//与输入无关的更新
{
int i;
if(serpent_x[0]==food_x&&serpent_y[0]==food_y)//如果蛇吃到果子
{
score++;
srand((unsigned)time(NULL));//食物刷新
food_x=rand()%(High-3)+1;
food_y=rand()%(Width-3)+1;
canvas[food_x][food_y]=2;
serpent_long++;//蛇的增长
}
if((serpent_x[0]==0||serpent_y[0]==0||serpent_x[0]==High-1||serpent_y[0]==Width-1))
{
printf("死亡游戏结束!\n");//撞墙死亡
getch();
exit(1);
}
for(i=1;i
说明:
a.判断蛇是否吃到果子:即蛇头的坐标等于食物的坐标serpent_x[0]==food_x&&serpent_y[0]==food_y;
b.如果蛇吃到果子:食物坐标变0,蛇身加长(只需要加长,在下一个函数中自动实现赋值1)
b.食物的刷新:使用rand()函数获得随机数,然后对(High-3)取余,使食物的坐标落在围墙内;
c. srand((unsigned)time(NULL))使用时间函数作随机数的种子;
e.死亡判定,如果蛇头坐标等于墙的坐标死亡;如果等于蛇身的坐标死亡
f.死亡后,先提示,然后输入任意键退出,exit(1)退出程序
void updateWithInput()//与输入有关的更新
{
int i=1;
if(kbhit())//输入方向
input=getch();
if(input=='w'||input=='s'||input=='a'||input=='d')//蛇的移动
{
canvas[serpent_x[serpent_long-1]][serpent_y[serpent_long-1]]=0;
for(i=serpent_long-1;i>0;i--)
{
serpent_x[i]=serpent_x[i-1];
serpent_y[i]=serpent_y[i-1];
canvas[serpent_x[i]][serpent_y[i]]=1;
}
}
if(input=='w')//头的移动
serpent_x[0]--;
else if(input=='s')
serpent_x[0]++;
else if(input=='a')
serpent_y[0]--;
else if(input=='d')
serpent_y[0]++;
canvas[serpent_x[0]][serpent_y[0]]=4;
}
a.四个函数中,这个函数最麻烦也是最难理解的。
b.输入方向:if(kbhit()) input=getch(); kbhit()函数作用为检测当前是否有输入的值,有的话返回1,getch()作用:接受键盘输入的字符,并返回;类似于scanf("%c",& input);但是不需要回车键表示输入完成;
c.蛇身的移动:让蛇从第二个节点开始等于前一个节点,让最后一个节点变为零(这个方法想了很久);
d.方向的控制:根据键盘输入的方向键(wasd)改变蛇头的坐标,注意,input一定要设为全局变量,在其他控制台小游戏中如果想实现输入动,不输入不动,则设为自动局部变量;
7.完整代码
#include
#include
#include
#include
#include
#define High 20//地图的尺寸
#define Width 30
#define SerpentNum 200//蛇长的最大值
//全局变量
int serpent_x[SerpentNum],serpent_y[SerpentNum];//蛇的坐标
int serpent_long; //蛇的长度
int canvas[High][Width]={0};//地图对应元素 0空格 1蛇 2食物 3围墙 4蛇头
int food_x,food_y;//食物的坐标
int score; //分数
char input;//方向的控制
void gotoxy(int x,int y)
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X=x;
pos.Y=y;
SetConsoleCursorPosition(handle,pos);
}
void startup()
{
serpent_x[0]=High/2;serpent_y[0]=Width/3;//蛇的初始位置
serpent_x[1]=High/2;serpent_y[1]=Width/3+1;
serpent_long=2;
food_x=High/3;food_y=Width/3;//食物
score=0;
int i,j;
canvas[serpent_x[0]][serpent_y[0]]=4;
canvas[serpent_x[1]][serpent_y[1]]=1;
canvas[food_x][food_y]=2;
for(i=0;i0;i--)
{
serpent_x[i]=serpent_x[i-1];
serpent_y[i]=serpent_y[i-1];
canvas[serpent_x[i]][serpent_y[i]]=1;
}
}
if(input=='w')
serpent_x[0]--;
else if(input=='s')
serpent_x[0]++;
else if(input=='a')
serpent_y[0]--;
else if(input=='d')
serpent_y[0]++;
canvas[serpent_x[0]][serpent_y[0]]=4;
}
int main(void)
{
startup();
while(1)
{
show();
updateWithoutInput();
updateWithInput();
}
return 0;
}
优点:
a.函数功能明确,找错好找
b.思路较为简单
缺点:
a.功能不太完善
b.蛇的横向和纵向移动速度不同
c.食物刷新存在bug
后续优化:
a.暂停功能
b.难度的递增
第二次更新:
a.可以暂停
b.难度的递增
c.修复食物刷新bug(原因,食物被刷新到蛇的体内)
#include
#include
#include
#include
#include
#define High 20//地图的尺寸
#define Width 30
#define SerpentNum 200//蛇长的最大值
//全局变量
int serpent_x[SerpentNum],serpent_y[SerpentNum];//蛇的坐标
int serpent_long; //蛇的长度
int canvas[High][Width]={0};//地图对应元素 0空格 1蛇 2食物 3围墙 4蛇头
int food_x,food_y;//食物的坐标
int score; //分数
char input;//方向的控制
int speed;
void gotoxy(int x,int y)
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X=x;
pos.Y=y;
SetConsoleCursorPosition(handle,pos);
}
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void startup()
{
serpent_x[0]=High/2;serpent_y[0]=Width/3;//蛇的初始位置
serpent_x[1]=High/2;serpent_y[1]=Width/3+1;
serpent_long=2;
food_x=High/3;food_y=Width/3;//食物
score=0;
speed=5;
int i,j;
canvas[serpent_x[0]][serpent_y[0]]=4;
canvas[serpent_x[1]][serpent_y[1]]=1;
canvas[food_x][food_y]=2;
for(i=0;i0)
speed--;
}
if((serpent_x[0]==0||serpent_y[0]==0||serpent_x[0]==High-1||serpent_y[0]==Width-1))
{
printf("死亡游戏结束!\n");//撞墙死亡
getch();
exit(1);
}
for(i=1;i0;i--)
{
serpent_x[i]=serpent_x[i-1];
serpent_y[i]=serpent_y[i-1];
canvas[serpent_x[i]][serpent_y[i]]=1;
}
}
if(input=='w')
serpent_x[0]--;
else if(input=='s')
serpent_x[0]++;
else if(input=='a')
serpent_y[0]--;
else if(input=='d')
serpent_y[0]++;
canvas[serpent_x[0]][serpent_y[0]]=4;
v=0;
}
canvas[food_x][food_y]=2;
}
int main(void)
{
startup();
while(1)
{
show();
updateWithoutInput();
updateWithInput();
}
return 0;
}