当前位置: 首页 > news >正文

C语言·贪吃蛇游戏(下)

        上节我们将要完成贪吃蛇游戏所需的前置知识都学完了,那么这节我们就开始动手写代码了

1. 程序规划

        首先我们应该规划好我们的代码文件,设置3个文件:snack.h 用来声明游戏中实现各种功能的函数,snack.c 用来实现函数,test.c 用来测试和运行这个游戏

                        

        然后我们将游戏的大概流程在test.c文件中写出来,因为我们会用到宽字符,所以要记得适配本地中文环境

                

2. 游戏数据结构设计

2.1 蛇身数据结构(链表)

        我们设计用链表来表示蛇身,链表的每个节点中需要存这节蛇身的坐标 x、y 和下一节点的地址,然后我们给蛇身节点结构体类型改个好写一点的名字

        链表的基础知识:数据结构·单链表-CSDN博客

                

2.2 维护整个游戏的结构体

        我们还要创建一个结构体,用来存放当前游戏的种种状态

        

        

        

3. 游戏开始前的初始化

        游戏的开始前初始化都在GameStart()函数中实现,那么我们着手开始写这个函数。

        首先,我们要先创建维护贪吃蛇游戏的结构体,将它的信息传到GameStart()中去,在snack.h中声明这函数,然后再在snack.c中实现它

        

        我们把这个函数种封装的功能先都展示出来,之后就不重复展示了

3.1 控制台信息设置及光标隐藏

        控制台为了美观我们设置成100列30行的,名字就叫做贪吃蛇

        运行以下发现控制台设置好了,并且光标也很好的隐藏了起来

3.2 打印欢迎信息

        WelcomeToGame()函数内部的大部分东西我们上节其实已经写过了,下面就展示一下

3.3 打印地图

        地图大小我们上节已经说过了,要设计一个27行58列的棋盘,然后我们用一个宏把每块墙写出来,方便写打印语句

                        

        在打印墙的时候上边界和下边界挨着打印就行,左边界和右边界的时候要在每次打印之前把光标都定一下位

        展示打印地图的代码:

                

3.4 初始化蛇

        蛇身我们采用链表的结构进行管理。最开始,我们展示5个蛇身,初始的蛇尾巴从(24,5)的位置开始,向右5节之后是蛇头,这里我们采用头插的方式依次创建节点并加入蛇身中。

        同时定义蛇尾初始位置的宏和蛇身形状的宏

                        ​​​​​​​        

        最后将贪吃蛇的所有状态进行初始化

3.5 创建食物

        创建食物时不能随意创建的,要满足一下四点要求:

        1. 食物是随机出现的,就是说坐标是随机的

        2. 坐标必须在墙内    (x:2~54  y:1~25)

        3. 坐标不能在蛇身上

        4. 横坐标必须是偶数

        创建的食物其实就相当于蛇的一段身体,所以我们之间用蛇身节点的结构体类型保存食物的()(位置)信息就行,然后食物的创建要满足上面的要求,最后要注意的是,我们想要生成真随机数,就不要忘了在程序开始时给rand()函数种种子srand()

        ​​​​​​​        ​​​​​​​        ​​​​​​​        

4. 游戏的运行过程

        下面我们来完成GameRun()函数,首先将这个函数中要实现的功能理出来

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

4.1 打印帮助信息

        这个没啥好说的,定好位打印就行

        ​​​​​​​        

4.2 按键逻辑

        写一个do···while循环,当游戏状态是OK的情况下就一直循环,持续检测按键的状态,同时在这里把帮助信息也写一下。我们检测按键的时候写一个宏 KEY_PRESS  内容跟上节的一样,这里我就不展示了,最后我会把所有代码都贴出来的

        ​​​​​​​        

        pause()函数

                        

        

4.3 蛇的移动(走一步)

        这里我们的策略是在蛇头前面再创建一个节点,用来判断蛇要走的下一个位置是否有食物,这里要注意,当蛇向下走的时候不能直接向上走,向右走的时候不能像左走,以此类推。蛇的下一步的位置信息先全都存在新创建的节点中,等待接入蛇身

        

        ​​​​​​​        

4.3.1 蛇头下一步是食物

        ​​​​​​​            

4.3.2 蛇头下一步不是食物

        ​​​​​​​   ​​​​​​​        ​​​​​​​

4.3.3 检测撞墙

        撞墙简单,判断一下蛇头横纵坐标有没有跟墙重合就行

                

4.3.4 检测撞自己

        同理,蛇头的横纵坐标没有跟自身重合就行

5. 游戏结束善后的工作

        善后工作其实就是打印一下蛇的死亡原因,然后把,malloc的内存都释放掉

             ​​​​​​​

6. 复玩功能

        复玩功能我们之前已经写过很多次了,像扫雷中就有很详细的介绍,这里我就简单写一下了

        扫雷请参考:函数·扫雷游戏-CSDN博客

        ​​​​​​​        ​​​​​​​

7. 完整代码

        snack.h

#include<locale.h>
#include<stdlib.h>
#include<stdio.h>
#include<Windows.h>
#include<stdbool.h>
#include<time.h>#define WALL L'□'
#define BODY 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,//玩家按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 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 InitSnake(pSnake ps);
//创建食物
void CreateFood(pSnake ps);//游戏的运行过程
void GameRun(pSnake ps);//打印帮助信息
void PrintHelpInfo();
//蛇的移动
void SnakeMove(pSnake ps);
//蛇头下一步要走的坐标是否是食物
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);

        snack.c

#include"snack.h"//修改光标位置
void SetPos(int x, int y)
{//获得设备句柄HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//根据句柄设置光标位置COORD pos = { x,y };SetConsoleCursorPosition(handle, pos);
}
//打印欢迎信息
void WelcomeToGame()
{//欢迎界面SetPos(38, 12);printf("欢迎来到贪吃蛇小游戏\n");SetPos(40, 20);system("pause");system("cls");//清空屏幕//操作介绍界面SetPos(20, 10);printf("用 ↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n");SetPos(37, 12);printf("加速能得到更高的分数\n");SetPos(40, 20);system("pause");system("cls");//清空屏幕}//打印地图
void CreateMap()
{int i = 0;//上边界SetPos(0, 0);for (i = 0; i <= 56; i += 2){wprintf(L"%lc", WALL);}//下边界SetPos(0, 26);for (i = 0; i <= 56; i += 2){wprintf(L"%lc", WALL);}//左边界for (int i = 1; i <= 25; i++){SetPos(0, i);wprintf(L"%lc", WALL);}//右边界for (int i = 1; i <= 25; i++){SetPos(56, i);wprintf(L"%lc", WALL);}
}//初始化蛇
void InitSnake(pSnake ps)
{pSnakeNode cur = NULL;int i = 0;for (i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL)//节点创建失败{perror("InitSnake():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", BODY);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, y = 0;again:do{//当x不是偶数就再生成一次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();//初始化蛇InitSnake(ps);//创建食物CreateFood(ps);
}void PrintHelpInfo()
{SetPos(62,15);printf("1. 不能撞墙,不能咬到自己");SetPos(62, 16);printf("2. 用 ↑ ↓ ← → 控制蛇的移动"); SetPos(62, 17);printf("3. F3为加速,F4为减速");}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;}else{//不是食物return 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", BODY);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 pcur = ps->pSnake;while (pcur->next->next){//这里捎带着把新蛇身打印SetPos(pcur->x, pcur->y);wprintf(L"%lc", BODY);pcur = pcur->next;}//先将尾节点的位置打印空白字符SetPos(pcur->next->x, pcur->next->y);printf("  ");//打印两个空格//最后freefree(pcur->next);pcur->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)
{//打印帮助信息PrintHelpInfo();do{//当前的分数情况SetPos(62, 10);printf("总分:%d", ps->Score);SetPos(62, 11);printf("食物的分值:%02d", ps->FoodWeight);//检测按键//上、下、左、右、ESC、空格、F3、F4if (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_F3)){//睡眠时间不能无限减小,控制一下if (ps->SleepTime >= 80){//加速,休眠时间变短ps->SleepTime -= 30;//每个食物得分增加ps->FoodWeight += 2;}}else if (KEY_PRESS(VK_F4)){//睡眠时间不能无限减小,控制一下if (ps->FoodWeight > 2){//减速,休眠时间变长ps->SleepTime += 30;//每个食物得分减少ps->FoodWeight -= 2;}}//睡眠一下Sleep(ps->SleepTime);//蛇的移动SnakeMove(ps);} while (ps->status == OK);
}//游戏结束善后的善后工作
void GameEnd(pSnake ps)
{SetPos(20, 11);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 = ps->pSnake;while (cur){del = cur;cur = cur->next;free(del);}ps->pSnake = NULL;//释放食物节点free(ps->pFood);ps->pFood = NULL;}

        test.c

#include"snack.h"void test()
{int ch;//getchar()返回的是整形ASCII码值do{//创建贪吃蛇游戏Snake snake = { 0 };GameStart(&snake);//游戏开始前的初始化GameRun(&snake);//游戏的运行过程GameEnd(&snake);//游戏结束善后的工作SetPos(25, 15);printf("再来一局吗?(Y/N):>");ch = getchar();getchar();//清理缓冲区的\n} while (ch == 'Y');
}int main()
{srand((unsigned int)time(NULL));//修改适配本地中文环境setlocale(LC_ALL, "");//贪吃蛇游戏的测试test();//控制程序退出结语的位置SetPos(0, 27);return 0;
}

8. 结语

        那么到此,贪吃蛇游戏就写好了,当然,这个游戏的功能还有美观度还有待各位共同开发,如果说想要给这个游戏图形化一下,大家可以去 easyX 看看EasyX Graphics Library for C++,把这个库下载下来应该就能在VS上用了

        同时,我们的C语言讲解就告一段落了,下一阶段我将着手数据结构的相关知识

相关文章:

C语言·贪吃蛇游戏(下)

上节我们将要完成贪吃蛇游戏所需的前置知识都学完了&#xff0c;那么这节我们就开始动手写代码了 1. 程序规划 首先我们应该规划好我们的代码文件&#xff0c;设置3个文件&#xff1a;snack.h 用来声明游戏中实现各种功能的函数&#xff0c;snack.c 用来实现函数&#xff0c;t…...

Flask 入门2:路由

1. 前言 在上一节中&#xff0c;我们使用到了静态路由&#xff0c;即一个路由规则对应一个 URL。而在实际应用中&#xff0c;更多使用的则是动态路由&#xff0c;它的 URL是可变的。 2. 定义一个很常见的路由地址 app.route(/user/<username>) def user(username):ret…...

【C++】 C++入门— 基于范围的 for 循环

C 基于范围的for循环1 使用样例2 使用条件3 完善措施 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;下一篇文章见&#xff01;&#xff01;&#xff01; 基于范围的for循环 1 使用样例 使用for循环遍历数组&#xff0c;我们通常这么写&#xff1a; …...

C++——析构函数

C——析构函数 什么是析构函数 析构函数是C中的一个特殊的成员函数&#xff0c;它在对象生命周期结束时被自动调用&#xff0c;用于执行对象销毁前的清理工作。析构函数特别重要&#xff0c;尤其是在涉及动态分配的资源&#xff08;如内存、文件句柄、网络连接等&#xff09;…...

Vue3学习记录(二)--- 组合式API之计算属性和侦听器

一、计算属性 1、简介 ​ 计算属性computed()&#xff0c;用于根据依赖的响应式变量的变化&#xff0c;进行自动的计算&#xff0c;并返回计算后的结果。当依赖的响应式变量发生变化时&#xff0c;computed()会自动进行重新计算&#xff0c;并返回最新的计算结果。如果依赖的…...

react-virtualized实现行元素不等高的虚拟列表滚动

前言&#xff1a; 当一个页面中需要接受接口返回的全部数据进行页面渲染时间&#xff0c;如果数据量比较庞大&#xff0c;前端在渲染dom的过程中需要花费时间&#xff0c;造成页面经常出现卡顿现象。 需求&#xff1a;通过虚拟加载&#xff0c;优化页面渲染速度 优点&#xff1…...

Linux系统各目录作用

/etc文件系统 /etc 目录包含各种系统配置文件&#xff0c;下面说明其中的一些。其他的你应该知道它们属于哪个程序&#xff0c;并阅读该程序的m a n页。许多网络配置文件也在/etc 中。 1. /etc/rc或/etc/rc.d或/etc/rc?.d 启动、或改变运行级时运行的脚本或脚本的目录。 2. /…...

嵌入式系统学习(一)

嵌入式现状&#xff08;UP经历&#xff09;&#xff1a; 大厂的招聘要求&#xff1a; 技术栈总结&#xff1a; 产品拆解网站&#xff1a; 52audio 方案查询网站iotku,我爱方案网&#xff0c; 主要元器件类型&#xff1a;...

重写Sylar基于协程的服务器(3、协程模块的设计)

重写Sylar基于协程的服务器&#xff08;3、协程模块的设计&#xff09; 重写Sylar基于协程的服务器系列&#xff1a; 重写Sylar基于协程的服务器&#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar&#xff09; 重写Sylar基于协程的服务器&#xff08;1、日志模…...

Linux之系统安全与应用续章

目录 一. PAM认证 1.2 初识PAM 1.2.1 PAM及其作用 1.2.2 PAM认证原理 1.2.3 PAM认证的构成 1.2.4 PAM 认证类型 1.2.5 PAM 控制类型 二. limit 三. GRUB加密 /etc/grub.d目录 四. 暴力破解密码 五. 网络扫描--NMAP 六. 总结 一. PAM认证 1.2 初识PAM PAM是Linux系…...

《HTML 简易速速上手小册》第7章:HTML 多媒体与嵌入内容(2024 最新版)

文章目录 7.1 在HTML中嵌入视频和音频7.1.1 基础知识7.1.2 案例 1&#xff1a;嵌入视频文件7.1.3 案例 2&#xff1a;嵌入音频文件7.1.4 案例 3&#xff1a;创建一个视频和音频混合的播放列表 7.2 使用 <iframe> 嵌入外部内容7.2.1 基础知识7.2.2 案例 1&#xff1a;嵌入…...

【CSS】移动端适配

移动端适配怎么做&#xff1f; 适配的目的是在屏幕大小不同的终端设备拥有统一的界面&#xff0c;让拥有更大屏幕的终端展示更多的内容。 meta viewport (视口) 移动端初始视口的大小默认是980px&#xff0c;因为世界上绝大多数PC网页的版心宽度为980px &#xff0c;如果网页…...

DFS剪枝算法经典题目-挑选

4954. 挑选 - AcWing题库 给定一个包含 n 个正整数 a1,a2,…,an的集合。 集合中可能存在数值相同的元素。 请你从集合中挑选一些元素&#xff0c;要求同时满足以下所有条件&#xff1a; 被选中元素不少于 2 个。所有被选中元素之和不小于 l 且不大于 r。所有被选中元素之中最大…...

考研经验总结——考试期间

文章目录 一、订房二、看考场三、休息四、考前带宾馆的书五、安全 一、订房 我刚刚看了看&#xff0c;是9.10号订的酒店。你们可以提前向学长学姐打听你的考场在哪个学校&#xff08;徐州的考生&#xff0c;考省外的学校是在矿大考试&#xff0c;考省内的学校是在江师大&#…...

vue3 源码解析(6)— lifecycle 生命周期的实现

前言 对于 vue3 的生命周期&#xff0c;我们经常性会去疑问&#xff0c;生命周期有哪些呢&#xff0c;它是怎么去实现的&#xff0c; 又是什么时候调用的。 vue3 生命周期有哪些 下面这个表格列出了所有选项式api生命周期钩子和组合式api生命周期钩子&#xff0c;以及他们的…...

three.js CSS2DRenderer、CSS2DObject渲染HTML标签

有空的老铁关注一下我的抖音&#xff1a; 效果&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red;position: relative;"><…...

SECS/GEM300和半导体e84控制器

SECS&#xff08;SEMI EQUIPMENT COMMUNICATIONS STANDARD 2&#xff09;半导体设备通讯标准 GEM&#xff08;Generic Equipment Model&#xff09;定义了Fab中各个场景下设备行为及其所使用SECS消息。 GEM300也称为300mm标准&#xff0c;FAB是12寸设备的处理作业规范。主要包…...

k8s二进制及负载均衡集群部署详解

目录 常见部署方式 二进制部署流程 环境准备 操作系统初始化配置 关闭防火墙 配置SELinux 关闭SWAP 根据规划设置主机名 在master添加hosts&#xff0c;便于主机名解析 调整内核参数 配置时间同步 部署docker引擎 在所有node节点部署docker引擎 部署etcd集群 签发…...

【Django开发】0到1开发美多商城项目第3篇:用户注册业务实现(附代码,已分享)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论django商城项目相关知识。项目利用Django框架开发一套前后端不分离的商城项目&#xff08;4.0版本&#xff09;含代码和文档。功能包括前后端不分离&#xff0c;方便SEO。采用Django Jinja2模板引擎 Vue.js实现前后端…...

免费的ppt网站分享

前言 相信大学生们深有体会&#xff0c;对于学校而言&#xff0c;好像是任何活动都需要我们做ppt&#xff0c;当你拿着自己辛苦做的ppt去展示现场的时候&#xff0c;你看到别人的ppt比你的还好&#xff0c;此时心情就是毙&#xff0c;当你知道人家不过是仅仅的1个小时不到就完成…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

ZYNQ学习记录FPGA(一)ZYNQ简介

一、知识准备 1.一些术语,缩写和概念&#xff1a; 1&#xff09;ZYNQ全称&#xff1a;ZYNQ7000 All Pgrammable SoC 2&#xff09;SoC:system on chips(片上系统)&#xff0c;对比集成电路的SoB&#xff08;system on board&#xff09; 3&#xff09;ARM&#xff1a;处理器…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...

云原生安全实战:API网关Envoy的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口&#xff0c;负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...