小白入门——“贪吃蛇”的C语言实现(详细)

2023-10-28

C语言实现,编译环境VS2017 附:easyx图形化(文章末尾)

 

 

效果图如下

 

(有一些函数kbhit,getch,在这表示为_kbhit与_getch)//不同编译器原因 注意在Dev等集成开发软件下可能会CE

 

o(* ̄▽ ̄*)o

 

 

 

一、引言

    作为一个小白,相信大家的心情都是一样的,渴望写一个人生的第一个“贪吃蛇”。

    在网上看了基本思路后,如果有一定的知识(链表的相关操作),写出这个应该是不难的。

    1、背景

        打印游戏背景框,以及一些初设的东西,如蛇的初始长度,可以的话可以自己加上出场界面

    2、食物产生

        通过srand,与rand 函数实现随机产生

    3、键盘信号获取

        由 _kbhit(),_getch() ,函数获取

    4、蛇的移动

        分为普通移动与吃到食物的移动

        ps.(许多网上通过刷屏实现,其实可以靠覆盖实现,将原来蛇覆盖用空格,然后重新打印蛇)

二、一些必要函数

    打印这个并不是图形库实现,所以要通过光标跳转实现打印

    注:此方法我也不清楚是从网上查阅资料所得,目前还是小白(ง •_•)ง

    

void gotoxy(int x, int y) 
{
    // 更新光标位置 
	COORD pos;
	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(hOutput, pos);
    // 隐藏光标 
    CONSOLE_CURSOR_INFO cursor;
	cursor.bVisible = FALSE;    
	cursor.dwSize = sizeof(cursor);
	SetConsoleCursorInfo(hOutput, &cursor);
}

    应该是获取窗口句柄

    详细可以参考

    https://baike.baidu.com/item/SetConsoleCursorPosition/575826

    https://baike.baidu.com/item/GetStdHandle/6909878?fr=aladdin

    https://baike.baidu.com/item/coord/4594820?fr=aladdin

三、不多说,看代码

以前写的太烂了 现在重新更新了

/*
@Author: Joke-Lin
@Time: 2020-03-19
@Encoding: GB 2312
@IDE: VS2019
*/

#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<time.h>
#include<conio.h>

#define up 'w'
#define down 's'
#define left 'a'
#define right 'd'

void welcome();               // 开始界面
void Finish();                // 结束界面
void creatgraph();            // 围墙打印
void gotoxy(int x, int y);    // 光标跳转,横为X 0,1,2..
void gotoprint(int x, int y); // 跳转打印
void gotodelete(int x, int y);// 跳转删除
void creatfood();             // 食物产生
int ClickControl();           // 获取键盘信号
int Judge();                  // 游戏结束判断
void MovingBody();            // 蛇的移动 
void Eating();                // 蛇吃到东西后的操作(伸长)
void ChangeBody(int x, int y); // 蛇的坐标变换

/*全局变量 + 预处理:*/
typedef struct Snakes
{
    int x;
    int y;
    struct Snakes* next;
}snake;

snake* head;    // 声明蛇头指针 

// 申明并定义食物 
struct Food
{
    int x;
    int y;
}food;

char name[20];  // 保存用户名 有兴趣可以制作登录系统 
int score = 0;  // 分数 
char click = 1; // 记录敲下的键盘按键 
int speed;      // 速度 其实是延迟的毫秒数 

/************************************************************/

int main()
{
    system("color 0B"); // 设置控制台字体颜色 
    welcome();          // 欢迎界面 
    creatgraph();       // 创建地图 
    creatfood();        // 新建食物 
    // 捕获鼠标按键 ClickControl
    if (ClickControl() == 0) return 0;
    return 0;
}

/**********************************************************/
void welcome()
{
    gotoxy(15, 10);
    printf("/**********************************************/");
    gotoxy(15, 20);
    printf("/**********************************************/");
    gotoxy(20, 13);
    printf("WELCOME TO THE GAME OF RETRO SNAKE");
    gotoxy(14, 16);
    printf("请在英文输入法中操作,反向移动等同于吃到自己,wasd控制p暂停");
    gotoxy(20, 18);
    printf("PLEASE ENTER YOUR NAME:");
    scanf_s("%s", &name, 20);
    system("cls");
}

/**********************************************************/
void creatgraph() {
    int i;
    /*
    注意这里横坐标是每次+2 因为控制台字符宽高比为1:2
    */
    for (i = 0; i < 58; i += 2)
    {
        gotoprint(i, 0);
        gotoprint(i, 26);
    }
    for (i = 1; i < 26; i++)
    {
        gotoprint(0, i);
        gotoprint(56, i);
    }
    gotoxy(63, 10);
    printf("hello %s,Welcome To Play", name);
    gotoxy(63, 15);
    printf("Your Score Is:%d    = ̄ω ̄= ", score);
    gotoxy(63, 20);
    printf("This Game Is Created By JOKER");
    head = (snake*)malloc(sizeof(snake));
    snake* p = (snake*)malloc(sizeof(snake));
    snake* q = (snake*)malloc(sizeof(snake));
    head->x = 16;
    head->y = 15;
    p->x = 16;
    p->y = 16;
    q->x = 16;
    q->y = 17;
    head->next = p;
    p->next = q;
    q->next = NULL;
}
/**********************************************************/
void gotoxy(int x, int y)
{
    // 更新光标位置 
    COORD pos;
    HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(hOutput, pos);
    // 隐藏光标 
    CONSOLE_CURSOR_INFO cursor;
    cursor.bVisible = FALSE;
    cursor.dwSize = sizeof(cursor);
    SetConsoleCursorInfo(hOutput, &cursor);
}

/**********************************************************/
void gotoprint(int x, int y)
{
    gotoxy(x, y);
    printf("■");
}

/**********************************************************/
void gotodelete(int x, int y)
{
    gotoxy(x, y);
    printf("  ");
}

/**********************************************************/
void creatfood()
{
    // 随机产生一个食物 
    bool flag = false;
    while (!flag)
    {
        flag = true;
        srand((int)time(NULL));
        food.y = rand() % (25 - 1 + 1) + 1;
        food.x = rand() % (54 - 2 + 1) + 2;
        if (food.x % 2 != 0)
        {
            food.x = food.x + 1;
        }
        snake* judge = head;
        while (1)  //遍历排除蛇身重复
        {
            if (judge->next == NULL) break;
            if (food.x == judge->x && food.y == judge->y)
            {
                flag = false;
            }
            judge = judge->next;
        }
    }
    gotoxy(food.x, food.y);
    printf("⊙");
}

/**********************************************************/
// 捕获鼠标 游戏主循环 
int ClickControl()
{
    char c;
    while (1)
    {
        if (Judge() == 0) return 0;
        if (_kbhit())
        {
            click = _getch();
        }
        MovingBody();
        Eating();
    }
    return 1;
}

/**********************************************************/
void MovingBody() {
    int x = head->x, y = head->y;
    snake* p = head;
    // 通过先清空后打印实现动画效果
    while (p->next != NULL) {
        p = p->next;
    }
    gotodelete(p->x, p->y); // 消除尾节点
    switch (click)
    {
    case up:
        y -= 1;
        break;
    case down:
        y += 1;
        break;
    case left:
        x -= 2;
        break;
    case right:
        x += 2;
        break;
    default:
        break;
    }
    if (x != head->x || y != head->y) {
        // 改变坐标时更新 暂停游戏停止更新蛇 
        ChangeBody(x, y);
    }
    p = head;
    // 打印蛇头
    gotoprint(p->x, p->y);
    // 蛇速度控制 
    int count = score / 10;
    if (count <= 10) speed = 150;
    else if (count > 10 && count <= 20) speed = 100;
    else if (count > 20 && count <= 40) speed = 50;
    else speed = 10;
    Sleep(speed);
}

/**********************************************************/
// 吃到食物处理 添加一个尾巴 
void Eating()
{
    if (head->x == food.x && head->y == food.y)
    {
        creatfood();
        snake* _new = (snake*)malloc(sizeof(snake));
        snake* p;
        p = head;
        while (1)
        {
            if (p->next == NULL) break;
            p = p->next;
        }
        p->next = _new;
        _new->next = NULL;
        score += 10;
        gotoxy(77, 15);
        printf("%d", score);
    }
}

/**********************************************************/
// 更新蛇体坐标 只需要消除尾结点 然后把新坐标结点置为头结点即可 
void ChangeBody(int x, int y)
{
    snake* p = head;
    while (p->next->next != NULL) {
        p = p->next;
    }
    free(p->next);
    p->next = NULL;
    snake* new_head = (snake*)malloc(sizeof(snake));
    new_head->x = x;
    new_head->y = y;
    new_head->next = head;
    head = new_head;
}

/**********************************************************/
// 判断是否游戏结束 
int Judge()
{
    if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26)
    {
        Finish();
        return 0;
    }
    snake* p = head->next;
    while (1)
    {
        if (p == NULL) break;
        if (head->x == p->x && head->y == p->y)
        {
            Finish();
            return 0;
        }
        p = p->next;
    }
    return 1;
}

/**********************************************************/
void Finish()
{
    system("cls");
    gotoxy(15, 10);
    printf("/**********************************************/");
    gotoxy(15, 20);
    printf("/**********************************************/");
    gotoxy(18, 14);
    printf("GAME   OVER      o(* ̄▽ ̄*)o");
    gotoxy(20, 16);
    printf("Your Score is %d    hiahiahia", score);
    gotoxy(18, 18);
    printf("还不错哦,     继续努力O(∩_∩)O");
    gotoxy(0, 27);
    // 释放空间 
    snake* p = head, * q;
    while (p != NULL) {
        q = p->next;
        free(p);
        p = q;
    }
    system("pause");
}

四、

   easyx 实现:链接地址

 效果如下:

     

觉得好的话欢迎犒劳(ง •_•)ง (要恰饭的嘛嘿嘿)

对评论里的重点问题,我有时间在博客里多加一些

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

小白入门——“贪吃蛇”的C语言实现(详细) 的相关文章

  • python assert用法

    1 assert语句用来声明某个条件是真的 2 如果你非常确信某个你使用的列表中至少有一个元素 而你想要检验这一点 并且在它非真的时候引发一个错误 那么assert语句是应用在这种情形下的理想语句 3 当assert语句失败的时候 会引发一
  • Qt学习笔记——界面文件的使用

    一 界面文件的使用 1 独立的ui文件 使用uic命令把ui文件编译成 h文件 uic xxx ui o xxx h 2 在集成开发环境中使用 1 Qt构造器会把xxx ui文件生成 ui xxx h 文件 且会有一个xxx h xxx c
  • (转载)STM32与LAN9252构建EtherCAT从站

    目录 一 项目简介 EtherCAT及项目简述 LAN9252工作模式 整体开发流程 移植要处理的问题 代码层面的工作 开发中使用的工具 二 SSC的使用 SSC简介和下载 SSC构建协议栈文件和XML 三 LAN9252的XML文件 Et

随机推荐

  • postgresql常用函数>序列函数nextval():设置主键自动增长

    主键一般设置为Integer类型 并且自动增长 起始值为1 增量为1 有两种方法 法一 在建表时 nextval 表名 主键 seq regclass 法二 如果表已经建好 CREATE SEQUENCE 表名 主键 seq START W
  • anaconda jupyter-notebook

    文章目录 仓库镜像配置 新建python 环境 jupyter notebook 仓库镜像配置 conda config add channels https mirrors tuna tsinghua edu cn anaconda pk
  • 程序员必备的25个好网站汇总

    一 技术提升 0 GitHub 程序员托管代码的平台 很多开发者都会在上面找各种各样的开源项目来学习 阿里 腾讯 字节跳动 美团 Google Micosoft等国内外大厂都有自己的Github开源库 1 StackOverflow 一个强
  • 蓝桥杯单片机学习日记4-串口接收与发送,解决串口引脚与按键引脚冲突

    此片文章用于记录蓝桥杯单片机的学习 串口的发送与接收较为简单 主要是字节和字符串的发送与接收 直接上程序 串口初始化 void UartInit void 9600bps 11 0592MHz SCON 0x50 8位数据 可变波特率 AU
  • MySQL数据库是非关系_MySQL(数据库)基础知识、关系型数据库yu非关系型数据库、连接认证...

    什么是数据库 数据库 Database 存储数据的仓库 高效地存储和处理数据的介质 介质主要是两种 磁盘和内存 数据库系统 DBS Database System 是一种虚拟系统 将多种内容关联起来的称呼 DBS DBMS DB DBMS
  • 汇编语言(王爽)第四版学习1

    第一章 机器语言 0 1 简单语句 mov ax bx 汇编语言组成 1 汇编指令 机器码的助记符 有对应的机器码 2 伪指令 没有对应的机器码 由编译器执行 计算机并不执行 3 其他符号 如 等 由编译器识别 没有对应的机器码 存储器 内
  • SpringCloud微服务---Nacos配置中心

    1 Nacos Config 服务配置 1 1 服务配置中心介绍 首先我们来看一下 微服务架构下关于配置文件的一些问题 1 配置文件相对分散 在一个微服务架构下 配置文件会随着微服务的增多变的越来越多 而且分散在各个微服务中 不好统一配置和
  • 007 数据结构_堆——“C”

    前言 本文将会向您介绍关于堆Heap的实现 具体步骤 tips 本文具体步骤的顺序并不是源代码的顺序 typedef int HPDataType typedef struct Heap HPDataType a int size int
  • 04Python爬虫:retrying模块

    代码 结果 None 转载于 https www cnblogs com jumpkin1122 p 11521013 html
  • 勇担重任从不放弃——一个阿里P7的内部求职故事

    Java开发程序员在互联网行业中名声在外 同时也意味着竞争特别激烈 当然 在众多从业者中 并不是每个人都可以经历从Java外包到成为阿里P7这样的成功故事 不过 这个同志通过自己坚定的信仰和勤奋的努力 不仅完成了自己的进步增值 而且分享了成
  • 泰勒图(Taylor Diagrams)和常用模型评价指标小结

    文章内容仅用于自己知识学习和分享 如有侵权 还请联系并删除 一 泰勒图 1 原理 1 1 定义 泰勒图 Taylor diagram 可以简单的理解为一种的可同时展示相关系数 their correlation 中心均方根误差 their
  • win11上的虚拟机安装Ubuntu 16.04和基础环境配置教程

    1 安装 VM 17 win11最好装VM16以后的 2 下载 ubuntu 的iso文件 可以在国内的镜像站下载更快 如下是阿里云的镜像站ubuntu 16 04 网址 https mirrors aliyun com oldubuntu
  • LeetCode 37 把数组排成最小的数

    示例 1 输入 10 2 输出 102 示例 2 输入 3 30 34 5 9 输出 3033459 提示 0 lt nums length lt 100 解题思路 此题求拼接起来的最小数字 本质上是一个排序问题 设数组 nums 中任意两
  • 利用Hu不变矩进行特征提取

    include stdafx h include
  • C# 串口CRC CCITT-FALSE 校验

    串口CRC CCITT FALSE 校验 public static bool CRC16 CCITT FALSE byte byteData C crc 16 CCITT FALSE 带判断校验的 bool flag false usho
  • 大数据从入门到精通(超详细版)之HDFS安装部署 , 跟着部署 , 真的有手就行 !

    前言 嗨 各位小伙伴 恭喜大家学习到这里 不知道关于大数据前面的知识遗忘程度怎么样了 又或者是对大数据后面的知识是否感兴趣 本文是 大数据从入门到精通 超详细版 的一部分 小伙伴们如果对此感谢兴趣的话 推荐大家按照大数据学习路径开始学习哦
  • 什么是link标签?

    什么是link标签 link标签通常放置在一个网页的头部标签head标签内的用于链接外部css文件 链接收藏夹图标 favicon ico 标签最常见的用途是链接外部样式表 外部资源 link实例 链接外部css样式时候link标签的内容结
  • Android性能优化之内存优化

    前言 成为一名优秀的Android开发 需要一份完备的知识体系 在这里 让我们一起成长为自己所想的那样 内存优化可以说是性能优化中最重要的优化点之一 可以说 如果你没有掌握系统的内存优化方案 就不能说你对Android的性能优化有过多的研究
  • OpenHarmony鸿蒙 润和Pegasus套件样例--智能安防

    润和Pegasus套件样例 智能安防 该样例展示OpenHarmony智能安防项目 当温度传感器超过设定值后 或者烟雾传感器检测到烟雾时 会触发蜂鸣器工作 同时通知到HarmonyOS手机上的APP 下载源码 建议将本教程的设备源码下载后
  • 小白入门——“贪吃蛇”的C语言实现(详细)

    C语言实现 编译环境VS 附 easyx图形化 文章末尾 效果图如下 有一些函数kbhit getch 在这表示为 kbhit与 getch 不同编译器原因 注意在Dev等集成开发软件下可能会CE o o 一 引言 作为一个小白 相信大家的