日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

再来一次的C语言贪吃蛇小游戏(二)

發布時間:2025/6/17 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 再来一次的C语言贪吃蛇小游戏(二) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

5.游戲地圖

貪吃蛇的游戲地圖由一個個方格組成,每一格方格可以表示地面,墻,食物,蛇的身體等等,蛇只能在地面上行動,吃到食物則生長一節蛇身,撞到墻就GG。

我們可以同樣可以使用枚舉來表示地圖上的不同物體

//game.h typedef enum stuff_mark {wall_mark,ground_mark,food_mark,snake_mark }Stuff_Mark;

為了便于表示我們創建一個物品結構體,用來保存地圖上每個物理的位置,和物體的類別

//game.h typedef struct stuff {int pos_x;int pos_y;Stuff_Mark mark; }Stuff;

這樣一來整個游戲的表示框架就定好了。

//game.h //游戲當前狀態 typedef enum state {in_menu,gaming,to_quit }State;//WIDTH, HEIGHT為宏定義的地圖寬高,根據喜好設置 struct game {int score;Stuff map[HEIGHT][WIDTH];Stuff *food;State state; };

為什么要單獨保存食物在游戲結構體中呢?map中不是保存了地圖上所有相關信息嗎?不急,預計下下一篇揭曉哈。

關于游戲中的操作,暫時我們定義操作行為可以有:

  • 上移:move_up,對應w鍵
  • 下移:move_down,對應s鍵
  • 左移:move_left,對應a鍵
  • 右移:move_right,對應d鍵
  • 退出:esc,對應Esc鍵
  • 無操作:no_option

為了對操作進行規范,我們也定義為枚舉類型

//game.h typedef enum option {move_up = 'w',move_left = 'a',move_down = 's',move_right = 'd',esc = 27,no_option = 0 }Option;

6. 初始化游戲,在win32控制臺顯示出來

關于游戲中要展示的物體,我們都已經定義好了,那么怎么樣展示出來呢?

//game.h void start_game(); void init_map(struct game* Game); void display_map(struct game* Game); void display_snake(struct game *Game, Snake *snake); void display_mark(Stuff *stuff); void grow_food(struct game*Game); void snake_move(struct game*Game, Snake* snake, Direction dir); void judge_move_input(struct game*Game, Snake* snake, int* input, int* last_input);

首先解釋一下這個display_mark這個方法,這個方法的唯一功能就是在一個物體所在的地方,輸出表示該物體的符號,通過調用此方法,我們可以展示游戲中的所有內容,set_cursor_positon,set_console_color分別實我自定義的控制臺函數,用來設置控制臺輸出位置和顏色。相關代碼在本系列(三)所提供的源碼中。

//game.c void display_mark(Stuff *stuff) {set_cursor_position(stuff->pos_x, stuff->pos_y);switch (stuff->mark){case wall_mark:set_console_color(6, 0);printf("##");break;case ground_mark:set_console_color(7, 0);printf(" ");break;case food_mark:set_console_color(4, 0);printf("@");break;case snake_mark:set_console_color(2, 0);printf("■");break;default:break;} }

游戲初始化操作

//game.h void init_map(struct game* Game) {for (int i = 0; i < WIDTH; i++) {for (int j = 0; j < HEIGHT; j++){Game->map[j][i].pos_x = i;Game->map[j][i].pos_y = j;if (j == 0 || j == HEIGHT-1 || i==0 || i==WIDTH-1){Game->map[j][i].mark = wall;}else Game->map[j][i].mark = ground;}} }void grow_food(struct game* Game) {int pos_x = rand() % WIDTH;int pos_y = rand() % HEIGHT;Stuff *stuff = &Game->map[pos_y][pos_x];stuff->mark = food_mark;Game->food = stuff;display_mark(stuff); }void display_snake(struct game*Game, Snake *snake) {Snake_Body_Node *head = snake->head;Stuff *stuff;while (head->next_node != head){stuff = &Game->map[head->pos_y][head->pos_x];stuff->mark = snake_mark;display_mark(stuff);}stuff = &Game->map[head->pos_y][head->pos_x];stuff->mark = snake_mark;display_mark(stuff); }

當蛇移動的時候,我們在操作蛇的鏈表時并沒有改變全部的節點,同時我們在顯示蛇的時候,也沒有必要更新所有蛇身的顯示,我們只需要更新頭尾的顯示即可

void snake_move(struct game*Game, Snake* snake, Direction dir) {Stuff *stuff;int pos_x = snake->head->pos_x;int pos_y = snake->head->pos_y;pos_x = dir == left ? pos_x - 1 : dir == right ? pos_x + 1 : pos_x;pos_y = dir == up ? pos_y - 1 : dir == down ? pos_y + 1 : pos_y;switch (Game->map[pos_y][pos_x].mark){case ground_mark:stuff = &Game->map[pos_y][pos_x];stuff->mark = snake_mark;display_mark(stuff);stuff = &Game->map[snake->head->previous_node->pos_y][snake->head->previous_node->pos_x];stuff->mark = ground_mark;display_mark(stuff);move(snake, dir, pos_x, pos_y);break;case food_mark:stuff = &Game->map[pos_y][pos_x];stuff->mark = snake_mark;display_mark(stuff);eat(snake, dir, pos_x, pos_y);grow_food(Game);Game->score++;case snake_mark:exit(1);break;case wall_mark:exit(1);break;default:break;} }

最初效果如下:■■■■表示蛇,@表示食物

7. 游戲控制

關于操作的定義,我們已經在上文中說明了,但是在具體控制中,還有部分細節問題要處理

  • 連續按同一個方向鍵,蛇加速
  • 蛇不能立刻反向移動,比如蛇正在向左運動,即使你先按按下右移鍵,蛇也不會立刻右轉
  • 加速中的蛇方面變化后則回復正常移速
  • void judge_move_input(struct game*Game, Snake* snake, int* input, int* last_input) {if (*last_input + *input == move_down + move_up ||*last_input + *input == move_left + move_right){snake_move(Game, snake, snake->head->dir);return;}else if (*last_input == *input){snake->speed = fast;}else{snake->speed = normal;*last_input = *input;}Direction dir = *input == move_up ? up : *input == move_down ?down : *input == move_left ? left : right;snake_move(Game, snake, dir); }

    總的游戲循環如下

    void start_game() {struct game *Game = (struct game*)malloc(sizeof(struct game));Snake *snake = new_born_snake(5, 5);Game->score = 0;Game->state = gaming;init_map(Game);display_map(Game);display_snake(Game, snake);grow_food(Game);int input = no_option;int last_input = no_option;while (Game->state == gaming){if (_kbhit()){input = _getch();FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));}else input = no_option;switch (input){case move_up:case move_right:case move_down:case move_left:judge_move_input(Game, snake, &input, &last_input);break;case esc:Game->state = back_to_menu;break;case no_option:default:snake_move(Game, snake, snake->head->dir);break;}}free(Game); }

    8.游戲菜單實現

    下一篇鏈接

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的再来一次的C语言贪吃蛇小游戏(二)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。