最近好久没有写博客了,主要忙于网络编程的学习和聊天室项目的编写,怕忘了这个好习惯,只能拿点以前的东西了
/**********************************************
time : 2017年8月10日16:04:59
filename: snack_1.c
maker: Leo
explain:little sncak game
***********************************************/
//要制作一个贪吃神游戏,首先我必须要有蛇,墙和食物。老师的看不懂。不管了,先敲一遍
//gcc snake_1.c -lpthread
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <termios.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#define KEYCODE_U 0x41 //向上移动
#define KEYCODE_D 0x42 //向下移动
#define KEYCODE_L 0x44 //向左移动
#define KEYCODE_R 0x43 //向右移动
int kfd = 0;
struct termios cooked,raw;
char dir = KEYCODE_U; //默认向上移动
//获取键盘响应:上下左右键
void* get_dir(void *a)
{
while(1)
{
char c;
tcgetattr(kfd,&cooked); //得到termios结构体保存,然后重新配置终端
//memcpy内存拷贝函数
memcpy(&raw, &cooked,sizeof(struct termios));
raw.c_lflag &=~ (ICANON | ECHO);
raw.c_cc[VEOL] = 1;
raw.c_cc[VEOF] = 2;
tcsetattr(kfd, TCSANOW, &raw);
//读取失败
if(read(kfd, &c,1)<0)
{
perror("read");
exit(-1); //表示非正常关闭
}
tcsetattr(kfd,TCSANOW,&cooked); //程序结束时在恢复原来的配置
dir = c;
}
}
unsigned char map[17][17] = {0}; //游戏地图
unsigned char snake[50] = {133}; //初始化蛇坐标,游戏开始的时候在(8,5)这个位置
unsigned char food = 67; //食物的长度,游戏开始的时候在(4,3)的位置
int len = 1; //保存蛇当前的长度
//将数字转化为坐标
void num_to_xy(unsigned char num,unsigned char *x,unsigned char *y)
{
*x = num>>4; //右移了四位,及用一个字节的四位地址保存x
*y = (unsigned char)(num<<4) >> 4; //清空四位地址值,及用四位高地质保存y
} //因为需要改变x,y的值,所以用指针
//更新地图数据
void update_map()
{
int i,j;
//初始化地图
for(i=0;i<17;i++)
{
for(j=0;j<17;j++)
{
if(i == 0 || i == 16 || j == 0 || j==16) //设置边界
{
map[i][j] = '#';
}
else
{
map[i][j] = ' ';
}
}
}
//初始化食物
unsigned char x,y;
num_to_xy(food,&x,&y); //获取食物坐标(4,3) 0100 0011 及67
map[y][x] = '!';
//初始化蛇
for(i=0;i<len;i++)
{
num_to_xy(snake[i],&x,&y); //获取蛇第i+1节身体的坐标
map[y][x] = '*'; //表示蛇的身体 一维数组表示竖轴,二维数组表示横轴
}
}
//打印地图
void print_map()
{
int i,j;
for(i=0;i<17;i++)
{
for(j=0;j<17;j++)
{
printf("%c",map[i][j]);
}
printf("\n");
}
usleep(500*1000); //0.1秒刷新
//sleep(1);
system("clear"); //清屏
}
//生成食物
unsigned char generate_food()
{
//需要用到随机数
srand((unsigned int)time(NULL));
unsigned char new_food;
unsigned char x,y;
int insnake = 0; //标志生成的食物没有在蛇的身体里,默认是不在
do
{
insnake = 0;
new_food = rand()%256; //随机刷星一个食物
num_to_xy(new_food,&x,&y);
int i;
for(i=0;i<len;i++)
{
if(snake[i] == new_food)
{
insnake = 1; //代表
break;
}
}
}while(x==0 || x== 16 || y==0 || y==16 || insnake);
return new_food;
}
//移动蛇
void move_snake()
{
unsigned char x,y; //坐标
num_to_xy(snake[0], &x, &y); //获取蛇头坐标
//判断移动方向
switch (dir)
{
case KEYCODE_U:
y--;
break;
case KEYCODE_D:
y++;
break;
case KEYCODE_L:
x--;
break;
case KEYCODE_R:
x++;
break;
}
unsigned char last = snake[0]; //保存蛇头的位置
snake[0] = (unsigned char)(x << 4) + y; //更新蛇的位置
int i;
//移动蛇的身体
unsigned char current;
for(i=1;i<len;i++) //循环交换做到蛇的整体移动
{
current = snake[i];
snake[i] = last;
last = current;
}
//如果蛇头和食物重合,证明吃到食物
//len是蛇的长度 为了满足数组,从零开始
if(snake[0] == food)
{
//蛇要长一节
snake[len] = last;
len++;
//重新生成食物
food = generate_food();
}
}
//判断蛇是否存活,如果返回值是0代表存活,1代表不应该存活啊
int isalive()
{
unsigned char x,y;
num_to_xy (snake[0],&x,&y); //获取舌头
//判断蛇头有没有越过边界
if(x==0 || x== 16 || y==0 || y==16)
{
return 1;
}
//判断蛇头有没有咬到自己
int i;
for(i=1;i<len;i++)
{
//if(snake[0] = snake[i]);
if(snake[0] == snake[i])
{
return 1;
}
}
return 0;
}
int main()
{
//开启一个线程用于获取键盘的上下左右键响应
pthread_t tid1;
pthread_create(&tid1,NULL,get_dir,NULL);
while(1)
{
//更新数据地图
update_map();
//打印地图
print_map();
//移动蛇
move_snake();
if(isalive() == 1)
break;
}
tcsetattr(kfd,TCSANOW,&cooked); //程序结束是恢复原来的配置
printf("Game Over.\n");
return 0;
}