游戲界面當中沒有打印相關的按鍵說明,這里先逐一列出,貪吃蛇游戲按鍵說明:
除此之外,本游戲還擁有計分系統,可保存玩家的歷史最高記錄。
貪吃蛇游戲當中蛇的移動速度可以進行調整,動圖當中把速度調得較慢(速度太快導致動圖上蛇身顯示不全),下面給出的代碼當中將蛇的速度調整到了合適的位置,大家可以試試。
博友們可以將以下代碼復制到自己的編譯器當中運行:
#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); //設置光標位置}
初始化界面完成游戲區“墻”的打印,和提示區的打印即可。
在打印過程中需要注意兩點:
例如,要用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,則用空格覆蓋蛇。 打印蛇:
覆蓋蛇:
但需要注意在覆蓋前判斷覆蓋的位置是否為(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(" ");}}}
移動蛇函數的作用就是先覆蓋當前所顯示的蛇,然后再打印移動后的蛇。
參數說明:
蛇移動后,各種信息需要變化:
//移動蛇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 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(); //重新執行主函數}}}
參數說明:
給定一定的時間間隔,若在該時間間隔內鍵盤被敲擊,則退出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; //文件指針及時置空}
有了以上函數的支撐,寫出主函數是相當簡單的,但需要注意以下三點:
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
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
大鴨梨在北京有幾家分店???都在哪里?雅麗烤鴨店(上地店)招牌菜:精品烤鴨、剁椒魚頭、饞嘴牛蛙、砂鍋大魚頭。地址:海淀區上地農大南路舒村北圖書優惠券地圖大鴨梨烤鴨店(紫竹橋餐廳)美食:家常菜人均消費:30元優惠:90%招牌菜:精品烤鴨、剁椒魚頭、饞嘴牛蛙、砂鍋大魚頭。地址:海淀區北洼路98號(化工大學內),預約優惠券地圖大鴨梨烤鴨店(西三旗店)美食:家常菜人均消費:30元優惠:90%招牌菜:精品烤鴨...
QLDownload是什么文件?這是QQ電腦管理器的默認下載文件夾。如果已安裝軟件,則可以刪除qmdownload。刪除步驟如下:1。打開電腦。2. 在“計算機管理”頁上,單擊“搜索”“下載”。3. 單擊“搜索結果”。4. 進入qmdownload管理頁面,選擇文件并右鍵單擊。5. 最后,單擊刪除。qldownload是什么文件夾?這是QQ計算機管理器的默認下載文件夾。您通過QQ計算機管理器下載的...
QQ怎么刪除聊天記錄?1.可以打開手機,你選一個聯系人,再點右上角聊天記錄設置。2.選擇聊天記錄,再點右上角的刪除掉。3.你選擇刪掉手機或刪出男街霸聊天記錄,然后點擊“判斷”。電腦扣扣如何刪除聊天記錄?徹底刪除電腦中的聊天記錄的具體看操作步驟萬分感謝:我們需要準備的材料有:電腦、。1、是需要我們先打開,直接點擊左下角“主菜單”按鈕。2、之后我們在該頁面中然后點擊打開“系統設置”按鈕。3、然后把我們...