犀哥教你用C写贪吃蛇

2023-05-16

一,涉及知识点:

    结构体链表,动态分配内存,键盘输入检测,设置光标。

二,实现逻辑

    1,可以设置光标,就能实现制定位置打印制定符号。
    2,涉及一个结构体,包含两个元素坐标元素和一个结构体指针。
    3,结构体串联形成链表,遍历获取成员坐标,打印符号得到蛇身。
    4,不断的加头,去尾,重新遍历坐标,再打印形成蛇的移动。
    5,食物产生的位置判定,不能越界,也不能与蛇身体重合。
    6,蛇的转向判定,一条规则,不允许倒退。
    7,转向的实现,跟行进方向决定新的关节坐标(当前头的上下左右)
    8,死亡检测,是否头节点坐标是否与墙壁重合,是否与身体其他关节重合。
    9,加速减速,设置刷新休眠时间实现。

pragma comment(lib, “user32.lib”)
上面这句代码不加的话用VS的开发人员命令提示编译时不通过
这里写图片描述

具体这个东西是干嘛的,参考下面这位仁兄的博客:
//http://blog.csdn.net/jiary5201314/article/details/9011203

源码,拿走不谢

#pragma comment(lib, "user32.lib")  //http://blog.csdn.net/jiary5201314/article/details/9011203
#include<stdio.h>
#include<time.h>
#include<windows.h>
#include<stdlib.h>

#define U 1  //上
#define D 2  //下
#define L 3  //左
#define R 4  //右

typedef struct Node
{
    int x;
    int y;
    struct Node *next;
} Node;

Node *head,*food,*index;  //蛇头,食物,游标
void snake_create();      //生成蛇
void wall_create();       //生成墙壁
void Pos(int, int);       //设置光标位置
void game_description();  //游戏说明界面
void snake_move();        //蛇的移动
void game_control();      //游戏控制
void start_game();        //开始游戏
void pause_game();        //暂停游戏
void exit_game();         //退出游戏
void isbitself();         //吃到自己
void isbitwall();         //撞到墙壁
void spawn_food();        //生成食物
int score = 0,            //得分
    add = 10,             //加分
    death_type,           //死亡类型
    direction = R,        //前进方向
    sleeptime = 200;      //正常速度

//设置光标位置
void Pos(int x, int y)
{
    COORD pos;
    HANDLE hOutput;
    pos.X = x;
    pos.Y = y;
    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOutput, pos);
}

//游戏说明界面
void game_description()
{
    Pos(40, 14);
    printf("欢迎进入贪吃蛇游戏!\n\n");
    system("pause");
    system("color 5e");
    system("cls");
    Pos(10, 14);
    printf("您将通过键盘控制蛇的移动: 上↑  下↓  左 ←  右→  加速F1  减速F2  暂停space  退出Esc");
    Pos(10, 15);
    printf("吃到食物身体会变长\n");
    Pos(10, 16);
    printf("撞到身体或墙壁游戏都会结束\n");
    system("pause");
    system("cls");
    wall_create();     //生成墙壁
    snake_create();    //初始化蛇
    spawn_food();      //生成食物
}

//生成墙壁
void wall_create()
{
    int i;
    for (i = 0; i<58; i += 2)//打印上下边框
    {
        Pos(i, 0);
        printf("▓");
        Pos(i, 26);
        printf("▓");
    }
    for (i = 1; i<26; i++)//打印左右边框
    {
        Pos(0, i);
        printf("▓");
        Pos(56, i);
        printf("▓");
    }
    Pos(70, 10);
    printf("当前分数"); 
}

//初始化蛇
void snake_create()
{
    Node *tail;
    int i;
    tail = (Node*)malloc(sizeof(Node));   //从蛇尾开始,头插法,以x,y设定开始的位置
    tail->x = 24;
    tail->y = 5;
    tail->next = NULL;
    for (i = 1; i <= 4; i++)
    {
        head = (Node*)malloc(sizeof(Node));
        head->next = tail;
        head->x = 24 + 2 * i;
        head->y =5;
        tail = head;
    }
    while (tail != NULL)  //从头到为,输出蛇身
    {
        Pos(tail->x, tail->y);
        printf("◆");
        tail = tail->next;
    }
}


//生成食物
void spawn_food()
{
    if (food != NULL)   //避免食物重复生成
    {
        return;
    }
    Node* food_1 = (Node*)malloc(sizeof(Node));
    food_1->x = rand() % 52 + 2;
    food_1->y = rand() % 24 + 1;     //确保食物在蛇的活动范围以内
    while ((food_1->x) % 2 != 0)
    {
        food_1->x = rand() % 50 + 2;
    }
    index = head;
    while (index != NULL)
    {
        if (food_1->x == index->x && food_1->y == index->y)   //如果过食物位置与蛇身重合,就重新生成。
        {
            free(food_1);  //重新生成前记得释放旧的
            spawn_food();
            break;        //不然就相当于递归,下面的代码会导致报错
        }
        index = index->next;
    }
    food = food_1;
    Pos(food->x, food->y);   
    printf("●");
}

//蛇的移动
void snake_move()
{
    isbitwall();
    Node *nexthead = (Node*)malloc(sizeof(Node));
    switch (direction)
    {
    case U:
        nexthead->x = head->x;
        nexthead->y = head->y - 1;   //注意  坐标轴的原点是在命令框的左上角
        break;
    case D:
        nexthead->x = head->x;
        nexthead->y = head->y + 1;
        break;
    case L:
        nexthead->x = head->x - 2;   //我们使用的符号是占三个字节,需要用到两个字宽才能正常显示
        nexthead->y = head->y;
        break;
    case R:
        nexthead->x = head->x + 2;
        nexthead->y = head->y;
        break;
    }
    nexthead->next = head;
    head = nexthead;
    index = head;
    isbitself();
    if (nexthead->x == food->x  && nexthead->y == food->y)   //如果吃到食物就增加一节
    {
        while (index != NULL)
        {
            Pos(index->x,index->y);
            printf("◆");
            index = index->next;
        }
        score += add;
        free(food);
        food = NULL;   //如果吃到食物记得将食物指针赋空   
        spawn_food();
    }
    else   //否则就正常前进
    {
        while (index->next->next != NULL)
        {
            Pos(index->x, index->y);
            printf("◆");
            index = index->next;    
        }   
        Pos(index->next->x, index->next->y);
        printf(" ");    //前进的方式就是不断在头部增加关节,然后删除尾部。
        free(index->next);
        index->next = NULL;
    }
}

//蛇的控制
void game_control()
{
    Pos(64, 15);
    printf("不能穿墙,不能咬到自己\n");
    Pos(64, 16);
    printf("用↑ ↓ ← → 控制蛇的移动.");
    Pos(64, 17);
    printf("F1 为加速,F2 为减速\n");
    Pos(64, 18);
    printf("ESC :退出游戏    space:暂停游戏.");
    direction = R;
    while (1)
    {
        Pos(64, 10);
        printf("得分:%d ", score);
        Pos(64, 11);
        printf("当前食物分值:%d分", add);
        if (GetAsyncKeyState(VK_UP) && direction != D)
        {
            direction = U;
        }
        else if (GetAsyncKeyState(VK_DOWN) && direction != U)
        {
            direction = D;
        }
        else if (GetAsyncKeyState(VK_RIGHT) && direction != L)
        {
            direction = R;
        }
        else if (GetAsyncKeyState(VK_LEFT) && direction != R)
        {
            direction = L;
        }
        else if (GetAsyncKeyState(VK_ESCAPE))
        {
            death_type = 3;
            break;
        }
        else if (GetAsyncKeyState(VK_SPACE))
        {
            pause_game();
        }
        else if (GetAsyncKeyState(VK_F1))   //加速
        {
            if (sleeptime > 50)
            {
                sleeptime -= 30;
                add = add + 2;
                if (sleeptime == 320)
                {
                    add = 2;//防止减到1之后再加回来有错
                }
            }
        }
        else if (GetAsyncKeyState(VK_F2))   //减速
        {
            if (sleeptime<350)
            {
                sleeptime = sleeptime + 30;
                add = add - 2;
                if (sleeptime == 350)
                {
                    add = 1; //保证最低分为1
                }
            }
        }
        Sleep(sleeptime);
        snake_move();
    }
}

//暂停
void pause_game()
{
    while(1)
    {
        Sleep(300);
        if (GetAsyncKeyState(VK_SPACE))
        {
            break;
        }
    }
}

//是否撞墙
void isbitwall()
{
    if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)
    {
        death_type = 1;
        exit_game();
    }
}

//是否吃到自己
void isbitself()
{
    Node *self = head->next;  //拿除头部以外的关节跟头关节对比
    while (self != NULL)
    {
        if (self->x == head->x && self->y == head->y)  
        {
            death_type = 2;
            exit_game();
        }
        self = self->next;
    }
}

//退出游戏
void exit_game()
{
    system("cls");
    Pos(24, 12);
    if (death_type == 1)
    {
        printf("对不起,您撞到墙了。游戏结束.");
    }
    else if (death_type == 2)
    {
        printf("对不起,您咬到自己了。游戏结束.");
    }
    else if (death_type == 3)
    {
        printf("您已经结束了游戏。");
    }
    Pos(24, 13);
    printf("您的得分是%d\n", score);
    getchar();
    exit(0);
}

//主函数
void main()
{
    system("title ★★贪吃蛇★★");   //改变命令窗口名字
    system("mode con cols=100 lines=30");   //调整命令窗口的大小
    game_description();
    game_control();
    system("pause");
}

运行效果截图:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

犀哥教你用C写贪吃蛇 的相关文章

随机推荐

  • Hadoop安装和配置

    1 安装Hadoop 注意 xff1a 安装JDK类似 xff0c 解压后配置环境变量 1 0 Hadoop下载地址 xff1a https archive apache org dist hadoop common hadoop 2 7
  • 机器学习(1)机器学习的范围

    机器学习的范围包括但是不局限与如下 xff1a 机器学习跟模式识别 xff0c 统计学习 xff0c 数据挖掘 xff0c 计算机视觉 xff0c 语音识别 xff0c 自然语言处理等领域有着很深的联系 从范围上来说 xff0c 机器学习跟
  • Tesseract-OCR-v5.0中文识别,训练自定义字库,提高图片的识别效果

    1 xff0c 下载安装Tesseract OCR 安装 xff0c 链接地址Index of tesseract 2 xff0c 安装成功 tesseract v 注意 xff1a 安装后 xff0c 要添加系统环境变量 3 xff0c
  • 4x4矩阵按键应用详解

    一 简介 4x4矩阵按键是单片机外部设备中所使用的排布类似于矩阵的按键组 显然矩阵按键的使用要比独立按键要复杂一些 xff0c 编程也要复杂一些 xff0c 但可以单片机IO资源 4x4矩阵按键即分为4组列线 xff0c 4组行线 xff0
  • Hyper-V 显卡直通

    创建虚拟机后 xff0c 打开虚拟机设置 gt 禁用检查点功能 使用WIN11镜像来部署安装Hyper V虚拟机系统 xff0c 进入桌面后关闭虚拟机 物理机以管理员运行Windows PowerShell 输入以下命令 vm 61 34
  • mwan3 负载平衡 多PPPOE账号 LTE WIFI 负载均衡

    OpenWrt上的MWAN3可以支持多根网线或者多个PPPOE账号的同时拨号使用和负载均衡 并且还可以通过Ping方式来检测中断线路并自动屏蔽中断线路 mwan3的详细介绍 https openwrt org docs guide user
  • websocket实现页面数据实时加载(Springboot+vue)

    在这里先提供两种思路 要实现页面数据的实时加载有两种方式 xff0c 第一种是长轮询的方式 要么是后台长轮询 xff0c 检测到数据变化时 xff0c 通知websocket你该更新一下数据了 要么是前台长轮询 xff0c 每隔一段时间发起
  • 【Cocos2d-x】使用贝塞尔曲线(Bezier)实现精灵抛物线运动

    Cocos2d x中的贝塞尔曲线 在Cocos2d x中贝塞尔曲线运动的封装类为CCBezierTo和CCBezierBy 这两个Action都需要传入一个参数ccBezierConfig xff0c 这是一个结构体 xff0c 这个结构体
  • 常用开源Jabber(XMPP) IM服务器介绍

    转自 xff1a http www kfdoc com Article kaifayuyan Java 200909 283 html 1 Openfire Wildfire 3 x 授权 GPL or 商用 操作系统平台 xff1a 所有
  • socket缓冲区大小设置

    系统提供的socket缓冲区大小为8K xff0c 你可以将之设置为64K xff0c 尤其在传输实时视频时 设置发送和接收缓冲区 int rcvbuf int rcvbufsize 61 sizeof int if getsockopt
  • CentOS 7 安装PostgreSQL

    原文 xff1a https blog csdn net wlwlwlwl015 article details 53256358 下载 在postgresql的官方即可找到源码文件目录 xff0c 地址如下 xff1a https www
  • 使用sudo apt-get update总是报错软件包缓存文件损坏

    命中 1 http cn archive ubuntu com ubuntu xenial InRelease 获取 2 http cn archive ubuntu com ubuntu xenial updates InRelease
  • CSP202112 第四题 磁盘文件操作(C++ 25分)

    使用了tuple xff0c 但这么使用的话 xff0c 只能符合前25 的数据 xff0c 即m小于等于10000 include lt bits stdc 43 43 h gt include lt tuple gt using nam
  • 安装Rust(Windows 10 与 CentOS7)

    注 xff1a 安装及下载需要科学上网 官网下载地址 xff1a Install Rust Rust Programming Language Window安装Rust 0 前提条件 安装C 43 43 编译工具 xff08 如下图所示 x
  • 【辅助驾驶】透视变换、仿射变换(包含鸟瞰图、俯视图、正视图)[3]——汽车全景环视系统

    一 效果 4个不同方向的相机 xff0c 将其鸟瞰变化后 xff0c 进行拼接 xff0c 得到车辆及周围区域的鸟瞰视角图 二 处理流程 1 相机的标定和图片校正 xff1b 2 图像拼接 xff1b 3 拼接缝消除 xff1b 4 移植到
  • 玩客云刷Armbian详细教程

    网上放出了很多关于玩客云的刷机玩法 xff0c 有电视盒子 复古游戏机 Armbian Linux操作系统搭建自己的私有云 可玩性还是很高的 xff0c 而且价格还便宜就入手了一台 下面记录一下我的玩客云折腾之旅 xff0c 机器刷了Arm
  • 原创分析| 入门或者转行音视频,应该要怎么做?

    要不要从事音视频开发 这一两年因为该死的疫情 xff0c 让短视频 超高清视频和实时音视频反而成为需求风口 我的看法当然是觉得音视频这个行业还可以 xff0c 而且从我自己的观察来看 xff0c 做音视频的现在普遍年龄都在 30 43 了
  • while(a<b<c)怎么理解?

    首先计算a lt b 是否成立 xff0c 再计算1 lt c或 0 lt c span class hljs keyword int span main span class hljs keyword int span a 61 span
  • C判断字符输入是否为指定字符串

    题目要求 xff1a 设定口令为 yulingxi 请求输入 xff0c 如果错误循环输入直至正确为止 1 xff0c 偷懒用strcmp 的做法 xff1a span class hljs preprocessor define CRT
  • 犀哥教你用C写贪吃蛇

    一 xff0c 涉及知识点 xff1a 结构体链表 xff0c 动态分配内存 xff0c 键盘输入检测 xff0c 设置光标 二 xff0c 实现逻辑 1 xff0c 可以设置光标 xff0c 就能实现制定位置打印制定符号 2 xff0c