再来一次的C语言贪吃蛇小游戏(二)
生活随笔
收集整理的這篇文章主要介紹了
再来一次的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 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语言贪吃蛇小游戏(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 再来一次的C语言贪吃蛇小游戏(一)
- 下一篇: 再来一次的C语言贪吃蛇小游戏(三)