UNIX_C 链表实现贪吃蛇游戏_吃苹果可生长(.c 函数实现文件)
UNIX_C 链表贪吃蛇游戏_吃苹果可生长代码——<.c 测试文件文件>
UNIX_C 链表贪吃蛇游戏_吃苹果可生长代码——<.h头文件>
//链表实现可生长贪吃蛇游戏
#include "snake_me.h"
//设置苹果开始的随机位置
NOTE * init_apple( NOTE * p_apple )
{
p_apple->row = (rand()%(SIZE_ROW-2)) +1; //随机坐标
p_apple->col = (rand()%(SIZE_COL-2)) +1;
p_apple->mark = APPLE; //标记为蛇
return p_apple;
}
//蛇身动态分配内存生成
SNAKE * init_note(void)
{
SNAKE * pnote_temp = (SNAKE *) malloc ( sizeof(SNAKE) );
if( !pnote_temp )
{
perror("Malloc");
return NULL;
}
pnote_temp->note.mark = MID;
pnote_temp->note.row = 0;
pnote_temp->note.col = 0;
pnote_temp->p_next = NULL;
pnote_temp->p_pre = NULL;
return pnote_temp;
}
//初始化蛇头并设置蛇开始位置
SNAKE * init_snake_head( void )
{
SNAKE * psnake_head = init_note(); //蛇头
if(!psnake_head)
{
perror("psnake_head or psanke_tail or psnake_flag is NULL");
return NULL;
}
//将蛇头默认设置在地图中间
psnake_head->note.row = SIZE_ROW / 2;
psnake_head->note.col = SIZE_COL / 2;
psnake_head->note.mark = HEAD;
psnake_head->p_next = NULL;
psnake_head->p_pre = NULL;
return psnake_head;
}
//初始化蛇尾
SNAKE * init_snake_tail( SNAKE * p_snake )
{
SNAKE * psnake_head = p_snake;
SNAKE * psnake_tail = init_note(); //蛇尾
if(!psnake_head || !psnake_tail )
{
perror("psnake_head or psanke_tail or psnake_flag is NULL");
return NULL;
}
//将蛇尾坐标放在蛇头后面
psnake_tail->note.row = psnake_head->note.row - 1;
psnake_tail->note.col = psnake_head->note.col;
psnake_tail->note.mark = TAIL;
//将蛇尾挂在蛇头链表后面
psnake_head->p_next = psnake_tail;
psnake_tail->p_pre = psnake_head;
psnake_tail->p_next = NULL;
psnake_head->p_pre = NULL;
return psnake_head;
}
//蛇身插入一节
SNAKE * insert_add_snake(const NOTE * apple, SNAKE * p_snake )
{
SNAKE * psnake_temp = init_note();
if(!psnake_temp)
{
perror("Psnake_mid ERROR");
return NULL;
}
psnake_temp->note.mark = HEAD;
psnake_temp->note.col = apple->col;
psnake_temp->note.row = apple->row;
p_snake->note.mark = MID;
psnake_temp->p_pre = NULL;
psnake_temp->p_next = p_snake;
p_snake->p_pre = psnake_temp;
return psnake_temp;
}
//判断蛇和苹果位置是否重叠返回1为苹果和蛇有重叠,返回-1为不重叠
int link_overlap( const NOTE * p_apple, const SNAKE * p_snake)
{
const SNAKE * psnake_i = NULL;
//printf("%d:%d\t", p_apple->row, p_apple->col);
int i = 0;
for( psnake_i = p_snake; psnake_i != NULL; psnake_i = psnake_i->p_next )
{
// printf("%d:%d-",i++, psnake_i->note.row, psnake_i->note.col);
if(p_apple->row == psnake_i->note.row && p_apple->col == psnake_i->note.col)
{
return 1;
}
}
return -1;
}
//判断蛇头是否和苹果的位置相同,相同表示吃到了苹果,1返回重叠,-1为不重叠
int link_overlap_head( const NOTE * p_apple, const SNAKE * p_snake)
{
if(p_apple->row == p_snake->note.row && p_apple->col == p_snake->note.col)
{
return 1;
}
return -1;
}
//显示地图内容
void show_map(const NOTE * p_apple, const SNAKE * p_snake )
{
int r = 0;
int c = 0;
int flag = 0;
for( r = 0; r < SIZE_ROW; r++)
{
for( c = 0; c<SIZE_COL; c++)
{
flag = 0;
if( 0 == r || SIZE_ROW-1 == r ) //墙
{
printf("%c", PIC_ROW_WALL);
continue;
}
if( 0 == c || SIZE_COL-1 == c ) //墙
{
printf("%c", PIC_COL_WALL);
continue;
}
if(r == p_apple->row && c == p_apple->col && p_apple->mark == APPLE )
{
printf("%c", PIC_APPLE); //苹果
continue;
}
const SNAKE * psnake_i = NULL;
//遍历蛇比较坐标
for( psnake_i = p_snake; psnake_i != NULL; psnake_i = psnake_i->p_next )
{
if( r == psnake_i->note.row && c == psnake_i->note.col )
{
flag = 1; //标记位
if( psnake_i->note.mark == HEAD) //蛇头
{
printf("%c", PIC_HEAD);
break;
}
if(psnake_i->note.mark == TAIL) //蛇尾
{
printf("%c", PIC_TAIL);
break;
}
if(psnake_i->note.mark == MID) //蛇尾
{
printf("%c", PIC_MID);
break;
}
}
}
if(0 == flag)
{
printf(" ");
}
}
printf("\n");
}
}
//释放动态申请的内存
void dele_init_snake( SNAKE * p_snake )
{
SNAKE * psnake_i = p_snake;
while( psnake_i != NULL )
{
SNAKE * psnake_temp = psnake_i->p_next;
free(psnake_i);
psnake_i = psnake_temp;
psnake_temp = NULL;
}
}
//UNIX中自动获取键盘字符,而不用敲击回车键读取字符
static int linux_getch(void)
{
struct termios term_old;
ioctl( STDIN_FILENO, TCGETS, &term_old );
struct termios term_new = term_old;
term_new.c_lflag &= ~( ECHO | ICANON );
ioctl( STDIN_FILENO, TCSETS, &term_new );
int ch = getchar();
ioctl(STDIN_FILENO, TCSETS, &term_old);
return ch;
}
//检查蛇头是否与蛇身体发生触碰, 如有则游戏结束
void inspect_snake( const SNAKE * p_snake )
{
const SNAKE * psnake_head = p_snake;
const SNAKE * psnake_i = NULL;
for ( psnake_i = p_snake->p_next; psnake_i != NULL; psnake_i = psnake_i->p_next)
{
//判断蛇头坐标是否与蛇身坐标有重合
if(psnake_i->note.row == psnake_head->note.row && psnake_i->note.col == psnake_head->note.col)
{
printf("\n\n\t蛇咬到自己,游戏结束!!!\n");
exit(-1);
}
}
}
//移动蛇
SNAKE * move_snake( SNAKE * p_snake )
{
NOTE pnote_temp = p_snake->note;
// SNAKE * psnake_temp = p_snake;
printf("\n\n");
printf("\t上 %c\n", U);
printf("左 %c\t\t右 %c\n", L, R);
printf("\t下 %c\n", D);
printf("请输入蛇移动的方向:");
int ch = linux_getch(); //获取方向并不用按回车键
if( U == ch || (U-'a'+'A') == ch )
{
pnote_temp.row--;
}
else if( D == ch || (D-'a'+'A') == ch )
{
pnote_temp.row++;
}
else if( L == ch || (L-'a'+'A') == ch )
{
pnote_temp.col--;
}
else if( R == ch || (R-'a'+'A') == ch )
{
pnote_temp.col++;
}
if(pnote_temp.row == 0 || pnote_temp.row == SIZE_ROW-1
|| pnote_temp.col == 0 || pnote_temp.col == SIZE_COL-1 )
{
printf("\n\n\t蛇触碰墙壁,游戏结束!\n");
exit(-1);
}
SNAKE * psnake_i = NULL;
for( psnake_i = p_snake; psnake_i != NULL; psnake_i = psnake_i->p_next )
{
NOTE temp = psnake_i->note;
psnake_i->note.row = pnote_temp.row; //把新坐标赋值给蛇头
psnake_i->note.col = pnote_temp.col;
pnote_temp = temp; //把蛇头原坐标赋值给下一个坐标
}
return p_snake;
}
//
注:此代码为自己初学而写,如有不足或错误初请评论处提出并指教