再来一次的C语言贪吃蛇小游戏(一)
0. 写在开头
学习编程也有两三年时间了,中间也玩(学校安排学习)过很多东西 ,从汇编到C到Java和python。用Java和Python也就图一快,真要体会编程乐趣还得看我C语言(开玩笑 )
为什么要用C语言写一个贪吃蛇游戏呢,其实这是我大一时候万姐布置的一个课设,当时就是这个课设,逼着我一个星期“学会了”C语言,但是这段回忆是非常充实有趣的,现在我掌握了新的语言,新的编程思想,回过头来重新做一遍这个课设,感受编程带给我的最初的快乐。
贪吃蛇游戏我相信大家都玩过,具体规则也不用我多说,那么直接开始吧!
1. 如何表示一条蛇
那么如何用C语言表示一条蛇呢?倘若使用Java或者Python这种面向对象语言,我们肯定会为蛇创建一个对象,再添加相应的属性和方法来表示蛇的特征,在C语言中,可以使用结构体来实现相似的功能。
- 蛇由多节蛇身组成,包括蛇头也算是蛇身,每个蛇身都是一个结构体,我采用循环双链表来表示一条蛇,之所以使用双向循环链表,是为了每一节蛇身可以指向它的下一节蛇身,也可以指向它的上一节蛇身,同时头的上一节是尾巴,尾巴的下一节是头,便于我们遍历操作。类似于:(随意配图,无视苯环)
- 每一节蛇身有自己的坐标,也有自己运动方向,还有两个分别指向前一节和后一节的指针
- 蛇的运动方向,我们假设蛇只能向上下左右四个方向运动。
- 蛇的运动速度,我们假设蛇可以慢速,正常速,快速三种速度 爪巴
- 蛇的长度,我们记录在蛇的结构体内
2. 具体实现
snake.h头文件中部分内容:
typedef enum direction {up,right,down,left }Direction;typedef enum speed {slow,normal,fast, }Speed;//环状双向链表 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. 蛇的行为
定义了蛇的表示,那么蛇有哪些行为需要我们实现呢?
毫无疑问,在游戏中,我们要在地图上生成一条蛇,那么一个生成蛇的方法肯定少不了,于是有了
Snake *new_born_snake(int pos_x, int pos_y);参数pos_x,pox_y分别表示最初蛇的位置,这里我将蛇最初的长度设为1,相当于就一脑袋
蛇肯定要移动,蛇在移动的时候,直观上蛇身的全部节点都要移动,但实际则不然,只有两节蛇身是需要变化的,一节是脑袋,一节是蛇尾,其余的蛇身移动的位置其实都是其上一个蛇身移动前的位置,那么我们可以不管这些节点,我们需要做的就是新建一个蛇头,去掉蛇尾。
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);蛇吃到食物需要生长,我们就假设食物的位置变为一节蛇身(蛇头),尾巴不去掉,那么用上面add_head_node方法同样可以实现。
4. 具体实现
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. 在游戏中控制蛇,下篇揭晓。。。。。
一下篇链接
总结
以上是生活随笔为你收集整理的再来一次的C语言贪吃蛇小游戏(一)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: ASCII 编码对照表
- 下一篇: 再来一次的C语言贪吃蛇小游戏(二)