天天看點

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語言遊戲課程的基礎上總結改進完成。

繼續閱讀