首页 > 其他分享 >贪吃蛇完整代码解析

贪吃蛇完整代码解析

时间:2024-07-14 13:18:46浏览次数:6  
标签:body head int 代码 贪吃蛇 snake 解析 col row

1.1头文件

点击查看代码
#include<stdio.h>
#include<curses.h>  //包含curses插件
#include<stdlib.h>  //srand
#include<unistd.h>  //sleep头文件
#include<stdbool.h>  //bool条件判断
#include <pthread.h> //线程头文件
#include <time.h> //时间头文件

define WIDHT 20 //地图长度

define HEIGHT 20 //地图宽度

define MIN 0 //最小值宏定义

define UP 1 //蛇的方向上

define DOWN -1 //下

define LEFT 2 //左

define RIGHT -2 //右

//定义一个结构体snake_t
typedef struct snake
{
int row;
int col;
struct snake *next;
}snake_t;

typedef struct food
{
int row;
int col;
}food_t;

snake_t *snake_head = NULL; //蛇的头指针
snake_t *snake_tail= NULL; //蛇的尾巴
food_t food; //初始化一个食物
int dir; //方向 //捕获的方向
int key; //按键的值

void add_snake_body(); //添加一个蛇的身子函数
void food_init(); //初始化食物
void start_init(); //开始初始化
snake_t* create_snake(int row, int col); //创建一条蛇,row行,col列
int has_snake_body(int row, int col); //判断当前坐标是否有蛇的身子
void map_init(int witdh, int height); //刷新地图
void initscr_func(); //初始化scr函数
void head_delete_snake_body(); //删除蛇身子
void snake_move(); //蛇的移动函数
bool snake_need_init(); //判断蛇是否撞墙,或者咬到自己,需要重开
void turn_abs(int dirction); //取绝对值函数
int food_location(int row,int col); //判断当前坐标是否有食物
bool snake_bite_itself(); //判断蛇是否咬到了自己
void initscr_func(){
initscr();
keypad(stdscr,true);
noecho(); //不回显
}

//贪吃蛇创建
snake_t* create_snake(int row, int col){
snake_head = (snake_t*)malloc(sizeof(snake_t)); //蛇头分配内存
snake_head->row = row;
snake_head->col = col;
snake_head->next = NULL;
snake_tail=snake_head;
add_snake_body(); //添加蛇身体
add_snake_body();
dir=RIGHT; //初始方向为右
return snake_head;

}

void start_init(){
initscr_func();
create_snake(2,3); //创建蛇
food_init(); //初始化食物
map_init(WIDHT,HEIGHT);
refresh(); //刷新窗口

}

void food_init(){
srand(time(NULL));
food.row=rand()%(HEIGHT-2)+1;
food.col=rand()%(WIDHT-1)+1;
}

//判断是否蛇吃到了食物
int has_food(int row,int col){
if(snake_tail->rowrow&&snake_tail->colcol){
return 1;
}
else{
return 0;
}
}

//判断食物位置
int food_location(int row,int col){
if (rowfood.row&&colfood.col){
return 1;
}
else{
return 0;
}

}

//判断蛇是否撞到了自己
bool snake_bite_itself(){
snake_t *p=snake_tail;
snake_t *q=snake_head;
while(q->next!=NULL){
if(p->rowq->row&&p->colq->col){
return true;
}
q=q->next;
}

}
//添加贪吃蛇身体
void add_snake_body(){
snake_t snake_body = (snake_t)malloc(sizeof(snake_t)); //蛇身体分配内存
while (snake_tail->next!=NULL){
snake_tail=snake_tail->next; //找到尾节点
}
snake_body->next = NULL; //蛇身体的下一个节点为空

    //根据按键不同,蛇身体的位置不同
    switch (dir)
    {
        case UP:
             snake_body->row = snake_tail->row - 1;
             snake_body->col = snake_tail->col;
             break;
        case DOWN:
             snake_body->row = snake_tail->row + 1;
             snake_body->col = snake_tail->col;
             break;
        case LEFT:
             snake_body->row = snake_tail->row;
             snake_body->col = snake_tail->col - 1;
             break;
        case RIGHT:
             snake_body->row = snake_tail->row;
             snake_body->col = snake_tail->col + 1;
             break;
        default:
             break;
    }

    snake_tail->next = snake_body;  //尾节点的下一个节点指向蛇身体
    snake_tail=snake_body;  //更新尾节点

}

//delete snake body(head delete)
void head_delete_snake_body(){
snake_t *p;
if(snake_head!=NULL){
p=snake_head; //保存头节点
snake_head=snake_head->next; //头节点指向下一个节点
}
free(p); //释放头节点内存
}
//judge has snake body
int has_snake_body(int row, int col){
snake_t *p = snake_head;
while(p!=NULL){
if(p->rowrow&&p->colcol){
return 1;
}
p = p->next;
}
return 0;
}

bool snake_need_init(){
// if(snake_head->row0||snake_head->col0||snake_head->row20||snake_head->col20){
// return true;
// }
// else
if (snake_tail->rowMIN||snake_tail->colMIN||snake_tail->rowHEIGHT-1||snake_tail->colHEIGHT-1){
return true;
}

else{
    return false;
}

}

//right move
void snake_move(){

//判读是否需要重新开始游戏
if (snake_need_init()==true || snake_bite_itself()==true){
    snake_t *old_sanke_head =NULL;

    //游戏初始前,回收上一次蛇身子
    while(snake_head!=NULL){
    old_sanke_head = snake_head;
    snake_head = snake_head->next;
    free(old_sanke_head); 
    }
    
    create_snake(6,6); //创建蛇
    food.col=2;
    food.row=2;

    map_init(WIDHT,HEIGHT);
}

//不需要重新开始游戏
else{
    add_snake_body(); //添加蛇身体
    //吃到了食物
    if (has_food(food.row,food.col)){
        food_init(); //初始化食物
    }
    
    //没吃到食物
    else{
        head_delete_snake_body(); //删除蛇结点
    }
    
    
    map_init(WIDHT,WIDHT);
    refresh(); //刷新窗口  
}

}
//初始化地图
void map_init(int witdh, int height)
{
int row,col;

move(MIN,MIN); //复位光标

for (row = 0; row < witdh; row++){
    if(row==0){
        for (col = 0; col < height; col++){
            printw("--");

        }
        printw("\n");
    }
           
    else if(row>0&&row<witdh-1){
         for (col = 0; col <= height; col++){
                 if (col==0||col==height)
                 {
                     printw("|");
                 }
                 //判断食物位置,如果有则打印出来
                 else if(food_location(row,col)){
                    printw("##");
                 }

                 else if(has_snake_body(row,col)){
                   printw("[]");
                 }
                 else{
                     printw("  ");
                 }
             }
             printw("\n"); 
    }

    if(row==witdh-1){
         for (col = 0; col < height; col++){
    printw("--");
    }
    printw("\n");
    printw("Make buy guo,Key val:%d  food location:  %d,%d \n",key,food.row,food.col);
    
    }

}
refresh(); //刷新窗口  

}

//取绝对值函数
void turn_abs(int dirction){
if(abs(dir)!=abs(dirction)){
dir=dirction;
}
}

//按键处理函数
void key_handle(){
key = getch();
switch (key)
{
case KEY_UP:
turn_abs(UP);
break;

    case KEY_DOWN: 
    turn_abs(DOWN);
    break;
    
    case KEY_LEFT: 
    turn_abs(LEFT);
    break;

    case KEY_RIGHT: 
    turn_abs(RIGHT);
    break;

    default:
    break;
}

}

void *thread_func_1(void *arg){
while (1){
snake_move();
map_init(WIDHT,HEIGHT); //刷新地图
refresh(); //刷新窗口
usleep(200000); //延时100ms
}

}

void *thread_func_2(void *arg){
while (1){
key_handle(); //处理按键
}

}

//main
int main(int argc, char *argv[])
{
pthread_t thread1,thread2;
start_init();
pthread_create(&thread1,NULL,thread_func_1,NULL);
pthread_create(&thread2,NULL,thread_func_2,NULL);
while (1)
{

}

getch(); //等待用户输入   
endwin(); //关闭窗口

return 0;

}

编译环境,gcc交叉编译,ubantu18.04
使用命令: gcc -Wall -o 你的文件名 你的文件名.c -lcurses -lpthread
运行: ./curses
一两天做的,有点匆忙,不足欢迎批评指正

标签:body,head,int,代码,贪吃蛇,snake,解析,col,row
From: https://www.cnblogs.com/guoguo1728/p/18301380

相关文章

  • Spring的启动流程refresh方法、配置类解析流程@Component、@Configuration、@Import、
    Spring的启动流程概述:核心方法:refresh方法,作用就是实例化spring容器中的所有单例。 3步:生成BeanFactory容器(有beanDefinition类信息和bean对象实例)生成BeanDefinition类信息生成bean对象实例 需要知道的知识:1、先有beanDefinition类信息,再有bean对象。2、在beanDefi......
  • 代码随想录算法训练营第10天|232. 用栈实现队列,225. 用队列实现栈,20. 有效的括号,1047.
    学习任务:Leetcode232.用栈实现队列Leetcode225.用队列实现栈Leetcode20.有效的括号Leetcode1047.删除字符串中的所有相邻重复项Leetcode232.用栈实现队列难度:简单|相关标签:栈、设计、队列题目:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支......
  • 前端开发-- Webpack 代码分割和懒加载技术
    在现代前端开发中,优化应用性能是一个至关重要的任务。Webpack作为一个强大的打包工具,为我们提供了代码分割和懒加载的功能,可以显著提升应用的加载速度和用户体验。本文将深入解析Webpack的代码分割和懒加载技术,帮助开发者更好地理解和应用这些技术。什么是代码分割?代码分割(Co......
  • 深度解析前端开发中的解构赋值
    在现代JavaScript开发中,解构赋值(DestructuringAssignment)是一种非常实用且强大的语法。它可以从数组或对象中提取值,并将其赋值给变量,使代码更加简洁和可读。本文将详细介绍解构赋值的各种用法及其应用场景,帮助你更好地在前端开发中运用这一特性。什么是解构赋值?解构赋值是ES......
  • 深入解析C++中的特殊成员函数:构造函数、析构函数、拷贝构造函数与赋值操作符
    深入解析C++中的特殊成员函数:构造函数、析构函数、拷贝构造函数与赋值操作符在C++编程的浩瀚宇宙中,构造函数、析构函数、拷贝构造函数和赋值操作符是构成对象生命周期和行为的四大基石。它们各自扮演着不可或缺的角色,确保了对象从创建到销毁,从复制到赋值的整个过程既安全又......
  • 手机上也能玩 Python,随时撸代码!
    手机编程软件有很多,大部分都很难使用,操作不灵活,甚至不能安装第三方库。尝试安装了很多Python移动编程软件,发现了很多问题,不是编码效率低就是各种bug。今天,来自一位python编程小哥指导,向大家推荐两款精心挑选的手机编程软件,它们也是非常成熟的手机编程工具。QPythonOHQpyt......
  • SG90舵机介绍与PWM驱动代码
    目录舵机简介SG90参数工作原理舵机接线驱动方式代码示例Servo.hServo.cmain.c360°舵机PWM控制以180°SG90舵机为例学习舵机舵机简介 SG90舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。伺服(Servo)是ServoMechanism一词的......
  • Jmeter 引入自己写的jar包代码
    一、编译调试Java代码在编程工具中将代码进行调试,满足需求后将代码进行打包导出成.jar文件,根据不同的编译工具搜索导出功能即可 示例代码一:packagecom.dffl.gyl;publicclassJmeter_test{publicstaticStringmeter_test(){System.out.println(......
  • HALCON 2D高精密测量项目全流程解析
    1.标定相关的任务–>>解决畸变和坐标系的转换1.1描述和查找标定对象1.2补偿透视和径向变形,径向畸变包括枕形畸变和桶形畸变1.3相机参数(内外参)1.4图像坐标到世界坐标的转换1.5自标定:不用标定板用图像四周包含直线特征进行标定1.6其他标定:一台相机标定、多台相机......
  • 【故障定位】基于多元宇宙算法的主动配电网故障定位方法研究(Matlab代码实现)
    ......