<center id="qkqgy"><optgroup id="qkqgy"></optgroup></center>
  • <menu id="qkqgy"></menu>
    <nav id="qkqgy"></nav>
    <xmp id="qkqgy"><nav id="qkqgy"></nav>
  • <xmp id="qkqgy"><menu id="qkqgy"></menu>
    <menu id="qkqgy"><menu id="qkqgy"></menu></menu>
    <tt id="qkqgy"><tt id="qkqgy"></tt></tt>

  • 環境:windows系統,VS2019編譯器

    項目分析

    貪吃蛇游戲機制是通過控制蛇上下左右移動并吃到食物得分

    障礙物隨機生成,蛇頭碰到墻壁、障礙物或者碰到蛇身就游戲結束

    食物隨機生成,蛇吃到食物之后蛇身變長,蛇速加快

    代碼運行后可自定義障礙物數量、蛇初始速度、蛇身初識長度

    主函數界面有開始游戲、游戲設置、退出游戲三個選項,通過鍵盤上下鍵控制選擇

    讀寫文件記錄并顯示當前得分和歷史最高分

    項目效果

    snake.h頭文件

    頭文件包含、宏定義、外部變量聲明、函數聲明
    #pragma once #pragma warning (disable:4996) //消除警告 #include <stdio.h> #include
    <stdlib.h> #include <Windows.h> #include <string.h> #include <time.h> #include
    <conio.h> #define ROW 22 #define COL 42 #define EMPTY 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 #define ENTER 13 #define
    RATE 3000 //速度 typedef struct Body { int x, y; }Body; typedef struct Snake {
    int len; int x, y; Body* body; }Snake; extern int g_map[ROW][COL]; extern int
    g_max, g_grade; ? ? ? ? //歷史最高分,當前得分 extern Snake snake;? ? extern int g_len; ?
    ? //蛇初識長度 extern int g_wall, g_food, g_snake; //顏色 extern int g_obstacle; ? ?
    //障礙物數量 extern int g_rate; ? ? //速度 void CursorJump(int x, int y); //光標跳轉 void
    Color(int x); ? ? ? ? //顏色設置 void ReadGrade(); ? ? ? ? ? ? //從文件讀取最高分 void
    WriteGrade(); ? ? ? ? ? ? //更新最高分到文件 void InitMap(); ? ? ? ? ? ? //初始化地圖 void
    InitSnake(); ? ? ? ? ? ? //初始化蛇 void RandFood(); ? ? ? ? ? ? ? //隨機生成食物 void
    RandObstacle(); ? ? ? ? ? ? //隨機生成障礙物 void DrawSnake(int flag); ? ? ? ? //打印蛇
    void MoveSnack(int x, int y); //移動蛇 void JudgeGame(int x, int y); //判斷得分與結束
    void Run(int x, int y); //執行按鍵 void Game(); ? ? ? ? ? ? //游戲流程 void MainGame();
    ? ? ? ? ? ? //主函數游戲流程 void Main(); ? ? ? ? ? ? //主函數直接調用,代替主函數執行代碼,方便回調

    snake.c源文件

    文件讀寫

    讀檔和存檔游戲的最高分記錄
    #include "snake.h" void CursorJump(int x, int y) { COORD pos; //定義光標位置的結構體變量
    pos.X = x; pos.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),
    pos); //設置光標位置 } void Color(int x) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x); //設置顏色 // 6——土黃色
    7——白色 10——綠色 12——紅色 } void ReadGrade() { FILE* pf = fopen("snack.txt", "rb");
    if (pf == NULL) ? ? { pf = fopen("snack.txt", "wb"); fwrite(&g_max,
    sizeof(int), 1, pf); } fseek(pf, 0, SEEK_SET); //使文件指針pf指向文件開頭 fread(&g_max,
    sizeof(int), 1, pf); fclose(pf); pf = NULL; } void WriteGrade() { FILE* pf =
    fopen("snack.txt", "wb"); if (pf == NULL) ? ? { perror("writeGrade::fopen");
    exit(1); } fwrite(&g_grade, sizeof(int), 1, pf); fclose(pf); pf = NULL; }

    初始化

    初始化地圖、蛇
    void InitMap() { Color(g_wall); int i, j; for (i = 0; i < ROW; ++i) ? ? { for
    (j = 0; j < COL; ++j) ? ? ? ? { if (j == 0 || j == COL - 1) ? ? ? ? ? ? {
    g_map[i][j] = WALL; CursorJump(2 * j, i); printf("■"); } else if (i == 0 || i
    == ROW - 1) ? ? ? ? ? ? { CursorJump(2 * j, i); g_map[i][j] = WALL;
    printf("■"); } else ? ? ? ? ? ? { g_map[i][j] = EMPTY; CursorJump(2 * j, i);
    printf(" "); } } } Color(7); CursorJump(0, ROW); printf("當前得分: %d", g_grade);
    CursorJump(2 * COL - 18, ROW); printf("歷史最高分: %d\0", g_max); } void InitSnake()
    { snake.len = g_len; //蛇身初識長度 snake.x = COL / 2; snake.y = ROW / 2; //蛇頭u坐標
    g_map[snake.y][snake.x] = HEAD; snake.body = (Body*)malloc(sizeof(Body) * ROW *
    COL); if (snake.body == NULL) ? ? { perror("InitSnack::malloc"); exit(1); }
    memset(snake.body, 0, sizeof(Body) * ROW * COL); int i = 0; while (i < g_len) ?
    ? { snake.body[i].x = snake.x - (i + 1); snake.body[i].y = snake.y;
    g_map[snake.body[i].y][snake.body[i].x] = BODY; ++i; } //初始化蛇身 g_rate = RATE;
    //初始化速度 }

    隨機生成

    隨機生成食物和障礙物,障礙物只是游戲開始時隨機生成一次
    void RandFood() { int row, col; do ? ? { row = rand() % ROW; col = rand() %
    COL; } while (g_map[row][col] != EMPTY); g_map[row][col] = FOOD; Color(g_food);
    CursorJump(2 * col, row); printf("●"); } void RandObstacle() { Color(8); //灰色
    int obstacle = g_obstacle; int row, col; while (obstacle) ? ? { do ? ? ? ? {
    row = rand() % ROW; col = rand() % COL; } while (g_map[row][col] != EMPTY);
    g_map[row][col] = WALL; CursorJump(2 * col, row); printf("■"); --obstacle; } }

    打印蛇與移動蛇

    打印蛇分為覆蓋和打印,覆蓋是指將蛇尾用空格覆蓋

    蛇每移動一次都是要經過一次覆蓋一次打印,先將蛇尾覆蓋為空格,再將蛇前移之后打印出來

    覆蓋蛇的時候注意,蛇吃到食物之后身體變長,此時蛇尾不覆蓋
    void DrawSnake(int flag) { if (flag == 1) ? ? { //打印蛇 Color(g_snake);
    CursorJump(2 * snake.x, snake.y); printf("■"); //打印蛇頭 int i = 0; while (i <
    snake.len) ? ? ? ? { CursorJump(2 * snake.body[i].x, snake.body[i].y);
    printf("□"); ++i; } //打印蛇身 } else ? ? { //覆蓋蛇 if (snake.body[snake.len - 1].x
    != 0) ? ? ? ? { CursorJump(2 * snake.body[snake.len - 1].x,
    snake.body[snake.len - 1].y); printf(" "); //將蛇尾覆蓋為空格 } } } void MoveSnack(int
    x, int y) { DrawSnake(0); //覆蓋蛇 int tail = snake.len - 1;
    g_map[snake.body[tail].y][snake.body[tail].x] = EMPTY; //將蛇尾標記為空
    g_map[snake.y][snake.x] = BODY; //蛇移動后蛇頭變為蛇身 while (tail) ? ? {
    snake.body[tail].x = snake.body[tail - 1].x; snake.body[tail].y =
    snake.body[tail - 1].y; --tail; } snake.body[0].x = snake.x; snake.body[0].y =
    snake.y; snake.x += x; snake.y += y; //蛇頭位置更新 DrawSnake(1); //打印蛇 }

    判斷得分或游戲結束

    若蛇頭的下一步是食物,則得分,蛇身變長,蛇速變快

    若蛇頭的下一步是墻或者障礙物或者蛇身,則游戲結束,根據得分判斷是否打破紀錄

    游戲結束之后詢問玩家是否繼續游戲
    void JudgeGame(int x, int y) { if (g_map[snake.y + y][snake.x + x] == FOOD) ?
    ? { //蛇頭下一步位置是食物 //得分,蛇身變長,蛇速變快 ++snake.len; g_grade += 10; if (g_rate > 1000)
    g_rate -= 50; Color(7); CursorJump(0, ROW); printf("當前得分: %d", g_grade);
    //重新打印得分 RandFood(); //重新生成食物 } else if (g_map[snake.y + y][snake.x + x] ==
    WALL || g_map[snake.y + y][snake.x + x] == BODY) ? ? { Sleep(1000);
    //暫停1秒,給玩家反應時間 system("cls"); Color(7); CursorJump(2 * COL / 3, ROW / 2 - 3);
    if (g_grade > g_max) ? ? ? ? { printf("恭喜你創下新紀錄: %d", g_grade); WriteGrade(); }
    else ? ? ? ? { printf("請繼續加油,本次得分為: %d", g_grade); } CursorJump(2 * COL / 3,
    ROW / 2); printf("GAME OVER"); while (1) ? ? ? ? { //詢問玩家是否再來一局 char input;
    CursorJump(2 * COL / 3, ROW / 2 + 3); printf(" "); CursorJump(2 * COL / 3, ROW
    / 2 + 3); printf("再次挑戰?(y/n) "); scanf("%c", &input); switch (input) ? ? ? ? ?
    ? { case 'y': case 'Y': system("cls"); MainGame(); break; case 'n': case 'N':
    Main(); break; default: break; } } } }

    按鍵執行

    按鍵執行調用 conio.h 里面的kbhit() 函數,通過循環控制,若無按鍵則蛇自動走下一步

    kbhit() 函數可能會引發編譯器的報錯,用#pragma warning (disable:4996) //消除警告

    鍵盤敲擊,則執行鍵盤敲擊的操作,若無鍵盤敲擊則蛇按照方向往前走
    void Run(int x, int y) { int t = 0; while (1) { if (t == 0) t = g_rate; while
    (--t) ? ? ? ? { //鍵盤被敲擊,退出循環 if (kbhit() != 0) break; } if (t == 0) ? ? ? ? {
    //鍵盤未敲擊,判斷得分與移動蛇 JudgeGame(x, y); MoveSnack(x, y); } else ? ? ? ? { break;
    //鍵盤被敲擊,返回Game()函數 } } }

    游戲操作

    wsad、上下左右箭頭:控制蛇移動的上下左右方向

    space空格鍵:游戲暫停

    r、R:重新開始

    ESC:退出游戲

    每一個鍵位的鍵值對在頭文件進行宏定義
    void Game() { int dir = RIGHT; //默認初識方向向右 int tmp = dir; //記錄蛇移動的方向 while (1)
    ? ? { switch (dir) ? ? ? ? { case 'w': case 'W': case UP: Run(0, -1);
    //向上移動,x不變,y-1 tmp = UP; break; case 's': case 'S': case DOWN: Run(0, 1); tmp =
    DOWN; break; case 'a': case 'A': case LEFT: Run(-1, 0); tmp = LEFT; break; case
    'd': case 'D': case RIGHT: Run(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"); MainGame(); } dir =
    getch(); switch (dir) ? ? ? ? { case 'w': case 'W': case UP: case 's': case
    'S': case DOWN: if (tmp == UP || tmp == DOWN) dir = tmp; break; case 'a': case
    'A': case LEFT: case 'd': case 'D': case RIGHT: if (tmp == LEFT || tmp ==
    RIGHT) dir = tmp; break; case SPACE: case ESC: case 'r': case 'R': break;
    //這是個按鍵無需調整 default: dir = tmp; } } }

    游戲流程

    *
    讀取歷史最高分

    *
    初始化地圖、蛇

    *
    隨機生成食物、障礙物

    *
    打印蛇

    *
    游戲操作
    void MainGame() { ReadGrade(); //讀取歷史最高分 InitMap(); InitSnake(); RandFood();
    RandObstacle(); DrawSnake(1); Game(); }

    自定義游戲屬性

    自定義障礙物數量、蛇速、蛇身長度

    盡量保證合理性
    void GameSetting() { system("cls"); CursorJump(2 * COL / 3, ROW / 2 - 5);
    printf("設置障礙物數量 ( <=50 ): "); scanf("%d", &g_obstacle); while (g_obstacle > 50)
    ? ? { CursorJump(2 * COL / 3, ROW / 2 + 2); printf(" "); CursorJump(2 * COL /
    3, ROW / 2 - 3); printf("障礙物過多,請重新設置: "); scanf("%d", &g_obstacle); }
    CursorJump(2 * COL / 3, ROW / 2); printf("設置速度( >=1000 ): "); scanf("%d",
    &g_rate); while (g_rate < 1000) ? ? { CursorJump(2 * COL / 3, ROW / 2 + 2);
    printf(" "); CursorJump(2 * COL / 3, ROW / 2 + 2); printf("速度過快,請重新設置: ");
    scanf("%d", &g_rate); } CursorJump(2 * COL / 3, ROW / 2 + 5); printf("設置蛇身初始長度(
    >= 1): "); scanf("%d", &g_len); while (g_len < 1) ? ? { CursorJump(2 * COL / 3,
    ROW / 2 + 2); printf(" "); CursorJump(2 * COL / 3, ROW / 2 + 7);
    printf("蛇身太短,請重新設置: "); scanf("%d", &g_rate); } Main(); //回到主程序函數 }

    初始界面設計
    void PrintFrame(int col, int row) { system("cls"); CursorJump(col, ROW / 2 -
    5); printf("開始游戲"); CursorJump(col, ROW / 2); printf("游戲設置"); CursorJump(col,
    ROW / 2 + 5); printf("退出游戲"); CursorJump(col - 2, row - 1);
    printf("*----------*"); CursorJump(col - 2, row); printf("| "); CursorJump(col
    + 8, row); printf(" |"); CursorJump(col - 2, row + 1); printf("*----------*");
    CursorJump(2 * COL - 14, ROW - 1); printf(" ↑↓ 選擇"); CursorJump(2 * COL - 14,
    ROW); printf("Enter 確認"); } void Main() { srand((unsigned int)time(NULL));
    system("title 貪吃蛇"); system("mode con cols=84 lines=23"); //設置終端窗口大小
    CONSOLE_CURSOR_INFO curInfo; //光標信息結構體變量 curInfo.dwSize = 1; curInfo.bVisible =
    FALSE; //光標光標隱藏不可見 SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),
    &curInfo); //設置光標信息 Color(7); int col = 2 * COL / 3 + 5, row = ROW / 2 - 5;
    PrintFrame(col, row); char input; while (1) ? ? { while (1) ? ? ? ? { if
    (kbhit() != 0) break; } input = getch(); switch (input) { case UP: if (row ==
    ROW / 2 - 5) row = ROW / 2 + 5; else row -= 5; PrintFrame(col, row); break;
    case DOWN: if (row == ROW / 2 + 5) row = ROW / 2 - 5; else row += 5;
    PrintFrame(col, row); break; case ENTER: if (row == ROW / 2 - 5) ? ? ? ? ? ? {
    MainGame(); } else if (row == ROW / 2) ? ? ? ? ? ? { GameSetting(); } else ? ?
    ? ? ? ? { system("cls"); CursorJump(2 * COL / 3 + 5, ROW / 2); printf("退出游戲");
    CursorJump(0, ROW); exit(0); } break; default: break; } } }

    main.c源文件
    #include "snake.h" int g_map[ROW][COL]; int g_max = 0, g_grade = 0; Snake
    snake; int g_len = 2; //蛇初識長度默認為2 int g_wall = 6, g_food = 12, g_snake = 10;
    //默認顏色設置 int g_obstacle = 5; //默認障礙物數量 int g_rate = RATE;
    //默認初始速度為3000,rate值越小速度越快,rate >= 2000 int main() { Main(); return 0; }

    技術
    下載桌面版
    GitHub
    百度網盤(提取碼:draw)
    Gitee
    云服務器優惠
    阿里云優惠券
    騰訊云優惠券
    華為云優惠券
    站點信息
    問題反饋
    郵箱:ixiaoyang8@qq.com
    QQ群:766591547
    關注微信
    巨胸美乳无码人妻视频