C语言小游戏————贪吃蛇.c

 1.主函数框架的搭建

int main (void)
{
	starup();//数据初始化
	while(1)
	{
		show();//打印画面
		updateWithoutInput();//与用户输入无关的更新
		updateWithInput();//与用户输入有关的更新 
	} 
	return 0;
} 
说明:

    a.startup()对全局变量的初始化;

    b.while(1)为死循环:

每次循环进行的内容:

    c show().先清屏在打印一次画面(元素:围墙,蛇头,蛇身,果子,空白);

    d.updateWithoutInput()进行与输入无关的更新(判断是否吃到的果子,食物的刷新);

    e.updateWithInput()进行与输入有关的更新(蛇的移动,方向的改变);

2.全局变量的设定

#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列;

3.第一个函数startup():对数据的初始化

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<High;i++)
		for(j=0;j<Width;j++)
			if(i==0||j==0||i==High-1||j==Width-1)
				canvas[i][j]=3; 	 
}

说明:

     a.蛇,食物坐标可以随意设置;

     b.对地图中元素的初始化:0空格 1蛇 2食物 3围墙  4蛇头;在定义时已经对二维数组进行了初始化赋0;

     c.对围墙元素的初始化:使用两重循环,将行数为0和Higj-1列数为0和Width-1的点全部赋值为3;

4.第二个函数show():画面打印

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<High;i++)
	{
		for(j=0;j<Width;j++)
		{
			if(canvas[i][j]==0)
				printf(" ");
			else if(canvas[i][j]==1)
				printf("+");
			else if(canvas[i][j]==2)
				printf("@");
			else if(canvas[i][j]==3)
				printf("*");
			else if(canvas[i][j]==4)
				printf("O");
		}
		printf("\n");
	}	
	printf("得分;%d",score);
}

说明:

    a.对于gotoxy()功能为返回某点重新打印,即相当于清屏函数system("cls"),但是不存在闪屏问题。具体原理牵扯到windows系统的操作,嗯,本人不太懂(๑• . •๑)

使用时需加载#include <windows.h>头文件

    b.打印效果如下:



5.第三个函数updateWithoutInput()与输入无关的更新

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<serpent_long;i++)
        if(serpent_x[0]==serpent_x[i]&&serpent_y[0]==serpent_y[i])
        {
            printf("死亡游戏结束!\n");//碰到自己身子死亡 
            getch();
            exit(1);
        }
}
说明:

    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)退出程序

6.第四个函数updateWithInput() 与输入有关的更新

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 <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#include <time.h> 

#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;i<High;i++)
		for(j=0;j<Width;j++)
			if(i==0||j==0||i==High-1||j==Width-1)
				canvas[i][j]=3; 	 
}

void show()//画面打印 
{
	gotoxy(0,0);
	int i,j;
	for(i=0;i<High;i++)
	{
		for(j=0;j<Width;j++)
		{
			if(canvas[i][j]==0)
				printf(" ");
			else if(canvas[i][j]==1)
				printf("+");
			else if(canvas[i][j]==2)
				printf("@");
			else if(canvas[i][j]==3)
				printf("*");
			else if(canvas[i][j]==4)
				printf("O");
		}
		printf("\n");
	}	
	printf("得分;%d",score);
}

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<serpent_long;i++)
        if(serpent_x[0]==serpent_x[i]&&serpent_y[0]==serpent_y[i])
        {
            printf("死亡游戏结束!\n");//碰到自己身子死亡 
            getch();
            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;
	
}

int main(void)
{
	startup();
	while(1)
	{
		show();
		updateWithoutInput();
		updateWithInput(); 
	}
	return 0;
}

8.总结:

    优点:

        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;i 
        
          0) 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;i 
          
         
       
      
      
     
     
    
    
   
   





  • 25
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值