您的位置:首页 > 运维架构 > Linux

Linux下控制台版贪吃蛇

2015-06-20 17:17 537 查看
学了些Uinux C的知识,一时兴起而做,基本功能实现后又懒得休憩,因此美观方面也就很将就了,也没大量测试,应该也有不少BUG,仅当学习所用了。也是一种总结

设计思路:

1. 蛇体主要以结构体形式实现

2. 用计时器来在规定时间间隔内不断激发SIGALRM信号,再自定义函数来控制蛇体不断移动

难点:

1. 获取键盘命令

2. 使蛇体不断移动

缺点:

1. 界面粗糙

2. 代码繁杂,冗余。感觉很多可以更为简练。

3. 逻辑设计不够清晰,代码应用不够灵活

4. 码部分代码时候输入法有问题,注释用英文,太烂,语法错误多多,懒得改

游戏界面:



游戏说明:

'w' 's' 'a' 'd'分别控制上下左右

‘q'为退出 'length‘表示蛇的长度 level表示等级,等级越高,移动速度越快

————————————————————————————————

多文件-代码:

头文件:

#ifndef  __SNAKE_H_
#define  __SNAKE_H_

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#define S_FOOD -1
#define S_NONT	0
#define S_HEAD  1
#define S_BODY  2
#define S_TAIL  3

//define coordinate
typedef struct
{
int x;
int y;
}Coord;
//define snake
typedef struct node
{
int x;
int y;
struct node *next;
}Snake;

extern Snake *head, *tail;
extern Coord food;
extern int arr[100][100];
extern int row, col;
extern Coord dirct;
extern int s_len;
extern int level;

//创建蛇的节点
Snake *crt_snake(void);
//初始化
void init_set(void);
//打印界面
void print_show(void);
//蛇体移动
void s_move(void);
//键盘获取命令
void init_ter(int mode);
//投放食物
void set_food(void);
//判断游戏是否结束
void judge(void);
//创建计时器
void set_itime(void);

#endif // __SNAKE_H_


main 函数:

#include "snake.h"

int main(void)
{
init_set();
set_itime();
get_order();
return 0;
}


界面文件:

#include "snake.h"

//just print a line
void print_line(void)
{
int i = 0;
for (i =0; i <col +2; i++)
{
printf("- ");
}
printf("\n");
}

//print the interface
void print_show(void)
{
system("clear");
int i = 0, j = 0;

printf("\n \e[34mlevel: %d\e[m\n", level);
print_line();

for (i =0; i <row; i++)
{
printf("| ");
for (j =0; j <col; j++)
{
if (S_NONT == arr[i][j])
{
printf("  ");
}
else if (S_BODY ==  arr[i][j])
{
printf("* ");
}
else if (S_HEAD == arr[i][j])
{
printf("+ ");
}
else if (S_TAIL == arr[i][j])
{
printf("- ");
}
else
{
printf("$ ");
}
}

printf(" |\n");
}

print_line();

printf("Quit: 'Q'  length:%d\n", s_len);
}


初始化、收尾及判断函数:

// initialize all kinds of set

#include "snake.h"
#include <time.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>

//define arr for printing the interface
int arr[100][100];
//define the head and tail of snake
Snake *head, *tail;
//define the food by Coord struct
Coord food;
int row, col;
//record the snake length
int s_len;
//set the level of the game
int level;

void init_ter(int mode)
{
static struct termios old;
if (1 == mode)
{
tcgetattr(0, &old); // 获取之前属性
struct termios new = old; //临时修改属性
new.c_lflag &= ~ICANON; //开启非标准模式
new.c_lflag &= ~ECHO; // 屏蔽回显
new.c_cc[VMIN] = 0; // 立即接收
new.c_cc[VTIME] = 1; //受min影响 0秒
//把临时设置到标准输入0,改变标准输入的特征
tcsetattr(0, TCSANOW, &new);
}
if (0 == mode)
{
tcsetattr(0, TCSANOW, &old);

}

}

void judge(void)
{
//胜利的判断
if (s_len == (row * col / 2))
{
printf("GREAT! YOU WIN!\n");
exit(0);
}
//撞边框失败,碰到自身的判断在s_move函数
if (head->x >= row || head->x <0 || head->y >= col || head->y <0)
{
printf("YOU LOSE \n");
exit(0);
}
}

//when receive the signal of alarm
void fa(int signo)
{
static cnt = 0;
cnt++;
s_move();
judge();
print_show();
if (0 == cnt % 60 && level < 10)
{
level++;
set_itime();
}
//	printf("(%d,%d)\n", dirct.x, dirct.y);
}

//create snake node
Snake *crt_snake(void)
{
Snake *p = (Snake *)malloc(sizeof(Snake));
p->x = 0;
p->y = 0;
p->next = NULL;
return p;
}

//set food for snake
void set_food(void)
{
srand((unsigned)time(0));
while(1)
{
food.x = rand() % row;
food.y = rand() % col;

if (!arr[food.x][food.y])
{
arr[food.x][food.y] = S_FOOD;
break;
}
}
}

//当结束时执行的函数,释放内存
void destroy(void)
{
init_ter(0);
if (tail == NULL)
{
return;
}
while (tail != NULL)
{
Snake *p = tail;
tail = tail->next;
free(p);
p = NULL;
}
}

//set the interval timer
void set_itime(void)
{
struct itimerval it;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 999999 / level;

it.it_value.tv_sec = 1;
it.it_value.tv_usec = 0;

int res = setitimer(ITIMER_REAL, &it, NULL);
if(-1 == res)
{
perror("settimer"), exit(-1);
}
}

//initialize the interface and snake
void init_set(void)
{
atexit(destroy);
printf("please input the size of the face\n");
while((2 != scanf("%d%d", &row, &col)) || row <5 || col <5 || row >100 || col >100)
{
printf("incorrect input, input again!\n");
scanf("%*[\n]");
scanf("%*c");
}

//init the snake, make it in centre
head = crt_snake();
tail = crt_snake();
head->x = row / 2;
head->y = col /2;
head->next = NULL;
tail->x = head->x -1;
tail->y = head->y;
tail->next = head;

arr[head->x][head->y] = S_HEAD;
arr[tail->x][tail->y] = S_TAIL;

set_food();
//active the function fa when the recive the sigalrm form itimer
signal(SIGALRM, fa);
// snake length of starting
s_len = 2;
level = 1;
}


蛇体移动:

#include "snake.h"

//初始化移动方向
Coord dirct = {1, 0};

//获取键盘移动命令
void get_order(void)
{
char ch = 0;
init_ter(1);
while (1)
{
read(0, &ch, 1);
switch(ch)
{
case 'w':
case 'W':
if (dirct.x != 1)
{
dirct.x = -1;
dirct.y = 0;
}
break;
case 's':
case 'S':
if (dirct.x != -1)
{
dirct.x = 1;
dirct.y = 0;
}
break;
case 'a':
case 'A':
if (dirct.y != 1)
{
dirct.x = 0;
dirct.y = -1;
}
break;
case 'd':
case 'D':
if (dirct.y != -1)
{
dirct.x = 0;
dirct.y = 1;
}
break;
case 'q':
case 'Q':
exit(0);
default:
break;
}
}

}

//蛇体移动
void s_move(void)
{
//定义两坐标暂存蛇头、蛇尾坐标
Coord co_h, co_t;
co_h.x = head->x;
co_h.y = head->y;
co_t.x = tail->x;
co_t.y = tail->y;

//吃到食物情况
if ((food.x == head->x + dirct.x ) && (food.y == head->y + dirct.y))
{
Snake *ps = crt_snake();
ps->x = food.x;
ps->y = food.y;
head->next = ps;
head = ps;
arr[head->x][head->y] = S_HEAD;
arr[co_h.x][co_h.y] = S_BODY;
//蛇体长度加1
s_len++;
set_food();
}
else
{
Snake *ps = tail;
while (ps->next != NULL)
{
ps->x = ps->next->x;
ps->y = ps->next->y;
ps = ps->next;
}
head->x += dirct.x;
head->y += dirct.y;

//是否碰到蛇身的判断
if (S_BODY == arr[head->x][head->y] || S_TAIL == arr[head->x][head->y])
{
printf("YOU LOSE\n");
exit(0);
}

arr[head->x][head->y] = S_HEAD;
arr[co_h.x][co_h.y] = S_BODY;
arr[tail->x][tail->y] = S_TAIL;
arr[co_t.x][co_t.y] = S_NONT;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: