再来一次的C语言贪吃蛇小游戏(一)
0. 寫在開頭
學(xué)習(xí)編程也有兩三年時間了,中間也玩(學(xué)校安排學(xué)習(xí))過很多東西 ,從匯編到C到Java和python。用Java和Python也就圖一快,真要體會編程樂趣還得看我C語言(開玩笑 )
為什么要用C語言寫一個貪吃蛇游戲呢,其實這是我大一時候萬姐布置的一個課設(shè),當(dāng)時就是這個課設(shè),逼著我一個星期“學(xué)會了”C語言,但是這段回憶是非常充實有趣的,現(xiàn)在我掌握了新的語言,新的編程思想,回過頭來重新做一遍這個課設(shè),感受編程帶給我的最初的快樂。
貪吃蛇游戲我相信大家都玩過,具體規(guī)則也不用我多說,那么直接開始吧!
1. 如何表示一條蛇
那么如何用C語言表示一條蛇呢?倘若使用Java或者Python這種面向?qū)ο笳Z言,我們肯定會為蛇創(chuàng)建一個對象,再添加相應(yīng)的屬性和方法來表示蛇的特征,在C語言中,可以使用結(jié)構(gòu)體來實現(xiàn)相似的功能。
- 蛇由多節(jié)蛇身組成,包括蛇頭也算是蛇身,每個蛇身都是一個結(jié)構(gòu)體,我采用循環(huán)雙鏈表來表示一條蛇,之所以使用雙向循環(huán)鏈表,是為了每一節(jié)蛇身可以指向它的下一節(jié)蛇身,也可以指向它的上一節(jié)蛇身,同時頭的上一節(jié)是尾巴,尾巴的下一節(jié)是頭,便于我們遍歷操作。類似于:(隨意配圖,無視苯環(huán))
- 每一節(jié)蛇身有自己的坐標(biāo),也有自己運(yùn)動方向,還有兩個分別指向前一節(jié)和后一節(jié)的指針
- 蛇的運(yùn)動方向,我們假設(shè)蛇只能向上下左右四個方向運(yùn)動。
- 蛇的運(yùn)動速度,我們假設(shè)蛇可以慢速,正常速,快速三種速度 爪巴
- 蛇的長度,我們記錄在蛇的結(jié)構(gòu)體內(nèi)
2. 具體實現(xiàn)
snake.h頭文件中部分內(nèi)容:
typedef enum direction {up,right,down,left }Direction;typedef enum speed {slow,normal,fast, }Speed;//環(huán)狀雙向鏈表 typedef struct snake_body_node {int pos_x;int pos_y;Direction dir;struct snake_body_node *previous_node;struct snake_body_node *next_node; }Snake_Body_Node;typedef struct snake {int length;Speed speed;Snake_Body_Node *head; }Snake;3. 蛇的行為
定義了蛇的表示,那么蛇有哪些行為需要我們實現(xiàn)呢?
毫無疑問,在游戲中,我們要在地圖上生成一條蛇,那么一個生成蛇的方法肯定少不了,于是有了
Snake *new_born_snake(int pos_x, int pos_y);參數(shù)pos_x,pox_y分別表示最初蛇的位置,這里我將蛇最初的長度設(shè)為1,相當(dāng)于就一腦袋
蛇肯定要移動,蛇在移動的時候,直觀上蛇身的全部節(jié)點都要移動,但實際則不然,只有兩節(jié)蛇身是需要變化的,一節(jié)是腦袋,一節(jié)是蛇尾,其余的蛇身移動的位置其實都是其上一個蛇身移動前的位置,那么我們可以不管這些節(jié)點,我們需要做的就是新建一個蛇頭,去掉蛇尾。
void add_head_node(Snake* snake, int pos_x, int pos_y); void remove_tail_node(Snake* snake); void move(Snake* snake, Direction dir, int pos_x, int pos_y); void eat(Snake* snake, Direction dir, int pos_x, int pos_y);蛇吃到食物需要生長,我們就假設(shè)食物的位置變?yōu)橐还?jié)蛇身(蛇頭),尾巴不去掉,那么用上面add_head_node方法同樣可以實現(xiàn)。
4. 具體實現(xiàn)
snake.c
#include "snake.h"struct snake * new_born_snake(int pos_x, int pos_y) {Snake* new_snake = (Snake*)malloc(sizeof(Snake));Snake_Body_Node *head = mknode();new_snake->length = 1;new_snake->speed = normal;head->dir = up;head->pos_x = pos_x;head->pos_y = pos_y;new_snake->head = head;head->next_node = head;head->previous_node = head;return new_snake; }void add_head_node(Snake* snake, int pos_x, int pos_y) {Snake_Body_Node *head = snake->head;Snake_Body_Node *body = mknode();body->pos_x = pos_x;body->pos_y = pos_y;body->dir = head->dir;body->previous_node = head->previous_node;head->previous_node->next_node = body;head->previous_node = body;body->next_node = head;snake->head = body;snake->length++; }void remove_tail_node(Snake* snake) {Snake_Body_Node *head = snake->head;Snake_Body_Node *tail = head->previous_node;head->previous_node = tail->previous_node;tail->previous_node->next_node = head;free(tail);snake->length--; }void destroy_snake(Snake* snake) {Snake_Body_Node* head = snake->head;while (head != head->next_node) {free(head);head = head->next_node;}free(head);free(snake); }Snake_Body_Node* mknode() {Snake_Body_Node* node = (Snake_Body_Node*)malloc(sizeof(Snake_Body_Node));if (node == NULL){printf("out of memory");exit(1);}return node; }void move(Snake* snake, Direction dir, int pos_x, int pos_y) {Sleep(700 - snake->speed * 300);snake->head->dir = dir;add_head_node(snake, pos_x , pos_y);remove_tail_node(snake); }void eat(Snake* snake, Direction dir, int pos_x, int pos_y) {Sleep(700 - snake->speed * 300);snake->head->dir = dir;add_head_node(snake, pos_x, pos_y); }5. 在游戲中控制蛇,下篇揭曉。。。。。
一下篇鏈接
總結(jié)
以上是生活随笔為你收集整理的再来一次的C语言贪吃蛇小游戏(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASCII 编码对照表
- 下一篇: 再来一次的C语言贪吃蛇小游戏(二)