日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2025/6/17 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 再来一次的C语言贪吃蛇小游戏(二) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

5.游戲地圖

貪吃蛇的游戲地圖由一個(gè)個(gè)方格組成,每一格方格可以表示地面,墻,食物,蛇的身體等等,蛇只能在地面上行動(dòng),吃到食物則生長(zhǎng)一節(jié)蛇身,撞到墻就GG。

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

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

為了便于表示我們創(chuàng)建一個(gè)物品結(jié)構(gòu)體,用來(lái)保存地圖上每個(gè)物理的位置,和物體的類別

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

這樣一來(lái)整個(gè)游戲的表示框架就定好了。

//game.h //游戲當(dāng)前狀態(tài) typedef enum state {in_menu,gaming,to_quit }State;//WIDTH, HEIGHT為宏定義的地圖寬高,根據(jù)喜好設(shè)置 struct game {int score;Stuff map[HEIGHT][WIDTH];Stuff *food;State state; };

為什么要單獨(dú)保存食物在游戲結(jié)構(gòu)體中呢?map中不是保存了地圖上所有相關(guān)信息嗎?不急,預(yù)計(jì)下下一篇揭曉哈。

關(guān)于游戲中的操作,暫時(shí)我們定義操作行為可以有:

  • 上移:move_up,對(duì)應(yīng)w鍵
  • 下移:move_down,對(duì)應(yīng)s鍵
  • 左移:move_left,對(duì)應(yīng)a鍵
  • 右移:move_right,對(duì)應(yīng)d鍵
  • 退出:esc,對(duì)應(yīng)Esc鍵
  • 無(wú)操作:no_option

為了對(duì)操作進(jìn)行規(guī)范,我們也定義為枚舉類型

//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控制臺(tái)顯示出來(lái)

關(guān)于游戲中要展示的物體,我們都已經(jīng)定義好了,那么怎么樣展示出來(lái)呢?

//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);

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

//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); }

當(dāng)蛇移動(dòng)的時(shí)候,我們?cè)诓僮魃叩逆湵頃r(shí)并沒(méi)有改變?nèi)康墓?jié)點(diǎn),同時(shí)我們?cè)陲@示蛇的時(shí)候,也沒(méi)有必要更新所有蛇身的顯示,我們只需要更新頭尾的顯示即可

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. 游戲控制

關(guān)于操作的定義,我們已經(jīng)在上文中說(shuō)明了,但是在具體控制中,還有部分細(xì)節(jié)問(wèn)題要處理

  • 連續(xù)按同一個(gè)方向鍵,蛇加速
  • 蛇不能立刻反向移動(dòng),比如蛇正在向左運(yùn)動(dòng),即使你先按按下右移鍵,蛇也不會(huì)立刻右轉(zhuǎn)
  • 加速中的蛇方面變化后則回復(fù)正常移速
  • 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); }

    總的游戲循環(huán)如下

    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.游戲菜單實(shí)現(xiàn)

    下一篇鏈接

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

    總結(jié)

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

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。