天天看点

C语言|控制台小游戏|贪吃蛇

贪吃蛇

效果演示:

C语言|控制台小游戏|贪吃蛇

操作说明:

  1. W

    S

    A

    D

    控制 上 、下、左、右 方向,

    空格

    暂停,按下任意键继续
  2. 每吃掉一个食物长度加1,界面下方显示当前长度
  3. 蛇头撞到自身或边界后显示

    game over!

    2秒(时间可更改),任意键退出
  • 由于上下字符间隔与左右字符间隔不一致,纵向移动时移动速度会超过横向移动速度。
  • 画面显示:游戏画面信息存入二维数组:数组下标映射游戏中位置坐标,数组元素的值(0,1…)分别表示游戏场景中不同的对象(空白处,蛇头…),遍历数组根据不同的值输出游戏画面。每次输出前将光标调至首行首列处,覆盖之前的输出画面,达到刷新游戏画面的效果。
  • 小蛇移动与成长:根据方向变量的值(1,2,3,4)来向某一方向(上,下,左,右)持续前进,当方向按键按下时,修改方向变量的值以改变方向。蛇头对应的数组元素的数值为1,从头到尾,数值递增(2,3,4,5…),每次更新画面,使数组中大于0的数组元素(蛇头蛇身)的值加一,蛇头的值变为2,根据行进方向在新方向上生成新的蛇头(数值为1),未吃到食物的情况下,将蛇尾变为空白。即通过向目标方向生成一个新蛇头,去掉蛇尾,来达到移动的效果,而吃掉食物时生成新蛇头而不去掉蛇尾,使长度加一。
  • 食物生成:当食物被吃掉后,随机生成一个处于空白处的坐标,改变该坐标的值为新的食物。

以下为带注释的完整源代码:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

#define high  25    //画布高
#define width 60    //画布宽

#define border -1   //边界
#define blank   0   //空白
#define head    1   //蛇头
#define food   -2   //食物

int canvas[high+1][width+1];    //画布数组
int direction;       //行进方向
int head_h,head_w;   //蛇头坐标
int tail_h,tail_w;   //蛇尾坐标
int food_h,food_w;   //食物坐标
int length;          //贪吃蛇长度(包括蛇头)
int Isover;          //游戏结束标志

void Startup();   //游戏数值初始化
void Show();    //游戏界面输出
void UpdateInput();     //因输入导致的游戏状态更新
void UpdateNormal();    //与输入无关的游戏状态更新

int main()
{
    Startup();
    while(Isover){
        Show();
        UpdateInput();
        UpdateNormal();
    }
    printf("\ngame over!\n");
    Sleep(2000);
    system("pause");
    return 0;
}

void Startup(){
    /*设置边界值*/
    for(int i=0;i<=width;i++){
        canvas[0][i]=border;
        canvas[high][i]=border;
    }
    for(int i=0;i<=high;i++){
        canvas[i][0]=border;
        canvas[i][width]=border;
    }
    /*设置贪吃蛇初始位置*/
    head_h=high/2;
    head_w=width/2;
    canvas[head_h][head_w]=head;
    /*贪吃蛇初始长度*/
    length=6;
    for(int i=1;i<length;i++){  //设置蛇身,应与初始移动方向相反
        canvas[head_h][head_w-i]=i+1;
    }
    /*设置初始方向*/
    direction=4;
    /*设置食物位置,随机出现*/
    srand(time(NULL));
    do{
       food_h=rand()%high;
       food_w=rand()%width;
    }while(canvas[food_h][food_w]!=blank);
    canvas[food_h][food_w]= food;
    /*设置游戏结束条件*/
    Isover=1;
}
void Show(){
    HideCursor();   //隐藏光标
    gotoxy(1,1);    //回调光标位置,刷新画面

    for(int i=0;i<=high;i++){   //输出游戏界面
        for(int j=0;j<=width;j++){
            if(canvas[i][j] == border){     //边界
                printf("#");
            }
            else if(canvas[i][j] == head ){    //蛇头
                printf("@");
            }
            else if(canvas[i][j]== blank){     //空白处
                printf(" ");
            }
            else if(canvas[i][j]== food){      //食物
                printf("O");
            }
            else if(canvas[i][j]> 0){       //蛇身
                printf("*");
            }
        }
        printf("\n");
    }
    printf("\nLength of the snake:%2d",length);
}
void UpdateInput(){
    char key_W=GetKeyState('W'),  //监测 W 键是否按下
         key_S=GetKeyState('S'),  //监测 S 键是否按下
         key_A=GetKeyState('A'),  //监测 A 键是否按下
         key_D=GetKeyState('D'),  //监测 D 键是否按下
         key_BS=GetKeyState(' ');  //监测 空格 键是否按下
    if(kbhit()){  //当有键按下时
        if(key_BS<0){  //当按下 空格键 时,游戏暂停
            printf("\n游戏暂停!");
            system("pause");
            system("cls");
        }
        if(key_W<0 && direction!=2){  //当按下 W 键,且原方向不为下时,上移
            direction=1;
        }
        if(key_S<0 && direction!=1){  //当按下 S 键,且原方向不为上时,下移
            direction=2;
        }
        if(key_A<0 && direction!=4){  //当按下 A 键,且原方向不为右时,左移
            direction=3;
        }
        if(key_D<0 && direction!=3){  //当按下 D 键,且原方向不为左时,右移
            direction=4;
        }
    }
}
void UpdateNormal(){
    int max=0;
    for(int i=1;i<high;i++){ //遍历画布
        for(int j=1;j<width;j++){
            if(canvas[i][j] > 0){  //使蛇身的值自增
                canvas[i][j]++;
                if(canvas[i][j]>max){  //定位数值最大点,即蛇尾处
                    max=canvas[i][j];
                    tail_h=i;
                    tail_w=j;
                }
            }
        }
    }
    switch(direction){  //蛇头位置向当前方向移动
        case 1:head_h--;break;
        case 2:head_h++;break;
        case 3:head_w--;break;
        case 4:head_w++;break;
    }
    if(canvas[head_h][head_w] == blank){ //新蛇头在空白处
        canvas[head_h][head_w] = head;
        canvas[tail_h][tail_w] = blank;
    }
    else if(canvas[head_h][head_w] == food){ //新蛇头在食物处
        length++;
        canvas[head_h][head_w] = head;
        do{     //随机出现食物,且食物只能刷新在空白处
            food_h=rand()%high;
            food_w=rand()%width;
        }while(canvas[food_h][food_w]!=blank);
        canvas[food_h][food_w]= food;
    }
    else{ //新蛇头在边界处或蛇身处
        Isover=0;
    }
}
void gotoxy(int x,int y){ //回调光标
    COORD pos;
    pos.X=x-1;
    pos.Y=y-1;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
void HideCursor(){ //隐藏光标函数
	CONSOLE_CURSOR_INFO cursor;
	cursor.bVisible = FALSE;
	cursor.dwSize = sizeof(cursor);
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorInfo(handle, &cursor);
}

           

以上内容在观看河海大学童晶老师的C语言游戏课程的基础上总结改进完成。

继续阅读