目录
游戏说明
1.撞墙死翘翘的情况
2.如何解决初始化问题
封装函数initSnake();
注意事项
解决方法
总结
效果演示
游戏说明
玩家通过上下左右按键来控制小蛇的移动,我们之前的内容完成了小蛇每按下一次右键小蛇便向右移动一格,但是玩贪吃蛇一定会出现撞墙的情况,结果就是死掉,那么如何用代码实现呢?
1.撞墙死翘翘的情况
撞墙的情况一般发生在蛇移动以后,即moveSnake(),那么我们只需要在移动以后做一下判断:
if(tail ->hang == 0 || tail->lie == 0 || tail->hang == 20 || tail ->lie == 20)
{
initSnake();
}
在这个贪吃蛇游戏中,游戏里的贪吃蛇头其实是“tail”,每moveSnake()一次蛇做上面的判断。
tail -> hang == 0 判断贪吃蛇是否撞到上墙
tail -> lie == 0 判断贪吃蛇是否撞到左墙
tail -> hang == 20 判断贪吃蛇是否撞到下墙
tail -> lie == lie 判断贪吃蛇是否撞到右墙
那么如果确实撞墙了应该怎么做呢,当然是游戏重新开始,那么游戏如何重新开始呢?
2.如何解决初始化问题
封装函数initSnake();
我们之前封装了初始化游戏的函数initSnake();
void initSnake(){
head = (struct Snake *)malloc(sizeof(struct Snake));
head->hang = 2;
head->lie = 2;
head->next = NULL;
tail = head;
addNode();
addNode();
addNode();
}
作用就是初始化蛇身。
注意事项
我们在撞墙的时候,实际上这个蛇的链表是存在的,但是你重新调用initSnake()实际上是开辟新的地址空间,然后给新的地址空间去赋值,创建出新的链表,那么旧的链表怎么办呢?
如果不释放内存可能会造成空间的浪费,甚至造成内存的泄漏。
不切实际的讲,这个游戏你一直玩,不释放内存,总有一天内存会被你撑爆。
解决方法
每一次初始化蛇身的时候都要把内存清理掉,看看是如何操作的。
在initSnake()中每次判断:
while(head != NULL)
{
free(head);
head = head -> next;
}
如果这个head != NULL 我们就遍历这个链表
但是我们发现如果在这里free(head)的话下面就会出现问题:head都被你free掉了,下面的:
head = (struct Snake *)malloc(sizeof(struct Snake));
head->hang = 2;
head->lie = 2;
head->next = NULL;
该如何执行呢?
所以我们定义一个临时的变量p;
使用p来存放head变量,然后让head指向head的下一位,之后释放掉p的内存。
struct Snake * p;
while(head != NULL)
{
p = head;
head = head -> next;
free(p);
}
当然我们不能忘了,在初始化的时候,head和tail我们尽量都赋上初值NULL。
struct Snake * head = NULL;
struct Snake * tail = NULL;
这样做的主要目的是防止head和tail变成野指针的状态。
总结
完善后的代码:
#include <curses.h>
#include <stdlib.h>
struct Snake
{
int hang;
int lie;
struct Snake * next;
};
struct Snake * head = NULL;
struct Snake * tail = NULL;
void initNcurse()
{
initscr();
keypad(stdscr,1);
}
int hasSnakeNode(int i,int j)
{
struct Snake * p;
p = head;
while(p != NULL)
{
if(p->hang == i && p->lie == j)
{
return 1;
}
p = p -> next;
}
return 0;
}
void gamePic()
{
int hang;
int lie;
move(0,0);
for(hang = 0;hang < 20;hang ++)
{
if(hang == 0)
{
for(lie = 0;lie < 20;lie ++)
{
printw("--");
}
printw("\n");
}
if(hang >= 0 && hang <= 19)
{
for(lie = 0;lie <= 20;lie ++)
{
if(lie == 0 || lie == 20) printw("|");
else if(hasSnakeNode(hang,lie)) printw("[]");
else printw(" ");
}
printw("\n");
}
if(hang == 19)
{
for(lie = 0;lie < 20;lie ++)
{
printw("--");
}
printw("\n");
printw("by beiweiqiuAC");
}
}
}
void addNode()
{
struct Snake * new = (struct Snake *)malloc(sizeof(struct Snake));
new->hang = head->hang;
new->lie = tail->lie+1;
new->next = NULL;
tail->next = new;
tail = new;
}
void initSnake(){
struct Snake * p;
while(head != NULL)
{
p = head;
head = head -> next;
free(p);
}
head = (struct Snake *)malloc(sizeof(struct Snake));
head->hang = 2;
head->lie = 2;
head->next = NULL;
tail = head;
addNode();
addNode();
addNode();
}
void deleNode()
{
// struct Snake * p;
// p = head;
head = head ->next;
// free(p);
}
void moveSnake()
{
addNode();
deleNode();
if(tail ->hang == 0 || tail->lie == 0 || tail->hang == 20 || tail ->lie == 20)
{
initSnake();
}
}
int main()
{
int con;
initNcurse();
initSnake();
gamePic();
while(1)
{
con = getch();
if(con == KEY_RIGHT){
moveSnake();
gamePic();
}
}
getch();//防止程序退出
endwin();
return 0;
}
默认该文件为snake8.c
我们打开终端,加入以下指令编译该文件:
gcc snake8.c -lcurses
系统默认生成的可执行文件为a.out,在终端环节下执行该文件
./a.out
效果演示
此时,我们的贪吃蛇来到了墙的最右边,我们按下右键贪吃蛇向右移动
撞到了墙,初始化,游戏重新开始
好啦,关于本节讲解贪吃蛇向右移动撞墙死掉并且释放内存的内容就到这里,希望本期博客能对你有所帮助。同时发现错误请多多指正!