贪吃蛇C语言实现(有源码)

前言

之前学了一点easyx图形库的使用,掌握一些基本用法后就用贪吃蛇来进行实战了,运行视频放在csdn视频那一栏了,之前的烟花也是。

1.头文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<easyx.h>
#include<conio.h>
#include<time.h>
#include<stdlib.h>
#include<stdbool.h>
#define NODE_HIGHT 40
#define NODE_WIDTH 40
typedef enum direction
{up,down,left,right,
}direction;
typedef struct node
{int x, y;
}node;

2.源文件

#include"snack.h"
void Paintgrid()
{for (int x = 0; x < 800; x += NODE_WIDTH)line(x, 0, x, 600);for (int y = 0; y < 600; y += NODE_WIDTH)line(0, y, 800, y);
}
void PaintSnack(node* nodes, int n)
{int left, right, top, bottom;for (int i = 0; i < n; i++){left = nodes[i].x * NODE_WIDTH;top = nodes[i].y * NODE_WIDTH;right = (nodes[i].x + 1) * NODE_WIDTH;bottom = (nodes[i].y + 1) * NODE_WIDTH;solidrectangle(left, top, right, bottom);}
}
node* SnackMove(node* nodes, int length, int direction)
{node x = nodes[length - 1];for (int i = length - 1; i > 0; i--){nodes[i] = nodes[i - 1];}node new_head = nodes[0];if (direction == up)new_head.y--;if (direction == down)new_head.y++;if (direction == left)new_head.x--;if (direction == right)new_head.x++;nodes[0] = new_head;return &x;
}
void playerchoice(direction* dir)
{if (_kbhit())switch (_getch()){case 'A':case'a':if (*dir != left)*dir = left;break;case 'd':case'D':if (*dir != right)*dir = right;break;case 'w':case'W':if (*dir != up)*dir = up;break;case 's':case'S':if (*dir != down)*dir = down;break;}
}
void setfood(node* food,node*nodes,int length,int* flag)
{srand((unsigned)time(NULL));if (*flag == 0){again:food->x = rand() % (800 / NODE_WIDTH);food->y = rand() % (600 / NODE_HIGHT);for (int i = 0; i < length; i++){if (food->x == nodes[i].x && food->y == nodes[i].y)goto again;}*flag= 1;}setfillcolor(YELLOW);solidrectangle(food->x * NODE_WIDTH, food->y * NODE_HIGHT, (food->x + 1) * NODE_WIDTH, (food->y + 1) * NODE_HIGHT);setfillcolor(WHITE);}bool isover(node* nodes,int length)
{if (nodes->x >= 800/NODE_WIDTH || nodes->x < 0 || nodes->y < 0 || nodes->y>=600/NODE_HIGHT)return true;for (int i = 1; i < length; i++)if (nodes->x == nodes[i].x && nodes->y == nodes[i].y)return true;return FALSE;
}void reset(node* nodes, int* length, direction* dir,int*flag){nodes[0] = { 5,7 };nodes[1] = { 4,7 };nodes[2] = { 3,7 };nodes[3] = {2,7};nodes[4] = {1,7};*length = 5;*dir = right;*flag = 0;}int main(){srand((unsigned)time(NULL));initgraph(800, 600);setbkcolor(RGB(164, 225, 202));direction dir = right;int  length = 5;node nodes[100] = { {5,7},{4,7},{3,7},{2,7},{1,7} };//从蛇头到蛇尾node food = { 0 };int flag = 0;while (1){cleardevice();Paintgrid();//初始化表格setfood(&food, nodes, length, &flag);PaintSnack(nodes, length);Sleep(500);playerchoice(&dir);node* end = SnackMove(nodes, length, dir);if (nodes[0].x == food.x && food.y == nodes[0].y){length++;nodes[length - 1].x = end->x;nodes[length - 1].y = end->y;flag = 0;}if (isover(nodes, length)){reset(nodes, &length, &dir,&flag);}}closegraph();return 0;}

3.解析

0.创建环境

我使用的是vs编译环境和easyx图形库,貌似easyx也支持Dev,具体的下载方法可以去吧站搜索,easyx的使用在吧站也有相关 教程,包括vs的下载都有很详细的视频教程,所以就不再赘述了。

我们由于要用到随机数所以使用了<time.h><stdlib.h>头文件

关于随机数的使用若是不了解可以看看这篇博客

C语言rand函数,srand函数,time函数实现随机数,及猜数字小游戏-CSDN博客

图形库的使用需要<easyx.h>头文件

第一行的宏定义想必用vs的都知道,用来避免报错的

两个结构体是用来记录蛇的移动方向和坐标的。

#define _CRT_SECURE_NO_WARNINGS 1
#include<easyx.h>
#include<conio.h>
#include<time.h>
#include<stdlib.h>
#include<stdbool.h>
#define NODE_HIGHT 40
#define NODE_WIDTH 40
typedef enum direction
{
    up,
    down,
    left,
    right,
}direction;
typedef struct node
{
    int x, y;
}node;

我们只要知道以下几点就可以

1.把地图画出来

void Paintgrid()
{
    for (int x = 0; x < 800; x += NODE_WIDTH)
        line(x, 0, x, 600);
    for (int y = 0; y < 600; y += NODE_WIDTH)
        line(0, y, 800, y);
}

2.初始化并记录蛇的每个节点的坐标

void PaintSnack(node* nodes, int n)
{
    int left, right, top, bottom;
    for (int i = 0; i < n; i++)
    {
        left = nodes[i].x * NODE_WIDTH;
        top = nodes[i].y * NODE_WIDTH;
        right = (nodes[i].x + 1) * NODE_WIDTH;
        bottom = (nodes[i].y + 1) * NODE_WIDTH;
        solidrectangle(left, top, right, bottom);
    }
}

3.随机产生食物

void setfood(node* food,node*nodes,int length,int* flag)
{
    srand((unsigned)time(NULL));
    if (*flag == 0)
    {
    again:
        food->x = rand() % (800 / NODE_WIDTH);
        food->y = rand() % (600 / NODE_HIGHT);
        for (int i = 0; i < length; i++)
        {
            if (food->x == nodes[i].x && food->y == nodes[i].y)
                goto again;
        }
        *flag= 1;
    }
    setfillcolor(YELLOW);
    solidrectangle(food->x * NODE_WIDTH, food->y * NODE_HIGHT, (food->x + 1) * NODE_WIDTH, (food->y + 1) * NODE_HIGHT);
    setfillcolor(WHITE);
 }

4.蛇移动坐标随之变化

node* SnackMove(node* nodes, int length, int direction)
{
    node x = nodes[length - 1];
    for (int i = length - 1; i > 0; i--)
    {
        nodes[i] = nodes[i - 1];
    }
    node new_head = nodes[0];
    if (direction == up)
        new_head.y--;
    if (direction == down)
        new_head.y++;
    if (direction == left)
        new_head.x--;
    if (direction == right)
        new_head.x++;
    nodes[0] = new_head;
    return &x;
}
void playerchoice(direction* dir)
{
    if (_kbhit())
        switch (_getch())
        {
        case 'A':
        case'a':
            if (*dir != left)
                *dir = left;
            break;
        case 'd':
        case'D':
            if (*dir != right)
                *dir = right;
            break;
        case 'w':
        case'W':
            if (*dir != up)
                *dir = up;
            break;
        case 's':
        case'S':
            if (*dir != down)
                *dir = down;
            break;
        }
}

5.蛇吃到食物会长长

//主函数中

 if (nodes[0].x == food.x && food.y == nodes[0].y)
 {
     length++;
     nodes[length - 1].x = end->x;
     nodes[length - 1].y = end->y;
     flag = 0;
 }

6.碰到边界或自己会死,并设置游戏重开功能

 bool isover(node* nodes,int length)
{
     if (nodes->x >= 800/NODE_WIDTH || nodes->x < 0 || nodes->y < 0 || nodes->y>=600/NODE_HIGHT)
         return true;
     for (int i = 1; i < length; i++)
         if (nodes->x == nodes[i].x && nodes->y == nodes[i].y)
             return true;
     return FALSE;
}

//主函数中

 if (isover(nodes, length))
 {
     reset(nodes, &length, &dir,&flag);
 }

7.主函数调用函数

     srand((unsigned)time(NULL));
     initgraph(800, 600);
     setbkcolor(RGB(164, 225, 202));
     direction dir = right;
     int  length = 5;
     node nodes[100] = { {5,7},{4,7},{3,7},{2,7},{1,7} };//从蛇头到蛇尾
     node food = { 0 };
     int flag = 0;
     while (1)
     {
         cleardevice();
         Paintgrid();//初始化表格

         setfood(&food, nodes, length, &flag);
         PaintSnack(nodes, length);
         Sleep(500);
         playerchoice(&dir);
         node* end = SnackMove(nodes, length, dir);
         if (nodes[0].x == food.x && food.y == nodes[0].y)
         {
             length++;
             nodes[length - 1].x = end->x;
             nodes[length - 1].y = end->y;
             flag = 0;
         }
         if (isover(nodes, length))
         {
             reset(nodes, &length, &dir,&flag);
         }
     }
     closegraph();

总结

一直想写个小游戏玩玩,现在也算是小小的玩了一把,可惜最近要复习,没有时间学图形库了,不然真希望继续做点东西。最后祝愿还没考的同学考出好成绩,考完的寒假快乐,工作的早点放假,

若是觉得这篇博客对你有帮助就点个赞支持一下博主吧,感谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/319283.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读|冷冻电镜】DISCA: High-throughput cryo-ET structural pattern mining

论文题目 High-throughput cryo-ET structural pattern mining by unsupervised deep iterative subtomogram clustering 摘要 现有的结构排序算法的吞吐量低&#xff0c;或者由于依赖于可用模板和手动标签而固有地受到限制。本文提出了一种高吞吐量的、无需模板和标签的深度…

Apache HTTPD 多后缀解析漏洞详解

Apache HTTPD 多后缀解析漏洞 1.查看python版本 这里python版本很重要&#xff0c;因为版本过低可能会导致后面的结果运行不成功 这里我就遇到了因为版本过低而执行不了docker-compose up -d的情况 查看python版本 cd /usr/bin ls -al python* 当版本过低时安装高版本的 …

AI:106-基于卷积神经网络的遥感图像地物分类

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…

9. C++ GDB调试原理(简洁版)

背景 GDB支持断点、单步执行、打印变量、观察变量、查看寄存器、查看堆栈等调试手段。 断点 断点是我们在调试中经常用的一个功能&#xff0c;我们在指定位置设置断点之后&#xff0c;程序运行到该位置将会暂停&#xff0c;这个时候我们就可以对程序进行更多的操作&#xff…

IM即时通讯聊天社交APP源码+h5群聊+红包转账+朋友圈

支持文字、表情、图片、语音、单聊、群聊、已读未读、消息群发、内嵌外链、签到、等完备的 IM 功能。 单聊:快速实现私信单聊,具备图片、语音、动态表情、小视频、红包、通话等各种通信能力,消息历史记录支持漫游。 群聊:快速实现群组聊天,单人禁言、全员禁言、群红包、…

Kali Linux实现UEFI和传统BIOS(Legacy)引导启动

默认Kali linux安装会根据当前启动的引导模式进行安装 例&#xff1a;以UEFI引导启动安装程序&#xff0c;安装后仅能在UEFI引导模式下进入系统 安装Kali系统 这边基于VirtualBox虚拟机镜像实战操作 首先创建一个Kali虚拟机 这里需要注意&#xff0c;把启动 EFI (只针对某些操…

一起玩儿物联网人工智能小车(ESP32)——25. 利用超声波传感器测量距离

摘要&#xff1a;本文介绍如何利用超声波传感器测量障碍物的距离 测量距离是智能小车经常要用到的功能&#xff0c;今天就来介绍一个最常用的测量距离的传感器——超声波传感器。 超声波传感器的测距原理是利用超声波发射器向某个方向发射超声波&#xff0c;与此同时&#xff…

计算机网络(2)

计算机网络&#xff08;2&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 计算机网络和因特网&#xff08;2&#xff09;分组交换网中的时延、丢包和吞吐量时延丢包吞吐量总结 协议层次及其服务模型模型类型OSI模型分析TCP/IP模型分析 追溯历史 小程一言 我…

C++线程池的原理(画图)及简单实现+例子(加深理解)

1.为什么线程池会出现&#xff0c;解决什么问题&#xff1f; C线程池&#xff08;ThreadPool&#xff09;的出现主要是为了解决以下几个问题&#xff1a; 1.性能&#xff1a;创建和销毁线程都是相对昂贵的操作&#xff0c;特别是在高并发场景下&#xff0c;频繁地创建和销毁线…

当hashCode相同时,equals是否也相同?

在Java中&#xff0c;理解对象的这两个基本方法—hashCode和equals对于编码是至关重要的&#xff0c;尤其是在处理集合类如HashMap和HashSet时。然而&#xff0c;一个常见的误解是&#xff0c;如果两个对象有相同的哈希码&#xff08;hashCode&#xff09;&#xff0c;那么它们…

数据分析概述

数据分析概述 在当今数字化的时代&#xff0c;数据已经成为我们周围不可忽视的存在。从商业领域到医疗行业&#xff0c;从科学研究到政府治理&#xff0c;数据的涌现为我们提供了前所未有的信息资源。然而&#xff0c;要从这个庞大的信息海洋中获取有意义的见解并做出明智的决策…

虚幻引擎实时音频采集

Part1前言 虚幻引擎其实对实时音频的采集支持得非常好。不过由于对音频概念的学习&#xff0c;还是花了一些时间进行研究。本文主要介绍如何基于虚幻引擎采集实时麦克风的音频数据。 Part2音频采样率 在虚幻引擎中&#xff0c;我没有找到动态修改音频采样率的方法。下面的方法设…