C语言——实践小游戏(贪吃蛇)代码版

大家好久不见,我是残念我回来了,希望在你看完之后,能对你有所帮助,有什么不足请指正!共同学习交流
本文由:残念ing原创CSDN首发,如需要转载请通知
个人主页:残念ing-CSDN博客,欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:残念ing 的C语言系列专栏——CSDN博客

头文件和主函数的声明

snake.h

#pragma once#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<stdbool.h>
#include<locale.h>
#define WALL  L'■'
#define SNAKE L'●'
#define HEADSNAKE L'○'
#define FOOD L'★'
#define POS_X 24
#define POS_Y 5
#define KEY_PRESS(VK) ((GetAsyncKeyState(VK)&0x1)? 1:0)
//游戏状态
enum GAME_STATUS
{OK = 1,//正常运行ESC,//正常退出KILL_BY_WALL,//撞墙了KILL_BY_SELF//撞到自己了
};//⽅向
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};//蛇身结点的定义
typedef struct SnakeNode
{int x;int y;struct SnakeNode* next;
}SnakeNode,* pSnakeNode;//typedef struct SnakeNode* pSnakeNode;//蛇
typedef struct Snake
{pSnakeNode pSnake;//维护整条蛇的指针,指向蛇头pSnakeNode pFood;//指向食物的指针int Score;//当前累计的分数int FoodWeight;//一个食物的分数int SleepTime;//整条蛇的睡眠时间,休眠的时间越短,蛇的速度越快,休眠的时间越长,蛇的速度越慢enum GAME_STATUS status;//游戏当前的状态enum DIRECTION dir;//蛇当前走的方向
}Snake,* pSnake;//定位控制台光标位置
void setpos(int x, int y);
//游戏准备
void GameStart(pSnake ps);//打印欢迎界面
void WelcomeToGame();
//绘制地图
void CreateMap();
//初始化贪吃蛇
void InintSnake(pSnake ps);
//创建食物
void CreateFood(pSnake ps);//运行整个游戏的逻辑
void GameRun(pSnake ps);//玩游戏的过程//打印帮助信息
void printfHelpInfo();//每次的移动
void SnakeMove(pSnake ps);//判断蛇头下一步要走的位置是不是食物 是返回1,不是返回0;
int NextIsFood(pSnake ps, pSnakeNode pnext);//是食物就吃
void EatFood(pSnake ps, pSnakeNode pnext);
//不是食物
void NotEatFood(pSnake ps, pSnakeNode pnext);//检测撞墙
void KillByWall(pSnake ps);
//检测撞到自己
void KillBySelf(pSnake ps);//游戏结束的善后
void GameEnd(pSnake ps);//善后工作

主函数的详细实现

snake.c

#define _CRT_SECURE_NO_WARNINGS 1#include"snake.h"//将光标位置设置到指定的位置
void setpos(int x, int y)
{//获取句柄HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//设置光标的坐标COORD tmp = { x,y };SetConsoleCursorPosition(handle, tmp);
}void WelcomeToGame()
{setpos(40,10);printf("欢迎来到贪吃蛇小游戏!!!");setpos(43, 20);system("pause");//请按任意键继续进行下一步system("cls");//清屏setpos(10, 10);printf("请用 ↑	↓	←	→	分别来控制蛇的移动,SHIFT为加速,CTRL为减速");setpos(40, 12);printf("注意:加速将会使你得到更多分");setpos(43, 20);system("pause");//请按任意键继续进行下一步system("cls");//清屏
}//打印墙
void CreateMap()
{//上setpos(0, 0);for (int i = 0; i <= 56; i += 2){wprintf(L"%lc", WALL);}//下setpos(0, 26);for (int i = 0; i <= 56; i += 2){wprintf(L"%lc", WALL);}//左for (int i = 0; i <=25; i++){ setpos(0, i);wprintf(L"%lc", WALL);}//右for (int i = 0; i <=25; i++){setpos(56, i);wprintf(L"%lc", WALL);}}//初始化蛇
void InintSnake(pSnake ps)
{pSnakeNode cur=NULL;for (int i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InintSnake():malloc");return;}cur->x = POS_X +  2 * i;cur->y = POS_Y;cur->next = NULL;//头插if (ps->pSnake == NULL){ps->pSnake = cur;}else{cur->next = ps->pSnake;ps->pSnake = cur;}}//打印蛇cur = ps->pSnake;while (cur){setpos(cur->x, cur->y);wprintf(L"%lc", SNAKE);cur = cur->next;}//贪吃蛇的基本属性初始化ps->dir = RIGHT;ps->FoodWeight = 10;ps->pFood = NULL;ps->Score = 0;ps->SleepTime = 200;ps->status = OK;
}//创建食物
void CreateFood(pSnake ps)
{int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 24 + 1;} while (x % 2 != 0);//坐标和蛇的身体的每个节点的做坐标比较pSnakeNode cur = ps->pSnake;while (cur){if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}//创建食物pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc()");return;}pFood->x = x;pFood->y = y;ps->pFood = pFood;setpos(x, y);wprintf(L"%lc", FOOD);}void GameStart(pSnake ps)
{//设置控制台的信息,窗口大小,窗口名system("mode con cols=100 lines=30");//设置窗口的长和宽system("title 贪吃蛇");//设置窗口名//隐藏关标HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息CursorInfo.bVisible = false;//隐藏控制台光标SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标的状态//打印欢迎信息WelcomeToGame();//绘制地图CreateMap();//初始化蛇InintSnake(ps);//创建食物CreateFood(ps);
}void printfHelpInfo()
{setpos(63, 15);printf("注意:不能穿墙,不能咬到自己");setpos(63, 16);printf("用↑↓← →分别来控制蛇的移动");setpos(63, 17);printf("SHIFT为加速,CTRL为减速");setpos(63, 18);printf("Esc为退出游戏,space为暂停游戏");
}void pause()
{while (1){Sleep(100);if (KEY_PRESS(VK_SPACE)){break;}}
}int NextIsFood(pSnake ps, pSnakeNode pnext)
{if (ps->pFood->x == pnext->x && ps->pFood->y == pnext->y){return 1;}elsereturn 0;
}void EatFood(pSnake ps, pSnakeNode pnext)
{pnext->next = ps->pSnake;ps->pSnake = pnext;//打印蛇pSnakeNode cur = ps->pSnake;while (cur){setpos(cur->x, cur->y);wprintf(L"%lc", SNAKE);cur = cur->next;}ps->Score += ps->FoodWeight;//释放旧的食物free(ps->pFood);//新建食物CreateFood(ps);
}void NotEatFood(pSnake ps, pSnakeNode pnext)
{//头插法pnext->next = ps->pSnake;ps->pSnake = pnext;//释放尾结点pSnakeNode cur = ps->pSnake;while (cur->next->next){setpos(cur->x, cur->y);wprintf(L"%lc", SNAKE);cur = cur->next;}//将尾节点的位置打印成空白字符setpos(cur->next->x, cur->next->y);printf("  ");free(cur->next);cur->next = NULL;//易错
}void KillByWall(pSnake ps)
{if (ps->pSnake->x == 0 || ps->pSnake->x == 56 || ps->pSnake->y == 0 || ps->pSnake->y == 26){ps->status = KILL_BY_WALL;}
}void KillBySelf(pSnake ps)
{pSnakeNode cur = ps->pSnake->next;while (cur){if (cur->x == ps->pSnake->x && cur->y == ps->pSnake->y){ps->status = KILL_BY_SELF; return;}cur = cur->next;}}void SnakeMove(pSnake ps)
{pSnakeNode pnext = (pSnakeNode)malloc(sizeof(SnakeNode));if (pnext == NULL){perror("SnakeMove()::malloc()");return;}pnext->next = NULL; switch (ps->dir){case UP:pnext->x = ps->pSnake->x;pnext->y = ps->pSnake->y - 1;break;case DOWN:pnext->x = ps->pSnake->x;pnext->y = ps->pSnake->y + 1;break;case LEFT:pnext->x = ps->pSnake->x - 2;pnext->y = ps->pSnake->y;break;case RIGHT:pnext->x = ps->pSnake->x + 2;pnext->y = ps->pSnake->y;break;}//下一个坐标是不是食物if (NextIsFood(ps, pnext)){//是食物就吃EatFood(ps, pnext);}else{//不是食物就走NotEatFood(ps, pnext);}//检测撞墙KillByWall(ps);//检测撞到自己KillBySelf(ps);
}void GameRun(pSnake ps)
{//打印帮助信息printfHelpInfo();//检测按键do{//当前的分数情况setpos(63,10);printf("总得分:%5d 每个食物: %02d",ps->Score,ps->FoodWeight);//检查按键// 上 下 左 右 ESC 空格 shift Ctrlif (KEY_PRESS(VK_UP) && ps->dir != DOWN){ps->dir = UP;}else if (KEY_PRESS(VK_DOWN) && ps->dir != UP){ps->dir = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->dir != RIGHT){ps->dir = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->dir != LEFT){ps->dir = RIGHT;}else if (KEY_PRESS(VK_ESCAPE)){ps->status = ESC;break;}else if (KEY_PRESS(VK_SPACE)){//游戏要暂定pause();//暂定和回复暂定}else if(KEY_PRESS(VK_RSHIFT)){if (ps->SleepTime >= 80){ps->SleepTime -= 30;ps->FoodWeight += 2;}}else if (KEY_PRESS(VK_RCONTROL)){if (ps->FoodWeight > 2){ps->SleepTime += 30;ps->FoodWeight -= 2;}}//睡眠一下Sleep(ps->SleepTime);//走一步SnakeMove(ps);} while (ps->status==OK);
}void GameEnd(pSnake ps)
{setpos(17, 15);switch (ps->status){case ESC:printf("退出游戏\n");break;case KILL_BY_WALL:printf("撞到墙了!!!!,游戏结束\n");break;case KILL_BY_SELF:printf("咬到自己了!!!!,游戏结束\n");break;}//释放贪吃蛇的链表资源pSnakeNode  cur = ps->pSnake;pSnakeNode del = NULL;while (cur){del = cur;cur = cur->next;free(del);}free(ps->pFood);ps = NULL;
}

关于代码的测试

snake_test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "snake.h"
void test()
{int ret = 0;do{ret = 0;Snake snake = { 0 };GameStart(&snake);//游戏开始前的初始化GameRun(&snake);//玩游戏的过程GameEnd(&snake);//游戏的善后Sleep(800);system("cls");//清屏setpos(40, 15);printf("要再来一次吗???(Y/N)");ret=getchar();getchar();//清理\n} while (ret=='Y'||ret=='y');
}
int main()
{//修该适合本地中文环境setlocale(LC_ALL, "");test();//贪吃蛇的测试return 0;
}

这是详细代码,之后会给大家详细解答。

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

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

相关文章

DS数模-Mathorcup妈妈杯C题思路

2024Mathorcup数学建模挑战赛&#xff08;妈妈杯&#xff09;C题保姆级分析完整思路代码数据教学 C题题目&#xff1a;物流网络分拣中心货量预测及人员排班 接下来我们将按照题目总体分析-背景分析-各小问分析的形式来 总体分析&#xff1a;题目要求我们处理的是一个关于物流…

国芯科技(C*Core)车规MCU产品选型与应用

一、MCU市场概述 MCU&#xff08;Micro Controller Unit&#xff09;即微控制器&#xff0c;俗称单片机&#xff0c;是把 CPU 的规格与频率做适当缩减&#xff0c;并将ROM、RAM、A/D转换、各式I/O接口以及Timer等功能整合在单一芯片上&#xff0c;形成芯片级的计算机。 根据…

【应用】SpringBoot-自动配置原理

前言 本文简要介绍SpringBoot的自动配置原理。 本文讲述的SpringBoot版本为&#xff1a;3.1.2。 前置知识 在看原理介绍之前&#xff0c;需要知道Import注解的作用&#xff1a; 可以导入Configuration注解的配置类、声明Bean注解的bean方法&#xff1b;可以导入ImportSele…

Prototype 原型

意图 用原型实例指定创建对象的种类&#xff0c;并且通过复制这些原型创建新的对象。 结构 Prototype声明一个复制自身的接口。ConcretePrototype实现一个复制自身的操作。Client让一个原型复制自身从而创建一个新的对象。 适用性 当一个系统应该独立于他的产品创建、构成和…

oceanbase一键安装

安装文档&#xff1a;https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000000642554 软件下载 https://www.oceanbase.com/softwarecenter 安装obd yum install -y yum-utils yum-config-manager --add-repo https://mirrors.aliyun.com/oceanbase/OceanBa…

《剑指 Offer》专项突破版 - 面试题 107 : 矩阵中的距离(C++ 实现)

题目链接&#xff1a;矩阵中的距离 题目&#xff1a; 输入一个由 0、1 组成的矩阵 M&#xff0c;请输出一个大小相同的矩阵 D&#xff0c;矩阵 D 中的每个格子是矩阵 M 中对应格子离最近的 0 的距离。水平或竖直方向相邻的两个格子的距离为 1。假设矩阵 M 中至少有一个 0。 …

网络原理(应用层、传输层)

文章目录 一、应用层1.1 自定义协议1.2 通用协议XMLJSONprotobuf 1.3 DNS 域名解析系统 二、传输层2.1 UDP协议2.2 TCP协议协议端格式及解析可靠性机制确认应答超时重传连接管理&#xff08;三次握手&#xff0c;四次挥手&#xff09;流量控制拥塞控制 效率机制滑动窗口延迟应答…

【进阶六】Python实现SDVRPTW常见求解算法——差分进化算法(DE)

基于python语言&#xff0c;采用经典差分进化算法&#xff08;DE&#xff09;对 带硬时间窗的需求拆分车辆路径规划问题&#xff08;SDVRPTW&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整2.1 需求拆分2.2 需求拆分后的服务时长取值问题 3. 求解结果4. 代码…

Cloudshark数据包分析功能介绍

什么是CloudShark CloudShark是一种基于Web的数据包分析平台&#xff0c;可以认为是wiresshark的cloud版本&#xff0c;但是其在威胁分析等方面比Wireshark的功能强大&#xff0c;如下是他们的主要区别。 Wireshark VS Cloudshark Wireshark定位是一款本地开源的网络数据包分…

算法学习 | day40/60 单词拆分/多重背包/背包问题总结

一、题目打卡 1.1 单词拆分 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:bool findInVector(vector<string> &w, string& s){for(auto & it : w){if(it s) return true;}return false;}bool wordBreak(string …

构建第一个ArkTS用的资源分类与访问

应用开发过程中&#xff0c;经常需要用到颜色、字体、间距、图片等资源&#xff0c;在不同的设备或配置中&#xff0c;这些资源的值可能不同。 应用资源&#xff1a;借助资源文件能力&#xff0c;开发者在应用中自定义资源&#xff0c;自行管理这些资源在不同的设备或配置中的表…

每日一题---OJ题: 相交链表

片头 嗨! 小伙伴们,大家好! 今天我们来一起学习这道OJ题---相交链表,准备好了吗? Ready Go! ! ! emmm,看这道题好像不怎么难,我们一起画图分析分析 上图中,A链表有5个结点,分别为 a1,a2,c1,c2,c3 ; B链表有6个结点,分别为 b1,b2,b3,c1,c2,c3 ; A链表和B链表在c1结点相交 …

RabbitMQ 消息重复消费问题

RabbitMQ 消息重复消费问题 解决消息重复消费问题 解决消息重复消费问题 需要在消费端考虑消息的幂等性&#xff1a; 幂等性&#xff1a;对一个接口的多次调用和一次调用得到的结果都是一样的 使用数据库的唯一越苏保证幂等性。

vue表格操作列,按钮太多显示... 点击后悬浮显示全部按钮

效果: 分析原理: 一共就三步,仔细看看很简单,位置要加对,代码结构下边有demo 代码结构demo: <el-table-columnlabel"操作"align"center"fixed"right"show-overflow-tooltip><template slot-scope"scope"><el-buttonsi…

java 将 json 数据转为 java 中的对象

一、准备 json 数据 {"name": "mike","age": 17,"gender": 1,"subject": ["math","english"] }二、对应的java对象 package com.demo.controller;import lombok.Data; import java.util.List;Data pu…

LightM-UNet:Mamba 辅助的轻量级 UNet 用于医学图像分割

摘要 https://arxiv.org/pdf/2403.05246.pdf UNet及其变体在医学图像分割中得到了广泛应用。然而&#xff0c;这些模型&#xff0c;特别是基于Transformer架构的模型&#xff0c;由于参数众多和计算负载大&#xff0c;使得它们不适合用于移动健康应用。最近&#xff0c;以Mamb…

SpringMVC原理及工作流程

组件 SpringMVC的原理主要基于它的各个组件之间的相互协作交互&#xff0c;从而实现了Web请求的接收&#xff0c;处理和响应。 它的组件有如下几个&#xff1a; DispatcherServlet前端控制器 HandlerMapping处理器映射器 Controller处理器 ModelAndView ViewResolver视图…

数字乡村可视化大数据-DIY拖拽式设计

DIY拖拽式大数据自由设计万村乐可视化大数据V1.0 随着万村乐数字乡村系统的广泛使用&#xff0c;我们也接收到了客户的真实反馈&#xff0c;最终在公司的决定下&#xff0c;我们推出了全新的可视化大数据平台V1.0版本&#xff0c;全新的可视化平台是一个通过拖拽配置生成可视化…

【测试篇】Selenium + Java环境搭建

文章目录 Selenium Java环境搭建配置系统环境变量PATH验证环境是否搭建成功常见问题&解决办法 Selenium Java环境搭建 Java版本最低要求为8&#xff0c;这里默认大家都下载好了Java。&#x1f606; 下载chrome浏览器&#xff08;点我下载&#xff09; 观察chrome版本。…

【Java核心技术】第3章 Java的基本程序设计结构

1 数据类型 Java一共有8种数据类型&#xff1a; 4种整型 类型存储需求int4字节short2字节long8字节byte1字节 2种浮点型 类型存储需求float4字节double8字节 1种字符型 1种布尔型 2 变量声明 2.1 局部类型推断 如果可以从变量的初始值推断变量类型&#xff0c;只需要使用…