C語言七彩貪喫蛇源代碼---AI自動尋徑,分數排行,數據保存,背景音樂難度設置等 控制檯小遊戲

-------------------------------------------------------------------------------------------

七彩貪喫蛇小遊戲V1.0

        使用純C語言編寫的控制檯貪喫蛇小遊戲,可設置遊戲難度,有連擊分數加成,蛇身顏色自動隨機變化,緩衝防閃,數據存儲保護,排行榜與音效等功能,VC++與VS編譯均通過,只使用VC自帶庫。

-------------------------------------------------------------------------------------------

純C語言編寫,手感十足。

      ---目前最高紀錄爲107400分,0 0 一盤大概玩了半小時。。。。

      ---實乃無聊時必備解壓小遊戲之良品~~~

      ---個人製作,遊戲可能會有少許bug,敬請諒解,轉載請註明

-------------------------------------------------------------------------------------------

 

 

遊戲截圖:

-----------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------

 

-----------------------------------------------------------------------

源代碼:

 

//貪喫蛇彩色版源代碼,2018/3/8,僅供互相交流學習

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>
#include<math.h>
#include<time.h>
#include "StdAfx.h"
int snakeleng = 4;                        //全局變量,蛇長度
int last_dir = 'd';                      //上一次蛇頭和默認朝向
int markmax[101][2];                   //存儲蛇的座標信息
int n=1,l=0,g=150,e=30,h=15;          //l遊戲分數,g遊戲速度,n遊戲等級,e,h食物座標
int speedflag;                        //遊戲調速自定義
unsigned char c;                     //全局接收鍵盤按鍵變量
int randcolor();
void checking();
void msg_init();
void gotoxy(int x,int y);
void HideCursor();
void GUI();
void localtime();
void marksort();
void srandcolor(int randcolor);
void keyreceive();
void gamespeedset();
void snakemsg();
void initsnake();
void printmark();
void foodrandom();
void ready_game();
void read_next_coord();
void markrank();
void food_check();
void checking();
void game_opinion();
struct body  
{  
    int x;  
    int y;  
};  
struct body snake_body[500];    //蛇身的長度結構體,最長500               
void msg_init()
{
    n=1;
    l=0;
    g=150;
    snakeleng = 4;
}

void gotoxy(int x,int y)
{
    COORD c;
    c.X=x-1;
    c.Y=y-1;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}

HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); 
void HideCursor()//隱藏光標
{
    CONSOLE_CURSOR_INFO cursor_info = {1, 0}; 
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void GUI()
{
    int j=1,i=0;
    SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN);
    for(i=0;i<24;i++)
    {
        gotoxy(57,j++);
        printf("■"); 
        gotoxy(1,j);
        printf("■");
        gotoxy(81,j);
        printf("■");
        gotoxy(1,25);
        printf("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
        gotoxy(1,1);
        printf("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
    }
}

void localtime()                                   //載入並刷新系統RTC時間
{ 
    time_t now; 
    struct tm *timenow; 
    char time_end[1024];
    char time_start[1024];
    time(&now); 
    timenow = localtime(&now);                 
    SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
    strftime(time_end,1024,"%Y年%m月%d日",timenow);
    strftime(time_start,1024,"%H:%M:%S",timenow);
    gotoxy(63,17);
    printf("%s",time_end);
    gotoxy(63,19);
    printf("%s",time_start);

}

void marksort()                   //分數排序
{
    int i,x,temp;
    for(x=0;x<10;x++)                                   //先將排行榜的分數中最小的篩選出來
    {
        if(markmax[9][0]>markmax[x][0])
        {   
            temp=markmax[9][0];
            markmax[9][0]=markmax[x][0];
            markmax[x][0]=temp;
            temp=markmax[9][1];
            markmax[9][1]=markmax[x][1];
            markmax[x][1]=temp;
        }
    } 

    if(l>markmax[9][0])                                  //如果大於最小的纔會開始排序
    {
        markmax[9][0]=l;
        markmax[9][1]=snakeleng+1;
        for(x=0;x<10;x++)                                 //排序並交換排行位置
        {
            for(i=x;i<10;i++)
            {
                if(markmax[x][0]<markmax[i][0])
                {
                    temp=markmax[x][0];
                    markmax[x][0]=markmax[i][0];
                    markmax[i][0]=temp;
                    temp=markmax[x][1];
                    markmax[x][1]=markmax[i][1];
                    markmax[i][1]=temp;
                }
            }

        }
    }
}

int randcolor()
{
    int randcolor;
    srand((int)time(0));
    randcolor=rand()%10;
    return randcolor;
}

void srandcolor(int randcolor)
{
    switch(randcolor)                             //產生隨機顏色
    {
    case 0:
        SetConsoleTextAttribute(handle, FOREGROUND_GREEN ); break;
    case 1:
        SetConsoleTextAttribute(handle, FOREGROUND_RED ); break;
    case 2:
        SetConsoleTextAttribute(handle, FOREGROUND_BLUE ); break;
    case 3:
        SetConsoleTextAttribute(handle, FOREGROUND_GREEN | FOREGROUND_RED); break;
    case 4:
        SetConsoleTextAttribute(handle, FOREGROUND_GREEN | FOREGROUND_BLUE); break;
    case 5:
        SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN ); break;
    case 6:
        SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED ); break;
    case 7:
        SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE ); break;
    case 8:
        SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED); break;
    case 9:
        SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE); break;
    }

}

void keyreceive()                  //遊戲中鍵盤監聽和驅動模塊
{
    if(kbhit())
        c=getch();                          //判斷按鍵模塊
    if((c==75||c=='a'||c=='A')&&last_dir!='d')
    {
        snake_body[0].x=snake_body[0].x-2;  
        last_dir = 'a';
    }

    else if((c==75||c=='a'||c=='A')&&last_dir=='d')
    {
        snake_body[0].x=snake_body[0].x+2;  
        last_dir = 'd';
    }

    if((c==77||c=='d'||c=='D')&&last_dir!='a')
    {
        last_dir = 'd';
        snake_body[0].x=snake_body[0].x+2;  
    }

    else if((c==77||c=='d'||c=='D')&&last_dir=='a')
    {
        last_dir = 'a';
        snake_body[0].x=snake_body[0].x-2;  
    }

    if((c==80||c=='s'||c=='S')&&last_dir!='w')
    {
        snake_body[0].y=snake_body[0].y+1;
        last_dir = 's';
    }

    else if((c==80||c=='s'||c=='S')&&last_dir=='w')
    {
        snake_body[0].y=snake_body[0].y-1;
        last_dir = 'w';
    }

    if((c==72||c=='w'||c=='W')&&last_dir!='s')
    { 
        snake_body[0].y=snake_body[0].y-1;  
        last_dir = 'w';
    }

    else if((c==72||c=='w'||c=='W')&&last_dir=='s')
    {
        snake_body[0].y=snake_body[0].y+1;  
        last_dir = 's';
    }

    if(c==32)                                //空格鍵暫停及設置模塊
    {
        while(1)
        {
            gotoxy(11,25);
            srandcolor(randcolor());
            printf("遊戲暫停中,方向鍵繼續,'i'鍵進入設置");
            Sleep(1000);
            SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN);
            gotoxy(1,25);
            printf("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");//防抖動
            Sleep(1000);

            if(kbhit())
            {
                c=getch();
                if(c=='i'||c=='I')
                {
                    game_opinion();               //設置模塊
                    GUI();
                }
                break;

            }
        }
    }
    srandcolor(randcolor());
    gotoxy(snake_body[0].x,snake_body[0].y);            //蛇的關節處變化,更加美觀
    printf("●");                                                
}


void gamespeedset()                     //速度設定模塊
{
    if(speedflag==0)
    {
        if(l>=1500&&l<=4000)
        {
            g=120;
            n=2;
        }
        if(l>4000&&l<=6000)
        {
            g=100;
            n=3;
        }
        if(l>6000&&l<=15000)
        {
            g=80;
            n=4;
        }
        if(l>15000&&l<=30000)
        {
            g=50;
            n=5;
        }
        if(l>30000)
        {
            g=30;
            n=6;
        }
    }
    if(speedflag==1)                     //調速則保持速度
    {
        switch(n)
        {
        case 1:g=150;break;
        case 2:g=120;break;
        case 3:g=100;break;
        case 4:g=80;break;
        case 5:g=50;break;
        case 6:g=30;break;
        }
    }

    Sleep(g); 

}

void snakemsg()                           //信息顯示模塊
{
    gotoxy(63,4);
    printf("當前難度等級:%d",n);
    gotoxy(63,8);
    printf("遊戲分數:%d",l);
    gotoxy(63,6);
    printf("蛇身長度:%d",snakeleng+1);
    gotoxy(63,21);
    printf("Dz by Yuan");
    gotoxy(63,12);
    printf("方向鍵控制小蛇");
    gotoxy(63,10);
    printf("最高記錄:%d",markmax[0][0]);
    gotoxy(63,14);
    printf("空格鍵暫停並設置 ");
    gotoxy(63,23);
    printf("Defend Your Time");
}

void initsnake()                              //初始化蛇
{  
    int i,temp=7;  
    system("cls");
    last_dir = 'd';
    for(i=0;i<3;i++,temp-=2)  
    {  
        snake_body[i].x=temp;  
        snake_body[i].y=10;  
        srandcolor(randcolor());
    }  
}  

void printmark()                            //打印結束遊戲分數和評價
{
    gotoxy(27,11);
    printf("GAME OVER!");
    gotoxy(26,14);
    printf("最終得分:%d\n\n\n\n\n\n",l);
    if(l<=5000)
    {
        gotoxy(24,17);
        printf("評價:有待提高⊙o⊙");
    }
    if(l>5000&&l<=30000)
    {gotoxy(24,17);
    printf("評價:其實還不錯!!!");}

    if(l>30000&&l<=60000)
    {gotoxy(24,17);
    printf("評價:閣下很厲害!");}
    if(l>60000)
    {
        gotoxy(24,17);
        printf("評價:閣下已經超神了!!!");
    }
    while(1)
    {
        gotoxy(20,20);
        printf("按方向鍵繼續,M 鍵查看排行榜");
        Sleep(800);
        gotoxy(20,20);
        printf("                            ");
        Sleep(800);
        gotoxy(20,20);
        printf("按方向鍵繼續,M 鍵查看排行榜");
        Sleep(200);
        if(kbhit())
            break;
    }

}

void foodrandom()                         //隨機產生食物座標
{
    srand((int)time(0));
    e=rand()%53+3;
    h=rand()%22+2;  
}

void ready_game()                          //進入遊戲前畫面
{
    int k=20;
    while(!kbhit())
    {
        GUI();
        gotoxy(1,2);  
        printf("■                              \n");
        printf("■                               \n");
        printf("■                               \n");
        printf("■                                 * *     \n");
        printf("■                               *     *\n");
        printf("■*                             *         * \n");
        printf("■ *                           *            *  \n");
        printf("■  *                         *               *  \n");
        printf("■   *                       *                  * \n");
        printf("■    *                     *                     * \n");
        printf("■      *                 *                         *\n");
        printf("■        *             *        \n");
        printf("■          *         *          \n");
        printf("■             *   *             \n");
        printf("■                              \n");
        printf("■       ■            ■■■ \n");
        printf("■      ■  ■        ■     ■ \n");
        printf("■    ■     ■      ■■⊙o⊙■ \n");
        printf("■   ■        ■   ■■     ■ \n");
        printf("■  ■           ■ ■      ■   \n");
        printf("■ ■■■ \n");
        printf("■  \n");
        gotoxy(65,15); 
        printf("剩餘%d秒",k);
        gotoxy(64,20);
        printf("按任意鍵進入");
        Sleep(1000);
        k--;
        gotoxy(14,22);
        printf(" 歡 迎 來 到 我 的 貪 喫 蛇  !");
        gotoxy(65,15);
        printf("剩餘%d秒",k);
        gotoxy(64,20);
        printf("           ");
        Sleep(1000);
        k--;
        gotoxy(65,15);
        printf("剩餘%d秒",k);
        if(k==0)
            break;
    }
}


void read_next_coord()          //讀取下一個蛇座標
{  
    int i;  

    for(i=snakeleng;i>0;i--) //遍歷蛇身
    {  
        if(i==snakeleng)    //擦除蛇的尾巴
        {  
            gotoxy(snake_body[i].x,snake_body[i].y);       
            printf("  ");  
        }  
        snake_body[i].x=snake_body[i-1].x;           //座標給上一段蛇身          
        snake_body[i].y=snake_body[i-1].y;    
    }  
    srandcolor(randcolor());
    gotoxy(snake_body[0].x,snake_body[0].y);       
    printf("■");  
}  


void markrank()                  //分數排行榜UI
{ 
    int i;
    GUI();
    while(1)
    {
        for(i=0;i<10;i++)
        {
            gotoxy(4,3);
            printf("     排名           分數          長度記錄");
            if(i!=9)
                gotoxy(4,5+(i*2));
            else
                gotoxy(3,5+(i*2));
            if(markmax[i][0]!=0)
            {
                printf("      %d             %d                ",i+1,markmax[i][0]);
                gotoxy(40,5+(i*2));
                printf(" %d",markmax[i][1]);
            }
            else
            {
                printf("      %d             ****               ",i+1);
                gotoxy(40,5+(i*2));
                printf("****");
            }
        }
        gotoxy(62,13);
        printf("按任意鍵繼續遊戲");
        Sleep(1000);
        gotoxy(62,13);
        printf("                ");
        Sleep(1000);
        if(kbhit())
        {   
            msg_init();
            system("cls");
            break;
        }
    }
}

void food_check()
{
    int i,flag=1;
    while(flag)                  
    {
        for(i=snakeleng;i>=0;i--)     //遍歷蛇身,防止食物生成在蛇身裏
        {  
            if((abs(snake_body[i].x-e)<2) && (abs(snake_body[i].y-h<2)))  
            {  
                e=rand()%53+3;
                h=rand()%22+2;             
                flag = 1;                          //如果生成在蛇身裏就再次循環
                l+=100;                            //運氣不錯也能加分
            }  
            else  
                flag=0;                         
        }  
    }
    flag = 1;                //下次循環再次進行判斷
}

void main()
{
    HideCursor();
    system("color 0a");
    msg_init();
    initsnake(); 
    foodrandom();
    ready_game();
    system("cls");
    GUI(); 
    checking();
}


void game_opinion()
{
    unsigned char set;
    system("cls");
    GUI();
    SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN );
    gotoxy(3,3);
    printf("【設      置】");
    gotoxy(3,10);
    printf("【遊  戲  說  明】");
    gotoxy(3,12);
    printf("    七彩貪喫蛇小遊戲,C語言控制檯製作,VC/VS均測試通過");
    gotoxy(3,14);
    printf("推薦新手嘗試重構代碼,如有問題可加QQ:421736951交流,遊");
    gotoxy(3,15);
    printf("戲製作倉促,作者技術和精力有限,如遇BUG還請見諒!");
    gotoxy(3,17);
    printf("可使用右鍵點擊控制檯設置默認字體爲點陣,可設置窗口大小");
    gotoxy(3,18);
    printf("寬度爲83,高度爲25。");
    gotoxy(3,22);
    printf("                           -----------coding 2018.3.7");
    gotoxy(3,20);
    printf("希望能給編程初學者帶來幫助,請勿將源代碼用於其他用途!");
    gotoxy(60,13);
    printf("方向鍵設置,回車鍵確認");
    while(1)
    {
        if(kbhit())
            set = getch();
        SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED);       
        gotoxy(3,5);
        printf(" 設置難度等級:                        %d   ",n);        //下面代碼都是爲設置界面顯示效果優化
        gotoxy(3,7);
        printf(" 設置蛇身長度:                        %d",snakeleng+1);
        Sleep(5);                                     //防止屏閃
        if(set == 72)
        {   

            gotoxy(3,7);
            SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED);
            printf(" 設置蛇身長度:                        %d       ",snakeleng+1);
            while(1)
            {
                gotoxy(3,5);
                SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN *30| FOREGROUND_GREEN*18);
                printf(" 設置難度等級:                        %d   ",n);
                set = getch();
                speedflag=1;
                if(set==75)
                {  
                    n-=1;
                    set=72;
                }
                if(set==77)
                {
                    n+=1;
                    set=72;
                }
                if(set==80)
                {
                    set=80;
                    SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED);
                    gotoxy(3,5);
                    printf(" 設置難度等級:                        %d   ",n);
                    break;
                }
                if(set==13)
                { 
                    c=77;
                    SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
                    system("cls");
                    break;
                }
                if(n>6||n<1)
                    n=1;
            }
        }
        if(set == 80)
        {   
            while(1)
            {
                gotoxy(3,7);
                SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN *30| FOREGROUND_GREEN*18);
                if(snakeleng+1<10)
                    printf(" 設置蛇身長度:                        %d   ",snakeleng+1);
                if((snakeleng+1>9)&&(snakeleng+1<100))  
                    printf(" 設置蛇身長度:                        %d  ",snakeleng+1);
                if((snakeleng+1>99)&&(snakeleng+1<500))
                    printf(" 設置蛇身長度:                        %d ",snakeleng+1);
                set = getch();
                if(set==75)
                {  
                    snakeleng-=1;
                    set=80;
                }
                if(set==77)
                {
                    snakeleng+=1;
                    set=80;
                }
                if(set==72)
                {
                    set=72;
                    break;
                }
                if(snakeleng>479)                                                    //可設置的長度最長爲480
                    snakeleng=4;
                if(snakeleng<4)
                    snakeleng=479;
                if(set==13)
                    break;
            }
        }
        if(set==13)
        {
            SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
            system("cls");
            break;
        }
    }
    c=77;
}


void checking()                           //遊戲運行中核心檢測模塊
{
    int i,eatflag=0,live;
    unsigned char score;                //接受分數按鍵
    while(1)
    { 
        read_next_coord();
        keyreceive();                              //在循環中沒有按鍵時也需要接收keyreceive(); 
        if(kbhit())
            keyreceive();                               //非阻塞按鍵並行發生,以此改變蛇關節的外形及顏色

        for(i=snakeleng;i>=2;i--)                             //從3蛇身開始纔可能頭碰撞到尾巴
        {  
            if(snake_body[0].x==snake_body[i].x && snake_body[0].y==snake_body[i].y)  
            {  
                eatflag=1; 
                live = 0;
            }  
        }
        srandcolor(randcolor()+3);
        gotoxy(e,h);                                 //產生食物
        printf("●");
        if(abs(e-snake_body[0].x)<2&&abs(h-snake_body[0].y)<2)
        {
            snakeleng+=1;
            l+=600;
            gotoxy(e,h);                            //喫到後迅速擦除食物,並形成蛇身
            printf(" ");
            snakemsg();
            Sleep(120);                          //喫到了變化顏色刷新閃爍一下分數等信息,並給一定延時減小遊戲難度            
            foodrandom();                       //隨機升成下一個食物座標
            food_check();
            srandcolor(randcolor()+1);
            gotoxy(e,h);
            printf("●");
            snake_body[snakeleng].x=snake_body[snakeleng-1].x;
            snake_body[snakeleng].y=snake_body[snakeleng-1].y; 
        }

        if((snake_body[0].x>=57||snake_body[0].x<=1||snake_body[0].y>=25||snake_body[0].y<=1||eatflag==1)) //如果撞牆或者自殺死亡
        {
            GUI();
            live=0;                                                   //遊戲結束
            marksort();                                             //死亡排行算法     
            printmark();
            system("cls");
            last_dir='d';
            score=getch();
            if((score!='m')&&(score!='M'))            //如果不查看排行榜,就快速遊戲
            {
                system("cls");                            //清屏
                msg_init();                             //初始化顯示信息
                initsnake();                           //初始化蛇身
                live=1;                              //讓蛇處於存活狀態
                speedflag=0;                       //默認不調速
                main();                          //*主函數(按方向鍵將會快速再次開始遊戲,其它鍵進入最初界面)
            }
            else                        //查看排行榜 
                markrank();                //排行算法
            main();
        }
        localtime();
        SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN);
        snakemsg();
        gamespeedset();                       //難度等級設定
    }
}
--------------------- 
作者:qq_16620025 
來源:CSDN 
原文:https://blog.csdn.net/qq_16620025/article/details/97148223 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章