1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          貪吃蛇

          來源:互聯網轉載 時間:2024-01-29 08:01:37

          文章目錄

          • 游戲說明
          • 游戲效果展示
          • 游戲代碼
          • 游戲代碼詳解
            • 游戲框架構建
            • 隱藏光標
            • 光標跳轉
            • 初始化界面
            • 顏色設置
            • 初始化蛇
            • 隨機生成食物
            • 打印蛇與覆蓋蛇
            • 移動蛇
            • 游戲主體邏輯函數
            • 執行按鍵
            • 判斷得分與結束
            • 從文件讀取最高分
            • 更新最高分到文件
            • 主函數

          游戲說明

          游戲界面當中沒有打印相關的按鍵說明,這里先逐一列出,貪吃蛇游戲按鍵說明:

          1. 按方向鍵上下左右,可以實現蛇移動方向的改變。
          2. 短時間長按方向鍵上下左右其中之一,可實現蛇向該方向的短時間加速移動。
          3. 按空格鍵可實現暫停,暫停后按任意鍵繼續游戲。
          4. 按Esc鍵可直接退出游戲。
          5. 按R鍵可重新開始游戲。

          除此之外,本游戲還擁有計分系統,可保存玩家的歷史最高記錄。

          游戲效果展示

          貪吃蛇游戲當中蛇的移動速度可以進行調整,動圖當中把速度調得較慢(速度太快導致動圖上蛇身顯示不全),下面給出的代碼當中將蛇的速度調整到了合適的位置,大家可以試試。

          游戲代碼

          博友們可以將以下代碼復制到自己的編譯器當中運行:

          #include <stdio.h>#include <Windows.h>#include <stdlib.h>#include <time.h>#include <conio.h>#define ROW 22 //游戲區行數#define COL 42 //游戲區列數#define KONG 0 //標記空(什么也沒有)#define WALL 1 //標記墻#define FOOD 2 //標記食物#define HEAD 3 //標記蛇頭#define BODY 4 //標記蛇身#define UP 72 //方向鍵:上#define DOWN 80 //方向鍵:下#define LEFT 75 //方向鍵:左#define RIGHT 77 //方向鍵:右#define SPACE 32 //暫停#define ESC 27 //退出//蛇頭struct Snake{    int len; //記錄蛇身長度int x; //蛇頭橫坐標int y; //蛇頭縱坐標}snake;//蛇身struct Body{    int x; //蛇身橫坐標int y; //蛇身縱坐標}body[ROW*COL]; //開辟足以存儲蛇身的結構體數組int face[ROW][COL]; //標記游戲區各個位置的狀態//隱藏光標void HideCursor();//光標跳轉void CursorJump(int x, int y);//初始化界面void InitInterface();//顏色設置void color(int c);//從文件讀取最高分void ReadGrade();//更新最高分到文件void WriteGrade();//初始化蛇void InitSnake();//隨機生成食物void RandFood();//判斷得分與結束void JudgeFunc(int x, int y);//打印蛇與覆蓋蛇void DrawSnake(int flag);//移動蛇void MoveSnake(int x, int y);//執行按鍵void run(int x, int y);//游戲主體邏輯函數void Game();int max, grade; //全局變量int main(){    #pragma warning (disable:4996) //消除警告max = 0, grade = 0; //初始化變量system("title 貪吃蛇"); //設置cmd窗口的名字system("mode con cols=84 lines=23"); //設置cmd窗口的大小HideCursor(); //隱藏光標ReadGrade(); //從文件讀取最高分到max變量InitInterface(); //初始化界面InitSnake(); //初始化蛇srand((unsigned int)time(NULL)); //設置隨機數生成起點RandFood(); //隨機生成食物DrawSnake(1); //打印蛇Game(); //開始游戲return 0;}//隱藏光標void HideCursor(){    CONSOLE_CURSOR_INFO curInfo; //定義光標信息的結構體變量curInfo.dwSize = 1; //如果沒賦值的話,光標隱藏無效curInfo.bVisible = FALSE; //將光標設置為不可見HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //獲取控制臺句柄SetConsoleCursorInfo(handle, &curInfo); //設置光標信息}//光標跳轉void CursorJump(int x, int y){    COORD pos; //定義光標位置的結構體變量pos.X = x; //橫坐標pos.Y = y; //縱坐標HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //獲取控制臺句柄SetConsoleCursorPosition(handle, pos); //設置光標位置}//初始化界面void InitInterface(){    color(6); //顏色設置為土黃色for (int i = 0; i < ROW; i++){    for (int j = 0; j < COL; j++){    if (j == 0 || j == COL - 1){    face[i][j] = WALL; //標記該位置為墻CursorJump(2 * j, i);printf("■");}else if (i == 0 || i == ROW - 1){    face[i][j] = WALL; //標記該位置為墻printf("■");}else{    face[i][j] = KONG; //標記該位置為空}}}color(7); //顏色設置為白色CursorJump(0, ROW);printf("當前得分:%d", grade);CursorJump(COL, ROW);printf("歷史最高得分:%d", max);}//顏色設置void color(int c){    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //顏色設置//注:SetConsoleTextAttribute是一個API(應用程序編程接口)}//從文件讀取最高分void ReadGrade(){    FILE* pf = fopen("貪吃蛇最高得分記錄.txt", "r"); //以只讀的方式打開文件if (pf == NULL) //打開文件失敗{    pf = fopen("貪吃蛇最高得分記錄.txt", "w"); //以只寫的方式打開文件fwrite(&max, sizeof(int), 1, pf); //將max寫入文件(此時max為0),即將最高得分初始化為0}fseek(pf, 0, SEEK_SET); //使文件指針pf指向文件開頭fread(&max, sizeof(int), 1, pf); //讀取文件當中的最高得分到max當中fclose(pf); //關閉文件pf = NULL; //文件指針及時置空}//更新最高分到文件void WriteGrade(){    FILE* pf = fopen("貪吃蛇最高得分記錄.txt", "w"); //以只寫的方式打開文件if (pf == NULL) //打開文件失敗{    printf("保存最高得分記錄失敗n");exit(0);}fwrite(&grade, sizeof(int), 1, pf); //將本局游戲得分寫入文件當中fclose(pf); //關閉文件pf = NULL; //文件指針及時置空}//初始化蛇void InitSnake(){    snake.len = 2; //蛇的身體長度初始化為2snake.x = COL / 2; //蛇頭位置的橫坐標snake.y = ROW / 2; //蛇頭位置的縱坐標//蛇身坐標的初始化body[0].x = COL / 2 - 1;body[0].y = ROW / 2;body[1].x = COL / 2 - 2;body[1].y = ROW / 2;//將蛇頭和蛇身位置進行標記face[snake.y][snake.x] = HEAD;face[body[0].y][body[0].x] = BODY;face[body[1].y][body[1].x] = BODY;}//隨機生成食物void RandFood(){    int i, j;do{    //隨機生成食物的橫縱坐標i = rand() % ROW;j = rand() % COL;} while (face[i][j] != KONG); //確保生成食物的位置為空,若不為空則重新生成face[i][j] = FOOD; //將食物位置進行標記color(12); //顏色設置為紅色CursorJump(2 * j, i); //光標跳轉到生成的隨機位置處printf("●"); //打印食物}//判斷得分與結束void JudgeFunc(int x, int y){    //若蛇頭即將到達的位置是食物,則得分if (face[snake.y + y][snake.x + x] == FOOD){    snake.len++; //蛇身加長grade += 10; //更新當前得分color(7); //顏色設置為白色CursorJump(0, ROW);printf("當前得分:%d", grade); //重新打印當前得分RandFood(); //重新隨機生成食物}//若蛇頭即將到達的位置是墻或者蛇身,則游戲結束else if (face[snake.y + y][snake.x + x] == WALL || face[snake.y + y][snake.x + x] == BODY){    Sleep(1000); //留給玩家反應時間system("cls"); //清空屏幕color(7); //顏色設置為白色CursorJump(2 * (COL / 3), ROW / 2 - 3);if (grade > max){    printf("恭喜你打破最高記錄,最高記錄更新為%d", grade);WriteGrade();}else if (grade == max){    printf("與最高記錄持平,加油再創佳績", grade);}else{    printf("請繼續加油,當前與最高記錄相差%d", max - grade);}CursorJump(2 * (COL / 3), ROW / 2);printf("GAME OVER");while (1) //詢問玩家是否再來一局{    char ch;CursorJump(2 * (COL / 3), ROW / 2 + 3);printf("再來一局?(y/n):");scanf("%c", &ch);if (ch == 'y' || ch == 'Y'){    system("cls");main();}else if (ch == 'n' || ch == 'N'){    CursorJump(2 * (COL / 3), ROW / 2 + 5);exit(0);}else{    CursorJump(2 * (COL / 3), ROW / 2 + 5);printf("選擇錯誤,請再次選擇");}}}}//打印蛇與覆蓋蛇void DrawSnake(int flag){    if (flag == 1) //打印蛇{    color(10); //顏色設置為綠色CursorJump(2 * snake.x, snake.y);printf("■"); //打印蛇頭for (int i = 0; i < snake.len; i++){    CursorJump(2 * body[i].x, body[i].y);printf("□"); //打印蛇身}}else //覆蓋蛇{    if (body[snake.len - 1].x != 0) //防止len++后將(0, 0)位置的墻覆蓋{    //將蛇尾覆蓋為空格即可CursorJump(2 * body[snake.len - 1].x, body[snake.len - 1].y);printf(" ");}}}//移動蛇void MoveSnake(int x, int y){    DrawSnake(0); //先覆蓋當前所顯示的蛇face[body[snake.len - 1].y][body[snake.len - 1].x] = KONG; //蛇移動后蛇尾重新標記為空face[snake.y][snake.x] = BODY; //蛇移動后蛇頭的位置變為蛇身//蛇移動后各個蛇身位置坐標需要更新for (int i = snake.len - 1; i > 0; i--){    body[i].x = body[i - 1].x;body[i].y = body[i - 1].y;}//蛇移動后蛇頭位置信息變為第0個蛇身的位置信息body[0].x = snake.x;body[0].y = snake.y;//蛇頭的位置更改snake.x = snake.x + x;snake.y = snake.y + y;DrawSnake(1); //打印移動后的蛇}//執行按鍵void run(int x, int y){    int t = 0;while (1){    if (t == 0)t = 3000; //這里t越小,蛇移動速度越快(可以根據次設置游戲難度)while (--t){    if (kbhit() != 0) //若鍵盤被敲擊,則退出循環break;}if (t == 0) //鍵盤未被敲擊{    JudgeFunc(x, y); //判斷到達該位置后,是否得分與游戲結束MoveSnake(x, y); //移動蛇}else //鍵盤被敲擊{    break; //返回Game函數讀取鍵值}}}//游戲主體邏輯函數void Game(){    int n = RIGHT; //開始游戲時,默認向后移動int tmp = 0; //記錄蛇的移動方向goto first; //第一次進入循環先向默認方向前進while (1){    n = getch(); //讀取鍵值//在執行前,需要對所讀取的按鍵進行調整switch (n){    case UP:case DOWN: //如果敲擊的是“上”或“下”if (tmp != LEFT&&tmp != RIGHT) //并且上一次蛇的移動方向不是“左”或“右”{    n = tmp; //那么下一次蛇的移動方向設置為上一次蛇的移動方向}break;case LEFT:case RIGHT: //如果敲擊的是“左”或“右”if (tmp != UP&&tmp != DOWN) //并且上一次蛇的移動方向不是“上”或“下”{    n = tmp; //那么下一次蛇的移動方向設置為上一次蛇的移動方向}case SPACE:case ESC:case 'r':case 'R':break; //這四個無需調整default:n = tmp; //其他鍵無效,默認為上一次蛇移動的方向break;}first: //第一次進入循環先向默認方向前進switch (n){    case UP: //方向鍵:上run(0, -1); //向上移動(橫坐標偏移為0,縱坐標偏移為-1)tmp = UP; //記錄當前蛇的移動方向break;case DOWN: //方向鍵:下run(0, 1); //向下移動(橫坐標偏移為0,縱坐標偏移為1)tmp = DOWN; //記錄當前蛇的移動方向break;case LEFT: //方向鍵:左run(-1, 0); //向左移動(橫坐標偏移為-1,縱坐標偏移為0)tmp = LEFT; //記錄當前蛇的移動方向break;case RIGHT: //方向鍵:右run(1, 0); //向右移動(橫坐標偏移為1,縱坐標偏移為0)tmp = RIGHT; //記錄當前蛇的移動方向break;case SPACE: //暫停system("pause>nul"); //暫停后按任意鍵繼續break;case ESC: //退出system("cls"); //清空屏幕color(7); //顏色設置為白色CursorJump(COL - 8, ROW / 2);printf(" 游戲結束 ");CursorJump(COL - 8, ROW / 2 + 2);exit(0);case 'r':case 'R': //重新開始system("cls"); //清空屏幕main(); //重新執行主函數}}}

          游戲代碼詳解

          游戲框架構建

          首先定義游戲界面的大小,定義游戲區行數和列數。

          #define ROW 22 //游戲區行數#define COL 42 //游戲區列數

          這里將蛇活動的區域稱為游戲區,將分數提示的區域稱為提示區(提示區占一行)。

          此外,我們還需要兩個結構體用于表示蛇頭和蛇身。蛇頭結構體當中存儲著當前蛇身的長度以及蛇頭的位置坐標。

          //蛇頭struct Snake{    int len; //記錄蛇身長度int x; //蛇頭橫坐標int y; //蛇頭縱坐標}snake;

          蛇身結構體當中存儲著該段蛇身的位置坐標。

          //蛇身struct Body{    int x; //蛇身橫坐標int y; //蛇身縱坐標}body[ROW*COL]; //開辟足以存儲蛇身的結構體數組

          同時我們需要一個二維數組來標記游戲區各個位置的狀態(空、墻、食物、蛇頭以及蛇身)。

          int face[ROW][COL]; //標記游戲區各個位置的狀態

          為了增加代碼的可讀性,最好運用宏來定義各個位置的狀態,而不是在代碼中用干巴巴的數字對各個位置的狀態進行切換。

          #define KONG 0 //標記空(什么也沒有)#define WALL 1 //標記墻#define FOOD 2 //標記食物#define HEAD 3 //標記蛇頭#define BODY 4 //標記蛇身

          當然,為了代碼的可讀性,我們最好也將需要用到的按鍵的鍵值用宏進行定義。

          #define UP 72 //方向鍵:上#define DOWN 80 //方向鍵:下#define LEFT 75 //方向鍵:左#define RIGHT 77 //方向鍵:右#define SPACE 32 //暫停#define ESC 27 //退出

          隱藏光標

          隱藏光標比較簡單,定義一個光標信息的結構體變量,然后對光標信息進行賦值,最后用這個光標信息的結構體變量進行光標信息設置即可。

          //隱藏光標void HideCursor(){    CONSOLE_CURSOR_INFO curInfo; //定義光標信息的結構體變量curInfo.dwSize = 1; //如果沒賦值的話,光標隱藏無效curInfo.bVisible = FALSE; //將光標設置為不可見HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //獲取控制臺句柄SetConsoleCursorInfo(handle, &curInfo); //設置光標信息}

          光標跳轉

          光標跳轉,也就是讓光標跳轉到指定位置進行輸出。與隱藏光標的操作步驟類似,先定義一個光標位置的結構體變量,然后設置光標的橫縱坐標,最后用這個光標位置的結構體變量進行光標位置設置即可。

          //光標跳轉void CursorJump(int x, int y){    COORD pos; //定義光標位置的結構體變量pos.X = x; //橫坐標pos.Y = y; //縱坐標HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //獲取控制臺句柄SetConsoleCursorPosition(handle, pos); //設置光標位置}

          初始化界面

          初始化界面完成游戲區“墻”的打印,和提示區的打印即可。

          在打印過程中需要注意兩點:

          1. 在cmd窗口中一個小方塊占兩個單位的橫坐標,一個單位的縱坐標。
          2. 光標跳轉函數CursorJump接收的是光標將要跳至位置的橫縱坐標。

          例如,要用CursorJump函數跳轉至 i 行 j 列(以一個小方塊為一個單位),就等價于讓光標跳轉至坐標(2*j,i)處。

          //初始化界面void InitInterface(){    color(6); //顏色設置為土黃色for (int i = 0; i < ROW; i++){    for (int j = 0; j < COL; j++){    if (j == 0 || j == COL - 1){    face[i][j] = WALL; //標記該位置為墻CursorJump(2 * j, i);printf("■");}else if (i == 0 || i == ROW - 1){    face[i][j] = WALL; //標記該位置為墻printf("■");}else{    face[i][j] = KONG; //標記該位置為空}}}color(7); //顏色設置為白色CursorJump(0, ROW);printf("當前得分:%d", grade);CursorJump(COL, ROW);printf("歷史最高得分:%d", max);}

          注意: 在初始化界面的同時,記得對游戲區相應位置的狀態進行標記。

          顏色設置

          顏色設置函數的作用是,將此后輸出的內容顏色都更為所指定的顏色,接收的參數c是顏色代碼,十進制顏色代碼表如下:

          //顏色設置void color(int c){    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //顏色設置//注:SetConsoleTextAttribute是一個API(應用程序編程接口)}

          設置顏色函數在其頭文件當中的聲明如下:

          初始化蛇

          初始化蛇時將蛇身的長度初始化為2,蛇頭的起始位置在游戲區的中央,蛇頭向右依次是第0個蛇身、第1個蛇身。

          在初始化蛇的信息后,記得對游戲區該位置的狀態進行標記。

          //初始化蛇void InitSnake(){    snake.len = 2; //蛇的身體長度初始化為2snake.x = COL / 2; //蛇頭位置的橫坐標snake.y = ROW / 2; //蛇頭位置的縱坐標//蛇身坐標的初始化body[0].x = COL / 2 - 1;body[0].y = ROW / 2;body[1].x = COL / 2 - 2;body[1].y = ROW / 2;//將蛇頭和蛇身位置進行標記face[snake.y][snake.x] = HEAD;face[body[0].y][body[0].x] = BODY;face[body[1].y][body[1].x] = BODY;}

          隨機生成食物

          隨機在游戲區生成食物,需要對生成后的坐標進行判斷,只有該位置為空才能在此生成食物,否則需要重新生成坐標。食物坐標確定后,需要對游戲區該位置的狀態進行標記。

          //隨機生成食物void RandFood(){    int i, j;do{    //隨機生成食物的橫縱坐標i = rand() % ROW;j = rand() % COL;} while (face[i][j] != KONG); //確保生成食物的位置為空,若不為空則重新生成face[i][j] = FOOD; //將食物位置進行標記color(12); //顏色設置為紅色CursorJump(2 * j, i); //光標跳轉到生成的隨機位置處printf("●"); //打印食物}

          打印蛇與覆蓋蛇

          打印蛇和覆蓋蛇這里直接使用一個函數來實現,若傳入參數flag為1,則打印蛇;若傳入參數為0,則用空格覆蓋蛇。 打印蛇:

          1. 先根據結構體變量snake獲取蛇頭的坐標,到相應位置打印蛇頭。
          2. 然后根據結構體數組body依次獲取蛇身的坐標,到相應位置進行打印即可。

          覆蓋蛇:

          1. 用空格覆蓋最后一段蛇身即可。

          但需要注意在覆蓋前判斷覆蓋的位置是否為(0,0)位置,因為當得分后蛇身長度增加,需要覆蓋當前的蛇(進而打印長度增加后的蛇),而此時新加蛇身還未進行賦值(編譯器一般默認初始化為0),我們根據最后一段蛇身獲取到的坐標便是(0,0),則會用空格對(0,0)位置的墻進行覆蓋,需要看完后面的移動蛇函數的實現后再進行理解。(也可以先將該判斷去掉,觀察蛇吃到食物后(0,0)位置墻的變化再進行分析)

          //打印蛇與覆蓋蛇void DrawSnake(int flag){    if (flag == 1) //打印蛇{    color(10); //顏色設置為綠色CursorJump(2 * snake.x, snake.y);printf("■"); //打印蛇頭for (int i = 0; i < snake.len; i++){    CursorJump(2 * body[i].x, body[i].y);printf("□"); //打印蛇身}}else //覆蓋蛇{    if (body[snake.len - 1].x != 0) //防止len++后將(0, 0)位置的墻覆蓋{    //將蛇尾覆蓋為空格即可CursorJump(2 * body[snake.len - 1].x, body[snake.len - 1].y);printf(" ");}}}

          移動蛇

          移動蛇函數的作用就是先覆蓋當前所顯示的蛇,然后再打印移動后的蛇。

          參數說明:

          • x:蛇移動后的橫坐標相對于當前蛇的橫坐標的變化。
          • y:蛇移動后的縱坐標相對于當前蛇的縱坐標的變化。

          蛇移動后,各種信息需要變化:

          1. 最后一段蛇身在游戲區當中需要被重新標記為空。
          2. 蛇頭位置在游戲區當中需要被重新標記為蛇身。
          3. 存儲蛇身坐標信息的結構體數組body當中,需要將第i段蛇身的坐標信息更新為第i-1段蛇身的坐標信息,而第0段,即第一段蛇身的坐標信息需要更新為當前蛇頭的坐標信息。
          4. 蛇頭的坐標信息需要根據傳入的參數x和y,進行重新計算。
          //移動蛇void MoveSnake(int x, int y){    DrawSnake(0); //先覆蓋當前所顯示的蛇face[body[snake.len - 1].y][body[snake.len - 1].x] = KONG; //蛇移動后蛇尾重新標記為空face[snake.y][snake.x] = BODY; //蛇移動后蛇頭的位置變為蛇身//蛇移動后各個蛇身位置坐標需要更新for (int i = snake.len - 1; i > 0; i--){    body[i].x = body[i - 1].x;body[i].y = body[i - 1].y;}//蛇移動后蛇頭位置信息變為第0個蛇身的位置信息body[0].x = snake.x;body[0].y = snake.y;//蛇頭的位置更改snake.x = snake.x + x;snake.y = snake.y + y;DrawSnake(1); //打印移動后的蛇}

          游戲主體邏輯函數

          主體邏輯:

          1. 首先第一次進入該函數,默認蛇向右移動,進而執行run函數。
          2. 直到鍵盤被敲擊,再從run函數返回到Game函數進行按鍵讀取。
          3. 讀取到鍵值后需要對讀取到的按鍵進行調整(這是必要的)。
          4. 調整后再進行按鍵執行,然后再進行按鍵讀取,如此循環進行。

          按鍵調整機制:

          1. 如果敲擊的是“上”或“下”鍵,并且上一次蛇的移動方向不是“左”或“右”,那么將下一次蛇的移動方向設置為上一次蛇的移動方向,即移動方向不變。
          2. 如果敲擊的是“左”或“右”鍵,并且上一次蛇的移動方向不是“上”或“下”,那么將下一次蛇的移動方向設置為上一次蛇的移動方向,即移動方向不變。
          3. 如果敲擊的按鍵是空格、Esc、r或是R,則不作調整。
          4. 其余按鍵無效,下一次蛇的移動方向設置為上一次蛇的移動方向,即移動方向不變。
          //游戲主體邏輯函數void Game(){    int n = RIGHT; //開始游戲時,默認向后移動int tmp = 0; //記錄蛇的移動方向goto first; //第一次進入循環先向默認方向前進while (1){    n = getch(); //讀取鍵值//在執行前,需要對所讀取的按鍵進行調整switch (n){    case UP:case DOWN: //如果敲擊的是“上”或“下”if (tmp != LEFT&&tmp != RIGHT) //并且上一次蛇的移動方向不是“左”或“右”{    n = tmp; //那么下一次蛇的移動方向設置為上一次蛇的移動方向}break;case LEFT:case RIGHT: //如果敲擊的是“左”或“右”if (tmp != UP&&tmp != DOWN) //并且上一次蛇的移動方向不是“上”或“下”{    n = tmp; //那么下一次蛇的移動方向設置為上一次蛇的移動方向}case SPACE:case ESC:case 'r':case 'R':break; //這四個無需調整default:n = tmp; //其他鍵無效,默認為上一次蛇移動的方向break;}first: //第一次進入循環先向默認方向前進switch (n){    case UP: //方向鍵:上run(0, -1); //向上移動(橫坐標偏移為0,縱坐標偏移為-1)tmp = UP; //記錄當前蛇的移動方向break;case DOWN: //方向鍵:下run(0, 1); //向下移動(橫坐標偏移為0,縱坐標偏移為1)tmp = DOWN; //記錄當前蛇的移動方向break;case LEFT: //方向鍵:左run(-1, 0); //向左移動(橫坐標偏移為-1,縱坐標偏移為0)tmp = LEFT; //記錄當前蛇的移動方向break;case RIGHT: //方向鍵:右run(1, 0); //向右移動(橫坐標偏移為1,縱坐標偏移為0)tmp = RIGHT; //記錄當前蛇的移動方向break;case SPACE: //暫停system("pause>nul"); //暫停后按任意鍵繼續break;case ESC: //退出system("cls"); //清空屏幕color(7); //顏色設置為白色CursorJump(COL - 8, ROW / 2);printf(" 游戲結束 ");CursorJump(COL - 8, ROW / 2 + 2);exit(0);case 'r':case 'R': //重新開始system("cls"); //清空屏幕main(); //重新執行主函數}}}

          執行按鍵

          參數說明:

          • x:蛇移動后的橫坐標相對于當前蛇的橫坐標的變化。
          • y:蛇移動后的縱坐標相對于當前蛇的縱坐標的變化。

          給定一定的時間間隔,若在該時間間隔內鍵盤被敲擊,則退出run函數,返回Game函數進行按鍵讀取。若未被敲擊,則先判斷蛇到達移動后的位置后是否得分或是游戲結束,然后再移動蛇的位置。 若鍵盤一直未被敲擊,則就會一直執行run函數當中的while函數,蛇就會一直朝一個方向移動,直到游戲結束。

          //執行按鍵void run(int x, int y){    int t = 0;while (1){    if (t == 0)t = 3000; //這里t越小,蛇移動速度越快(可以根據次設置游戲難度)while (--t){    if (kbhit() != 0) //若鍵盤被敲擊,則退出循環break;}if (t == 0) //鍵盤未被敲擊{    JudgeFunc(x, y); //判斷到達該位置后,是否得分與游戲結束MoveSnake(x, y); //移動蛇}else //鍵盤被敲擊{    break; //返回Game函數讀取鍵值}}}

          判斷得分與結束

          判斷得分: 若蛇頭即將到達的位置是食物,則得分。得分后需要將蛇身加長,并且更新當前得分,除此之外,還需要重新生成食物。

          判斷結束: 若蛇頭即將到達的位置是墻或者蛇身,則游戲結束。游戲結束后比較本局得分和歷史最高得分,給出相應的提示語句,并且詢問玩家是否再來一局,可自由發揮。

          //判斷得分與結束void JudgeFunc(int x, int y){    //若蛇頭即將到達的位置是食物,則得分if (face[snake.y + y][snake.x + x] == FOOD){    snake.len++; //蛇身加長grade += 10; //更新當前得分color(7); //顏色設置為白色CursorJump(0, ROW);printf("當前得分:%d", grade); //重新打印當前得分RandFood(); //重新隨機生成食物}//若蛇頭即將到達的位置是墻或者蛇身,則游戲結束else if (face[snake.y + y][snake.x + x] == WALL || face[snake.y + y][snake.x + x] == BODY){    Sleep(1000); //留給玩家反應時間system("cls"); //清空屏幕color(7); //顏色設置為白色CursorJump(2 * (COL / 3), ROW / 2 - 3);if (grade > max){    printf("恭喜你打破最高記錄,最高記錄更新為%d", grade);WriteGrade();}else if (grade == max){    printf("與最高記錄持平,加油再創佳績", grade);}else{    printf("請繼續加油,當前與最高記錄相差%d", max - grade);}CursorJump(2 * (COL / 3), ROW / 2);printf("GAME OVER");while (1) //詢問玩家是否再來一局{    char ch;CursorJump(2 * (COL / 3), ROW / 2 + 3);printf("再來一局?(y/n):");scanf("%c", &ch);if (ch == 'y' || ch == 'Y'){    system("cls");main();}else if (ch == 'n' || ch == 'N'){    CursorJump(2 * (COL / 3), ROW / 2 + 5);exit(0);}else{    CursorJump(2 * (COL / 3), ROW / 2 + 5);printf("選擇錯誤,請再次選擇");}}}}

          注意: 若本局得分大于歷史最高得分,需要更新最高分到文件。

          從文件讀取最高分

          首先需要使用fopen函數打開“貪吃蛇最高得分記錄.txt”文件,若是第一次運行該代碼,則會自動創建該文件,并將歷史最高記錄設置為0,之后再讀取文件當中的歷史最高記錄存儲在max變量當中,并關閉文件即可。

          //從文件讀取最高分void ReadGrade(){    FILE* pf = fopen("貪吃蛇最高得分記錄.txt", "r"); //以只讀的方式打開文件if (pf == NULL) //打開文件失敗{    pf = fopen("貪吃蛇最高得分記錄.txt", "w"); //以只寫的方式打開文件fwrite(&max, sizeof(int), 1, pf); //將max寫入文件(此時max為0),即將最高得分初始化為0}fseek(pf, 0, SEEK_SET); //使文件指針pf指向文件開頭fread(&max, sizeof(int), 1, pf); //讀取文件當中的最高得分到max當中fclose(pf); //關閉文件pf = NULL; //文件指針及時置空}

          更新最高分到文件

          首先使用fopen函數打開“貪吃蛇最高得分記錄.txt”,然后將本局游戲的分數grade寫入文件當中即可(覆蓋式)。

          //更新最高分到文件void WriteGrade(){    FILE* pf = fopen("貪吃蛇最高得分記錄.txt", "w"); //以只寫的方式打開文件if (pf == NULL) //打開文件失敗{    printf("保存最高得分記錄失敗n");exit(0);}fwrite(&grade, sizeof(int), 1, pf); //將本局游戲得分寫入文件當中fclose(pf); //關閉文件pf = NULL; //文件指針及時置空}

          主函數

          有了以上函數的支撐,寫出主函數是相當簡單的,但需要注意以下三點:

          1. 全局變量grade需要在主函數內初始化為0,不能在全局范圍初始化為0,因為當玩家按下R鍵進行重玩時我們需要將當前分數grade重新設置為0。
          2. 隨機數的生成起點建議設置在主函數當中。
          3. 主函數當中的#pragma語句是用于消除類似以下警告的:
          int max, grade; //全局變量int main(){    #pragma warning (disable:4996) //消除警告max = 0, grade = 0; //初始化變量system("title 貪吃蛇"); //設置cmd窗口的名字system("mode con cols=84 lines=23"); //設置cmd窗口的大小HideCursor(); //隱藏光標ReadGrade(); //從文件讀取最高分到max變量InitInterface(); //初始化界面InitSnake(); //初始化蛇srand((unsigned int)time(NULL)); //設置隨機數生成起點RandFood(); //隨機生成食物DrawSnake(1); //打印蛇Game(); //開始游戲return 0;}

          141097.html

          標簽:c語言貪吃蛇-

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          大鴨梨在北京有幾家分店???都在哪里?雅麗烤鴨店(上地店)招牌菜:精品烤鴨、剁椒魚頭、饞嘴牛蛙、砂鍋大魚頭。地址:海淀區上地農大南路舒村北圖書優惠券地圖大鴨梨烤鴨店(紫竹橋餐廳)美食:家常菜人均消費:30元優惠:90%招牌菜:精品烤鴨、剁椒魚頭、饞嘴牛蛙、砂鍋大魚頭。地址:海淀區北洼路98號(化工大學內),預約優惠券地圖大鴨梨烤鴨店(西三旗店)美食:家常菜人均消費:30元優惠:90%招牌菜:精品烤鴨...

          QLDownload是什么文件?這是QQ電腦管理器的默認下載文件夾。如果已安裝軟件,則可以刪除qmdownload。刪除步驟如下:1。打開電腦。2. 在“計算機管理”頁上,單擊“搜索”“下載”。3. 單擊“搜索結果”。4. 進入qmdownload管理頁面,選擇文件并右鍵單擊。5. 最后,單擊刪除。qldownload是什么文件夾?這是QQ計算機管理器的默認下載文件夾。您通過QQ計算機管理器下載的...

          QQ怎么刪除聊天記錄?1.可以打開手機,你選一個聯系人,再點右上角聊天記錄設置。2.選擇聊天記錄,再點右上角的刪除掉。3.你選擇刪掉手機或刪出男街霸聊天記錄,然后點擊“判斷”。電腦扣扣如何刪除聊天記錄?徹底刪除電腦中的聊天記錄的具體看操作步驟萬分感謝:我們需要準備的材料有:電腦、。1、是需要我們先打開,直接點擊左下角“主菜單”按鈕。2、之后我們在該頁面中然后點擊打開“系統設置”按鈕。3、然后把我們...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>