设为首页 加入收藏

TOP

C语言实现贪吃蛇(3):结构+链表实现(一)
2016-12-06 20:24:02 】 浏览:449
Tags:语言 实现 结构

本博客所讲到的知识跟前面我的两篇博客:C语言实现贪吃蛇(一)—-数组实现》、C语言实现贪吃蛇(二)—-局部刷新》 有很大的关系,建议大家前往看一下,尤其是第一篇,那篇博客是所有关于贪吃蛇游戏的基础。

之前的两篇博客将运用的C语言知识限定在了一般的数组上,但如果已经完整地了解过C语言的话,运用结构和链表会让程序的结构更明了,逻辑更清晰。这篇博客就将介绍如何用结构和链表改善之前的程序。

程序实现:

首先,把蛇看成一条单链表(还挺形象),蛇的每一节就是一个节点,以下是蛇节点的定义:

//蛇结点 
typedef struct node{
    //COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标
    COORD cor;      //蛇节点坐标
    struct node * next;     //该节点的下一节点
} snake_node;

老套路,我们来看看程序修改后的一些变量和函数声明:

#include 
  
   
#include <
   windows.h>
#include 
   
     #include 
    
      #include 
     
       //72,80,75,77是方向键对应的键值 #define UP 72 #define DOWN 80 #define LEFT 75 #define RIGHT 77 #define SNAKE 1 #define FOOD 2 #define BAR 3 //用链表实现 //蛇结点 typedef struct node{ //COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标 COORD cor; struct node * next; }snake_node; //初始化食物坐标 COORD food = {3,5}; //初始化蛇头 snake_node * snake_head; //蛇长 char len = 1; //坐标比较函数(程序中有多次的坐标比较) int cor_cmp(COORD pt1,COORD pt2); //将光标移动到命令行的 (x,y)位置,参数是一个坐标结构体 void gotoxy(COORD pt); //初始化游戏 void init_game(void); //生成食物坐标 COORD generate_food(void); //移动蛇 void move_snake(int dir); //释放申请的内存空间 void free_node(snake_node * n); //获取方向函数(注意当蛇身长度超过一节时不能回头) int get_dir(int old_dir); //判断蛇死活的函数(判断了蛇是否撞到边界或者自食) int isalive(void); int main(void) { int dir = UP; //初始方向默认向上,UP是我们定义的宏 init_game(); //初始化游戏 while(1){ dir = get_dir(dir); //获取方向(我们摁下的方向) move_snake(dir); //移动蛇身 if(!isalive()){ //判断蛇的生命状态 break; } } //清除屏幕 system("cls"); printf("Game Over!\n"); //释放申请的内存空间 free_node(snake_head); return 0; }
     
    
   
  

这篇博客是对 《C语言实现贪吃蛇(二)—-局部刷新》 进行的优化,在该优化中我们修改的方面有一下几点(由于坐标存储的方式发生改变,因此所有的函数都得改变):

蛇节点使用结构体存储 坐标改用 COORD 结构体存储 增加坐标比较函数(因为坐标比较次数较多) 增加链表释放函数(蛇挂了之后,释放蛇单链表) 由于坐标存储的方式发生改变,因此所有的函数都得改变

我们先来看坐标比较函数,其实这个函数是很简单的:
也就对每个点的 x、y 坐标分别比较

//坐标比较函数(程序中有多次的坐标比较)
int cor_cmp(COORD pt1,COORD pt2);

int cor_cmp(COORD pt1, COORD pt2)
{
    return (pt1.X == pt2.X && pt1.Y == pt2.Y);
}

//将光标移动到命令行的 (x,y)位置,参数是一个坐标结构体
void gotoxy(COORD pt);

void gotoxy(COORD pt)
{
    //句柄 
    HANDLE hout;

    //GetStdHandle函数获取一个指向特定标准设备的句柄,包括标准输入,标准输出和标准错误。
    //STD_OUTPUT_HANDLE正是代表标准输出(也就是显示屏)的宏 
    hout = GetStdHandle(STD_OUTPUT_HANDLE);

    //SetConsoleCursorPosition函数用于设置控制台光标的位置
    SetConsoleCursorPosition(hout, pt);
}

//初始化游戏
void init_game(void);

void init_game(void){
    //初始化蛇头 (3,9)
    snake_head = (snake_node *)malloc(sizeof(snake_node));    //从无到有,必须手动申请内存
    (snake_head->cor).X = 3;
    (snake_head->cor).Y = 9;
    snake_head->next= NULL;

    int i,j;    //i,j对应x,y轴  
    for(j = 0;j < 17;j ++){
        for (i = 0; i<17; i++) {
            //围墙
            if (i == 0 || i == 16 || j == 0 || j == 16)
            {
                putchar('#');
            }
            //蛇身
            else if (i == (snake_head->cor).X && j == (snake_head->cor).Y)
            {
                putchar('*');
            }
            //食物
            else if (i == food.X && j == food.Y)
            {
                putchar('$');
            }
            //空白地方
            else
            {
                putchar(' ');
            }
        }
        putchar('\n');
    }
}

//生成食物坐标
COORD generate_food(void);

COORD generate_food(void){
    COORD food_;
    snake_node * p = NULL;      //把定义的指针初始为NULL是一个好习惯
    int in_snake = 0;
    //以当前时间为参数提供种子供rand()函数生成更为随机的数
    srand((unsigned int)time(NULL));
    //循环产生在边界内且不在蛇身上的食物
    do {
        food_.X = rand() % 16;
        food_.Y = rand() % 16;
        for (p = snake_head; p != NULL; p = p->next){
            //在蛇身上 
            if (cor_cmp(food_,p->cor)){
                in_snake = 1;       
            }
        }

    } while (food_.X == 0 || food_.X == 16 || food_.Y == 0 || food_.Y == 16 || in_snake);

    return food_;
}

好了,有了这些改进过的 函数,我们就可以写出move_snake函数了。这时我们还需要考虑的一个问题是我们该如何利用链表存储蛇的坐标。链表的一个优势在于它是动态的,它的单元数不像数组一样一开始就是被写死的。我们自然而然地想到当蛇吃到食物时,就向链表尾部追加一个单元。至于如何更新蛇的坐标,有两个办法,第一种是像之前数组的方法一样,从蛇头开始向后传递坐标,其代码如下

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇字符串 非暴力for循环法(内附C语.. 下一篇C语言编写扫雷

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目