/**********************
* 项目名称:贪吃蛇
* 项目要求:在GCC 下 完成贪吃蛇的游戏
* 项目采用的知识:
* 1.链表(贪吃蛇,食物)
* 2.构图(边框,贪吃蛇,食物,背景)
* 3.随机数(食物)
* 4.判断条件(蛇不能回头,不能碰尾巴,不能碰边框)
* 5.积分
**********************/
#include<stdio.h>
#include<assert.h>
#include<time.h>
#include<stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
int map[30][60] = {'0'}; //0 背景 1 蛇 2 食物 3 边框
int direct = 3; //1 上 2下 3 左 4 右
int score = 0 ; //分数
int level = 1 ; //游戏速度级别
typedef struct snake{
int x;
int y;
struct snake *next;
}Snake;
typedef struct food{
int x;
int y;
}Food;
Food f;
//初始化地图
void print_map(int map[30][60]);
//打印所有信息
void print_all(int map[30][60]);
//创建头节点
Snake *creat_head();
//创建蛇链表
Snake *init_snake(Snake *head);
//画蛇
void draw_snake(Snake *head);
//随即食物产生
void food_get();
//四个方向移动坐标
void move_left(Snake *head);
void move_right(Snake *head);
void move_up(Snake *head);
void move_down(Snake *head);
//及时响应输入
void get_key();
//蛇身的控制函数
void snake_move(Snake *head,int direct);
//检验食物是否被吃掉
int check_food();
//吃一口食物增加身体
void add_snake(Snake *head);
//检验是否碰到墙壁
int wall_check();
//检验是否碰到身体
int body_check(Snake *head);
//游戏速度控制
void speed_level();
void game_snake(void)
{
srand(time(NULL));
Snake *head = creat_head();
print_map(map); //初始化地图
init_snake(head); //初始化蛇
draw_snake(head); //画出来 (也可以不画出来)
print_all(map);
food_get(); //随即给食物 (不可以去掉,因为需要判断食物是否吃掉)
while(1){
speed_level();
get_key();
system("clear");
snake_move(head,direct);
printf("\t\t\t简易贪吃蛇\n"); //view 界面
printf("\t\t\t作者:钱蓓杰\n");
printf("\t\t\t指导老师:汪大佬\n");
printf("\t\t\tw a s d 移动 撞墙或者碰撞身体结束\n");
printf("\t\t\t您的得分 : %d\n",score);
printf("\t\t\t当前的游戏级别是 %d\n",level);
print_all(map);
if(check_food()){
food_get();
add_snake(head);
score += 10;
level++;
}
if(wall_check() || body_check(head)){
printf("game over\n");
break;
}
get_key();
}
printf("游戏结束,您的游戏分数为 %d\n",score);
Snake *p = head;
Snake *q = NULL;
while(p->next != head){
q = p->next;
p->next = p->next->next;
free(q);
}
free(head);
}
//游戏速度控制
void speed_level()
{
switch(level){
case 1: usleep(1000000);
break;
case 2: usleep(1000000/2);
break;
case 3: usleep(1000000/4);
break;
case 4: usleep(1000000/8);
break;
case 5: usleep(1000000/16);
break;
case 6: usleep(1000000/32);
break;
default:
break;
}
}
//检测是否碰到蛇身体
int body_check(Snake *head)
{
assert(head);
Snake *p = head->next;
p = p->next;
while(p != head){
if(p->x == head->next->x && p->y == head->next->y){
return 1;
}
p = p->next;
}
return 0;
}
//检查是否碰到边框
int wall_check()
{
int i = 0;
for(i = 0;i < 30;i++){
if(map[i][0] != 3 || map[i][59] != 3){
return 1;
}
}
for(i = 0;i <60 ;i++){
if(map[0][i] != 3 || map[29][i] != 3){
return 1;
}
}
return 0;
}
//检查是否吃到食物
int check_food()
{
if(map[f.x][f.y] != 2){
return 1;
}else{
return 0;
}
}
//吃到食物后添加蛇尾巴 //蛇头比较敏感,修改为蛇尾
void add_snake(Snake *head)
{
assert(head);
Snake *tail = head->next;
while(tail->next != head){
tail = tail->next;
}
//Snake * p = NULL ;
Snake *new = (Snake *)calloc(1,sizeof(Snake));
if(direct == 1){
new->x = tail->x - 1;
new->y = tail->y;
}else if(direct == 2){
new->x = tail->x + 1;
new->y = tail->y;
}else if(direct == 3){
new->x = tail->x;
new->y = tail->y + 1;
}else {
new->x = tail->x;
new->y = tail->y - 1;
}
new->next = head;
tail->next = new;
}
//蛇身体移动
void snake_move(Snake *head,int direct)
{
assert(head);
switch(direct){
case 1:
move_up(head);draw_snake(head);
break;
case 2:
move_down(head);draw_snake(head);
break;
case 3:
move_left(head);draw_snake(head);
break;
case 4:
move_right(head);draw_snake(head);
break;
default :
break;
}
}
//左移动 //横坐标-1,移动一次
void move_left(Snake *head)
{
assert(head);
Snake *tail = head->next;
Snake * p = NULL ;
Snake *new = (Snake *)calloc(1,sizeof(Snake));
new->x = tail->x;
new->y = tail->y - 1;
new->next = tail;
head->next = new; //添加头节点
while(tail->next->next != head){
tail = tail->next;
}
map[tail->next->x][tail->next->y] = 0;
p = tail->next;
tail->next = tail->next->next; //释放尾节点
free(p);
p = NULL;
}
//右移动 //横坐标+1,移动一次
void move_right(Snake *head)
{
assert(head);
Snake *tail = head->next;
Snake * p = NULL ;
Snake *new = (Snake *)calloc(1,sizeof(Snake));
new->x = tail->x;
new->y = tail->y + 1;
new->next = tail;
head->next = new; //添加头节点
while(tail->next->next != head){
tail = tail->next;
}
map[tail->next->x][tail->next->y] = 0;
p = tail->next;
tail->next = tail->next->next; //释放尾节点
free(p);
p = NULL;
}
//上移动 //纵坐标+1,移动一次
void move_up(Snake *head)
{
assert(head);
Snake *tail = head->next;
Snake * p = NULL ;
Snake *new = (Snake *)calloc(1,sizeof(Snake));
new->x = tail->x - 1;
new->y = tail->y;
new->next = tail;
head->next = new; //添加头节点
while(tail->next->next != head){
tail = tail->next;
}
map[tail->next->x][tail->next->y] = 0;
p = tail->next;
tail->next = tail->next->next; //释放尾节点
free(p);
p = NULL;
}
//下移动 //纵坐标-1,移动一次
void move_down(Snake *head)
{
assert(head);
Snake *tail = head->next;
Snake * p = NULL ;
Snake *new = (Snake *)calloc(1,sizeof(Snake));
new->x = tail->x + 1;
new->y = tail->y;
new->next = tail;
head->next = new; //添加头节点
while(tail->next->next != head){
tail = tail->next;
}
map[tail->next->x][tail->next->y] = 0;
p = tail->next;
tail->next = tail->next->next; //释放尾节点
free(p);
p = NULL;
}
//随即食物产生
void food_get()
{
int x = 0;
int y = 0;
while(1){
x = rand() % 29;
y = rand() % 59;
f.x = x;
f.y = y;
if(map[x][y] == 1 || map[x][y] == 3){
continue;
}else{
map[x][y] = 2;
break;
}
}
}
//创建头节点
Snake *creat_head()
{
Snake *head = (Snake *)calloc(1,sizeof(Snake));
assert(head);
head->next = head;
return head;
}
//创建蛇链表
Snake *init_snake(Snake *head)
{
assert(head);
int i = 0;
Snake *tail = (Snake *)calloc(1,sizeof(Snake));
head->next = tail;
tail->next = head;
tail->x = 15;
tail->y = 15;
for(i = 0;i<5;i++){
Snake *new = (Snake *)calloc(1,sizeof(Snake));
new->x = tail->x-1;
new->y = tail->y;
tail->next = new;
new->next = head;
tail = new ;
}
return head;
}
//画蛇
void draw_snake(Snake *head)
{
assert(head);
Snake *p = head->next;
while(p != head){
map[p->x][p->y] = 1;
p = p->next;
}
}
//初始化地图
void print_map(int map[30][60])
{
int i = 0;
int j = 0;
for(i = 0;i < 30;i++){
map[i][0] = 3;
map[i][59] = 3;
}
for(j = 0;j < 60;j++){
map[0][j] = 3;
map[29][j] = 3;
}
}
//打印所有信息
void print_all(int map[30][60])
{
int i = 0;
int j = 0;
for(i = 0;i < 30;i++){
for(j = 0 ;j < 60;j++){
if(map[i][j] == 0){
printf(" ");
}else if(map[i][j] == 3){
printf("#");
}else if(map[i][j] == 1){
printf("*");
}else if(map[i][j] == 2){
printf("&");
}
}
printf("\n");
}
}
int kbhit(void)
{
struct termios oldt, newt;
int ch = 0;
int oldf = 0;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch, stdin);
return 1;
}
return 0;
}
void get_key()
{
char key = '\0';
if(kbhit()){
key = getchar();
}
switch (key) {
case 'w'://用户按 上 键
if(direct != 2){
direct = 1;
}
break;
case 's'://用户按 下 键
if (direct != 1){
direct = 2;
}
break;
case 'a'://用户按 左 键
if (direct != 4){
direct = 3;
}
break;
case 'd'://用户按 右 键
if (direct != 3)
direct = 4;
break;
}
}
贪吃蛇 Linux C语言 第二次小练手
最新推荐文章于 2024-03-31 22:13:38 发布