C語言實現貪吃蛇小遊戲開發

本文實例為大傢分享瞭C語言實現貪吃蛇小遊戲的具體代碼,供大傢參考,具體內容如下

程序介紹

代碼

#include<stdafx.h>            //vc自帶頭文件
#include<stdio.h>            //標準輸入輸出函數庫
#include<time.h>            //用於獲得隨機數
#include<windows.h>            //控制dos界面
#include<stdlib.h>            //即standard library標志庫頭文件,裡面定義瞭一些宏和通用工具函數
#include<conio.h>            //接收鍵盤輸入輸出

/*******宏  定  義*******/
#define U 1
#define D 2
#define L 3 
#define R 4      //蛇的狀態,U:上 ;D:下;L:左 R:右

/*******定  義  全  局  變  量 *******/
typedef struct snake         //蛇身的一個節點
{
    int x;
    int y;
    struct snake *next;
}snake;
int score=0,add=10;            //總得分與每次吃食物得分
int HighScore = 0;            //最高分
int status,sleeptime=200;    //蛇前進狀態,每次運行的時間間隔
snake *head, *food;            //蛇頭指針,食物指針
snake *q;                    //遍歷蛇的時候用到的指針
int endgamestatus=0;        //遊戲結束的情況,1:撞到墻;2:咬到自己;3:主動退出遊戲。
HANDLE hOut;                //控制臺句柄


/*******函  數  聲  明 *******/
void gotoxy(int x,int y);   //設置光標位置
int color(int c);           //更改文字顏色
void printsnake();          //字符畫---蛇
void welcometogame();       //開始界面
void createMap();           //繪制地圖
void scoreandtips();        //遊戲界面右側的得分和小提示
void initsnake();           //初始化蛇身,畫蛇身
void createfood();          //創建並隨機出現食物
int biteself();             //判斷是否咬到瞭自己
void cantcrosswall();       //設置蛇撞墻的情況
void speedup();                //加速
void speeddown();            //減速
void snakemove();           //控制蛇前進方向
void keyboardControl();     //控制鍵盤按鍵
void Lostdraw();            //遊戲結束界面
void endgame();             //遊戲結束
void choose();                //遊戲失敗之後的選擇
void File_out();            //在文件中讀取最高分
void File_in();                //儲存最高分進文件
void explation();           //遊戲說明

/**
 * 設置光標位置
 */
void gotoxy(int x,int y)
{
    COORD c;
    c.X=x;
    c.Y=y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}
 
/**
 * 文字顏色函數      此函數的局限性:1、隻能Windows系統下使用   2、不能改變背景顏色
 */
int color(int c)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);        //更改文字顏色
    return 0;
}

/*
*   字符畫---蛇
*/
void printsnake()
{
    gotoxy(35,1);
    color(6);
    printf("/^\\/^\\");      //蛇眼睛

    gotoxy(34,2);
    printf("|__|  O|");      //蛇眼睛

    gotoxy(33,2);
    color(2);
    printf("_");

    gotoxy(25,3);
    color(12);
    printf("\\/");          //蛇信

    gotoxy(31,3);
    color(2);
    printf("/");

    gotoxy(37,3);
    color(6);
    printf(" \\_/");         //蛇眼睛

    gotoxy(41,3);
    color(10);
    printf(" \\");

    gotoxy(26,4);
    color(12);
    printf("\\____");       //舌頭

    gotoxy(32,4);
    printf("_________/");

    gotoxy(31,4);
    color(2);
    printf("|");

    gotoxy(43,4);
    color(10);
    printf("\\");

    gotoxy(32,5);
    color(2);
    printf("\\_______");    //蛇嘴

    gotoxy(44,5);
    color(10);
    printf("\\");

    gotoxy(39,6);
    printf("|     |                  \\");  //下面都是畫蛇身

    gotoxy(38,7);
    printf("/      /                   \\");

    gotoxy(37,8);
    printf("/      /                    \\ \\");

    gotoxy(35,9);
    printf("/      /                       \\ \\");

    gotoxy(34,10);
    printf("/     /                          \\  \\");

    gotoxy(33,11);
    printf("/     /             _----_         \\   \\");

    gotoxy(32,12);
    printf("/     /           _-~      ~-_         |  |");

    gotoxy(31,13);
    printf("(      (        _-~    _--_    ~-_     _/  |");

    gotoxy(32,14);
    printf("\\     ~-____-~    _-~    ~-_    ~-_-~    /");

    gotoxy(33,15);
    printf("~-_           _-~          ~-_       _-~");

    gotoxy(35,16);
    printf("~--______-~                ~-___-~");
}


/**
 * 開始界面
 */
void welcometogame()
{
    int n;
    int i,j = 1;
    gotoxy(43,18);
    color(11);
    printf("貪 吃 蛇 大 作 戰");
    color(14);                      //黃色邊框
    for (i = 20; i <= 26; i++)       //輸出上下邊框┅
    {
        for (j = 27; j <= 74; j++)  //輸出左右邊框┇
        {
            gotoxy(j, i);
            if (i == 20 || i == 26)
            {
                printf("-");
            }
            else if (j == 27 || j == 74)
            {
                printf("|");
            }
        }
    }
    color(12);
    gotoxy(35, 22);
    printf("1.開始遊戲");
    gotoxy(55, 22);
    printf("2.遊戲說明");
    gotoxy(35, 24);
    printf("3.退出遊戲");
    gotoxy(29,27);
    color(3);
    printf("請選擇[1 2 3]:[ ]\b\b");        //\b為退格,使得光標處於[]中間
    color(14);
    scanf("%d", &n);            //輸入選項
    switch (n)
    {
        case 1:
            system("cls");
            createMap();        //創建地圖
            initsnake();        //初始化蛇身
            createfood();       //創建食物
            keyboardControl();    //按鍵控制
            break;
        case 2:
            explation();          //遊戲說明函數
            break;
        case 3:
            exit(0);             //退出遊戲
            break;
        default:                //輸入非1~3之間的選項
            color(12);
            gotoxy(40,28);
            printf("請輸入1~3之間的數!");
            getch();            //輸入任意鍵
            system("cls");        //清屏
            printsnake();
            welcometogame();
    }
}

/**
 * 創建地圖
 */
void createMap()
{
    int i,j;
    for(i=0;i<58;i+=2)        //打印上下邊框
    {
        gotoxy(i,0);
        color(5);            //深紫色的邊框
        printf("□");
        gotoxy(i,26);
        printf("□");
    }
    for(i=1;i<26;i++)        //打印左右邊框
    {
        gotoxy(0,i);
        printf("□");                        
        gotoxy(56,i);
        printf("□");        
    }
    for(i = 2;i<56;i+=2)    //打印中間網格
    {
        for(j = 1;j<26;j++)
        {
            gotoxy(i,j);
            color(3);
            printf("■");
        }
    }
}

 /**
 *  遊戲界面右側的得分和小提示
 */
void scoreandtips()
{
    File_out();
    gotoxy(64,4);
    color(11);
    printf("☆最高記錄☆:%d",HighScore);
    gotoxy(64,8);
    color(14);
    printf("得分:%d  ",score);
    color(13);
    gotoxy(73,11);
    printf("小 提 示");
    gotoxy(60,13);
    color(6);
    printf("╬ ┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅ ╬");
    gotoxy(60,25);
    printf("╬ ┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅ ╬");
    color(3);
    gotoxy(64,14);
    printf("每個食物得分:%d分",add);
    gotoxy(64,16);
    printf("不能撞墻,不能咬到自己");
    gotoxy(64,18);
    printf("用↑ ↓ ← →分別控制蛇的移動");
    gotoxy(64,20);
    printf("F1鍵加速,F2鍵減速");
    gotoxy(64,22);
    printf("空格鍵暫停遊戲");
    gotoxy(64,24);
    printf("Esc鍵退出遊戲");
}

 /**
 * 初始化蛇身,畫蛇身
 */
void initsnake()
{
    snake *tail;
    int i;
    tail=(snake*)malloc(sizeof(snake));//從蛇尾開始,頭插法,以x,y設定開始的位置//
    tail->x=24;             //蛇的初始位置(24,5)
    tail->y=5;
    tail->next=NULL;
    for(i=1;i<=4;i++)       //設置蛇身,長度為5
    {
        head=(snake*)malloc(sizeof(snake)); //初始化蛇頭
        head->next=tail;        //蛇頭的下一位為蛇尾
        head->x=24+2*i;         //設置蛇頭位置
        head->y=5;
        tail=head;              //蛇頭變成蛇尾,然後重復循環
    }
    while(tail!=NULL)        //從頭到尾,輸出蛇身
    {
        gotoxy(tail->x,tail->y);
        color(14);
        printf("★");       //輸出蛇身,蛇身使用★組成
        tail=tail->next;    //蛇頭輸出完畢,輸出蛇頭的下一位,一直輸出到蛇尾
    }
}

 /**
 * 隨機出現食物
 */
void createfood()
{
    snake *food_1;
    srand((unsigned)time(NULL));            //初始化隨機數
    food_1=(snake*)malloc(sizeof(snake));   //初始化food_1
    while((food_1->x%2)!=0)                    //保證其為偶數,使得食物能與蛇頭對其,然後食物會出現在網格線上
    {
        food_1->x=rand()%52+2;              //食物隨機出現
    }
    food_1->y=rand()%24+1;
    q=head;
    while(q->next==NULL)
    {
        if(q->x==food_1->x && q->y==food_1->y) //判斷蛇身是否與食物重合
        {
            free(food_1);               //如果蛇身和食物重合,那麼釋放食物指針
            createfood();               //重新創建食物
        }
        q=q->next;
    }
    gotoxy(food_1->x,food_1->y);
    food=food_1;
    color(12);
    printf("●");           //輸出食物
}
 
 /**
 * 判斷是否咬到瞭自己
 */
int biteself()
{
    snake *self;            //定義self為蛇身上的一個節點
    self=head->next;        //self是蛇頭之外的蛇身上的節點
    while(self!=NULL)
    {
        if(self->x==head->x && self->y==head->y)    //如果self和蛇身上的節點重合
        {
            return 1;       //返回1
        }
        self=self->next;
    }
    return 0;
}

 /**
 * 設置蛇撞墻的情況
 */
void cantcrosswall()
{  
    if(head->x==0 || head->x==56 ||head->y==0 || head->y==26) //如果蛇頭碰到瞭墻壁
    {
        endgamestatus=1;        //返回第一種情況
        endgame();              //出現遊戲結束界面
    }
}

/**
 *  加速,蛇吃到食物會自動提速,並且按F1會加速
 */
void speedup()
{
    if(sleeptime>=50)
    {
        sleeptime=sleeptime-10;
        add=add+2;

    }
}

/**
 *  加速,按F2會減速
 */
void speeddown()
{
    if(sleeptime<350)               //如果時間間隔小於350
    {
        sleeptime=sleeptime+30;     //時間間隔加上30
        add=add-2;                  //每吃一次食物的得分減2

    }
}

/**
 *  控制方向    問題:為什麼要設置status,而不使用前兩章中接收鍵盤按鍵的方法
 */
void snakemove()    //蛇前進,上U,下D,左L,右R
{
    snake * nexthead;
    cantcrosswall();
    nexthead=(snake*)malloc(sizeof(snake));        //為下一步開辟空間
    if(status==U)
    {
        nexthead->x=head->x;        //向上前進時,x坐標不動,y坐標-1
        nexthead->y=head->y-1;
        nexthead->next=head;
        head=nexthead;
        q=head;                 //指針q指向蛇頭
        if(nexthead->x==food->x && nexthead->y==food->y)    //如果下一個有食物 下一個位置的坐標和食物的坐標相同
        {
            
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");       //原來食物的位置,從●換成★
                q=q->next;          //指針q指向的蛇身的下一位也執行循環裡的操作
                
            }
            score=score+add;        //吃瞭一個食物,在總分上加上食物的分
            speedup();
            createfood();           //創建食物
        }
        else                        
        {
            while(q->next->next!=NULL)    //如果沒遇到食物
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");           //蛇正常往前走,輸出當前位置的蛇身
                q=q->next;              //繼續輸出整個蛇身
            }
            gotoxy(q->next->x,q->next->y);  //經過上面的循環,q指向蛇尾,蛇尾的下一位,就是蛇走過去的位置
            color(3);
            printf("■");
            free(q->next);      //進行輸出■之後,釋放指向下一位的指針
            q->next=NULL;       //指針下一位指向空
        }
    }
    if(status==D)
    {
        nexthead->x=head->x;        //向下前進時,x坐標不動,y坐標+1
        nexthead->y=head->y+1;
        nexthead->next=head;
        head=nexthead;
        q=head;
        if(nexthead->x==food->x && nexthead->y==food->y)  //有食物
        {
            
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");
                q=q->next;
            }
            score=score+add;
            speedup();
            createfood();
        }
        else                               //沒有食物
        {
            while(q->next->next!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");
                q=q->next;
            }
            gotoxy(q->next->x,q->next->y);
            color(3);
            printf("■");
            free(q->next);
            q->next=NULL;
        }
    }
    if(status==L)
    {
        nexthead->x=head->x-2;        //向左前進時,x坐標向左移動-2,y坐標不動
        nexthead->y=head->y;
        nexthead->next=head;
        head=nexthead;
        q=head;
        if(nexthead->x==food->x && nexthead->y==food->y)//有食物
        {
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");
                q=q->next;
            }
            score=score+add;
            speedup();
            createfood();
        }
        else                                //沒有食物
        {
            while(q->next->next!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");
                q=q->next;        
            }
            gotoxy(q->next->x,q->next->y);
            color(3);
            printf("■");
            free(q->next);
            q->next=NULL;
        }
    }
    if(status==R)
    {
        nexthead->x=head->x+2;        //向右前進時,x坐標向右移動+2,y坐標不動
        nexthead->y=head->y;
        nexthead->next=head;
        head=nexthead;
        q=head;
        if(nexthead->x==food->x && nexthead->y==food->y)//有食物
        {
            while(q!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");
                q=q->next;
            }
            score=score+add;
            speedup();
            createfood();
        }
        else                                         //沒有食物
        {
            while(q->next->next!=NULL)
            {
                gotoxy(q->x,q->y);
                color(14);
                printf("★");
                q=q->next;        
            }
            gotoxy(q->next->x,q->next->y);
            color(3);
            printf("■");
            free(q->next);
            q->next=NULL;
        }
    }
    if(biteself()==1)       //判斷是否會咬到自己
    {
        endgamestatus=2;
        endgame();
    }
}


/**
 * 控制鍵盤按鍵
 */
void keyboardControl()
{
    status=R;       //初始蛇向右移動
    while(1)
    {
        scoreandtips();
        if(GetAsyncKeyState(VK_UP) && status!=D)            //GetAsyncKeyState函數用來判斷函數調用時指定虛擬鍵的狀態
        {
            status=U;           //如果蛇不是向下前進的時候,按上鍵,執行向上前進操作
        }
        else if(GetAsyncKeyState(VK_DOWN) && status!=U)     //如果蛇不是向上前進的時候,按下鍵,執行向下前進操作
        {
            status=D;
        }
        else if(GetAsyncKeyState(VK_LEFT)&& status!=R)      //如果蛇不是向右前進的時候,按左鍵,執行向左前進
        {
            status=L;
        }
        else if(GetAsyncKeyState(VK_RIGHT)&& status!=L)     //如果蛇不是向左前進的時候,按右鍵,執行向右前進
        {
            status=R;
        }
        if(GetAsyncKeyState(VK_SPACE))        //按暫停鍵,執行pause暫停函數
        {
            while(1)
            {
                Sleep(300); //sleep()函數,頭文件#include <unistd.h>  另進程暫停,知道達到裡面設定的參數的時間。
                if(GetAsyncKeyState(VK_SPACE))      //按空格鍵暫停
                {
                    break;
                }
                
            }       
        }
        else if(GetAsyncKeyState(VK_ESCAPE))
        {
            endgamestatus=3;    //按esc鍵,直接到結束界面
            break;
        }
        else if(GetAsyncKeyState(VK_F1))    //按F1鍵,加速
        {
            speedup();
        }
        else if(GetAsyncKeyState(VK_F2))    //按F2鍵,減速
        {
            speeddown();
            
        }
        Sleep(sleeptime);
        snakemove();
    }
}

/**
 * 儲存最高分進文件
 */
void File_in()
{
    FILE *fp;
    fp = fopen("save.txt", "w+");       //以讀寫的方式建立一個名為save.txt的文件
    fprintf(fp, "%d", score);           //把分數寫進文件中
    fclose(fp);                         //關閉文件
}

/**
 * 在文件中讀取最高分
 */
void File_out()
{
    FILE *fp;
    fp = fopen("save.txt", "a+");       //打開文件save.txt
    fscanf(fp, "%d", &HighScore);       //把文件中的最高分讀出來
    fclose(fp);                         //關閉文件
}

/*
*   遊戲說明
*/
void explation()
{
    int i,j = 1;
    system("cls");
    color(13);
    gotoxy(44,3);
    printf("遊戲說明");
    color(2);
    for (i = 6; i <= 22; i++)   //輸出上下邊框===
    {
        for (j = 20; j <= 75; j++)  //輸出左右邊框||
        {
            gotoxy(j, i);
            if (i == 6 || i == 22) printf("=");
            else if (j == 20 || j == 75) printf("||");
        }
    }
    color(3);
    gotoxy(30,8);
    printf("tip1: 不能撞墻,不能咬到自己");
    color(10);
    gotoxy(30,11);
    printf("tip2: 用↑.↓.←.→分別控制蛇的移動");
    color(14);
    gotoxy(30,14);
    printf("tip3: F1 為加速,F2 為減速");
    color(11);
    gotoxy(30,17);
    printf("tip4: 按空格鍵暫停遊戲,再按空格鍵繼續");
    color(4);
    gotoxy(30,20);
    printf("tip5: Esc :退出遊戲");
    getch();                //按任意鍵返回主界面
    system("cls");
    printsnake();
    welcometogame();
}

/**
 * 結束遊戲
 */
void endgame()
{
    system("cls");
    if(endgamestatus==1)
    {
        
        Lostdraw();
        gotoxy(35,9);
        color(12);
        printf("對不起,您撞到墻瞭。遊戲結束!");
    }
    else if(endgamestatus==2)
    {
        
        Lostdraw();
        gotoxy(35,9);
        color(12);
        printf("對不起,您咬到自己瞭。遊戲結束!");
    }
    else if(endgamestatus==3)
    {
        Lostdraw();
        gotoxy(40,9);
        color(12);
        printf("您已經結束瞭遊戲。");
    }
    gotoxy(43,12);
    color(13);
    printf("您的得分是 %d",score);

    if(score >= HighScore)
    {
        color(10);
        gotoxy(33,16);
        printf("創紀錄啦!最高分被你刷新啦,真棒!!!");
        File_in();              //把最高分寫進文件
    }
    else
    {
        color(10);
        gotoxy(33,16);
        printf("繼續努力吧~ 你離最高分還差:%d",HighScore-score);
    }
    choose();
}

/**
 * 邊框下面的分支選項
 */
void choose()
{
    int n;
    gotoxy(25,23);
    color(12);
    printf("我要重新玩一局-------1");
    gotoxy(52,23);
    printf("不玩瞭,退出吧-------2");
    gotoxy(46,25);
    color(11);
    printf("選擇:");
    scanf("%d", &n);
    switch (n)
    {
    case 1:
        system("cls");          //清屏
        score=0;                //分數歸零
        sleeptime=200;            //設定初始速度
        add = 10;                //使add設定為初值,吃一個食物得分10,然後累加
        printsnake();           //返回歡迎界面
        welcometogame();
        break;
    case 2:
        exit(0);                //退出遊戲
        break;
    default:
        gotoxy(35,27);
        color(12);
        printf("※※您的輸入有誤,請重新輸入※※");
        system("pause >nul");
        endgame();
        choose();
        break;
    }

}
/**
 * 失敗界面
 */
void Lostdraw()
{
    system("cls");
    int i;
    gotoxy(45,2);
    color(6);
    printf("\\\\\\|///");
    gotoxy(43,3);
    printf("\\\\");
    gotoxy(47,3);
    color(15);
    printf(".-.-");
    gotoxy(54,3);
    color(6);
    printf("//");

    gotoxy(44,4);
    color(14);
    printf("(");

    gotoxy(47,4);
    color(15);
    printf(".@.@");

    gotoxy(54,4);
    color(14);
    printf(")");

    gotoxy(17,5);
    color(11);
    printf("+------------------------");

    gotoxy(35,5);
    color(14);
    printf("oOOo");

    gotoxy(39,5);
    color(11);
    printf("----------");

    gotoxy(48,5);
    color(14);
    printf("(_)");

    gotoxy(51,5);
    color(11);
    printf("----------");

    gotoxy(61,5);
    color(14);
    printf("oOOo");

    gotoxy(65,5);
    color(11);
    printf("-----------------+");
    
    for(i = 6;i<=19;i++)        //豎邊框
    {
        gotoxy(17,i);
        printf("|");
        gotoxy(82,i);
        printf("|");
    }

    gotoxy(17,20);
    printf("+---------------------------------");

    gotoxy(52,20);
    color(14);
    printf("☆☆☆〃");

    gotoxy(60,20);
    color(11);
    printf("----------------------+");

}

/**
* 主函數
*/
int main()
{    
    system("mode con cols=100 lines=30");   //設置控制臺的寬高
    printsnake();
    welcometogame();
    File_out();
    keyboardControl();
    endgame();
    return 0;
}

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: