c语言项目-贪吃蛇项目2-游戏的设计与分析

文章目录

  • 前言
  • 游戏的设计与分析
    • 地图:
      • 这里简述一下c语言的国际化特性相关的知识
        • <locale.h> 本地化头文件
        • 类项
        • setlocale函数
      • 上面我们讲到需要打印★,●,□三个宽字符
        • 找到这三个字符
        • 打印的方式有两种:
      • 控制台屏幕的长宽特性:
    • 游戏代码实现:
      • 项目结构:
    • 总结:


前言

前面我们已经将项目所需的背景知识,大体讲解完了,接下来开始对游戏进行设计与分析


提示:以下是本篇文章正文内容,下面案例可供参考

游戏的设计与分析

地图:

我们要设计一个这样的地图:(本项目的设计并不是完全自主的从无到有的设置,而是学习已经写好的项目的思想与设计)
在这里插入图片描述

 在此地图中,□ 代表地图边界,★代表食物,●代表蛇
●,★,□三个符号均是宽字符,占两个字节,显示大小是普通字符的两倍

这里简述一下c语言的国际化特性相关的知识

c语言一开始是由美国人发明的,其使用的当然就是英语,其采用的编码方式是ASCII编码
,只使用了一个字节-准确地说是只使用了7个比特位,共128个字符,
但是对于一些其他非英语的国家如,德国,法国等其使用的字母,如法语中字母有注音符号,就无法用ASCII码表示,
为此,一些欧洲国家就决定用字节中闲置的最高位来引入新的符号,这样就可以用一个字节编码256个字符,
但是这样有个问题即不同国家的编码的字符是不一样的,比如希腊的与法国的就不同,
总体来说,不同国家在0-127表示字符是一样的,在128-256表示的字符是不同的。
在亚洲国家中所使用的字符就更多了,比如在中国,使用的汉字就达到10万左右,一个字节只能表示的256个字符,这是远远不够的,所以需要用多个字节来表示一个字符,比如简体中文常见的编码方式GB2312:即用两个字节表示一个汉字,所以理论上可以表示256*256 == 65536   个汉字!

那么c语言中除了字符集具有国际化特性之外,还有哪些成分具有国际化特性?
c语言的国际化特性,不体现在关键字与操作符,与c语言语法相关的各种符号(*,->等)。

还有数字量的格式
货币量的格式
日期与时间的表示形式

c语言标准不断被国际化支持,体现在一些标准头文件与库函数之中,
 比如:加入宽字符类型 wchar_t类型和宽字符的输入输出函数<locale.h>头文件中
其中提供了程序员针对特定地区调整程序行为(所谓调整程序行为,即在中国此程序该怎样执行,在其他地区此程序该怎样执行)的函数,
<locale.h> 本地化头文件
locale提供的函数用于调整程序在不同地区的表现,正规一点:即帮助程序实现国际化与本地化,以适应不同地区的语言环境要求。
locale提供的函数可以控制c标准库中根据不同地区会产生不一样行为的部分。
因为c标准库中的是函数或者宏,即locale提供的函数可以控制这些函数与宏。
类项

不同地区(语言环境不同),有许多方面不同,比如字符,时间与日期格式,货币的表现形式等,
这些可以调整的部分称其为类项,下面的这些宏针对各自的类项:
在这里插入图片描述

setlocale函数

在这里插入图片描述

 本函数的功能是通过调整C语言模式以改变程序对我们指定类项的操作
本函数的第一个参数是要调整的类项(适配到本地环境),第二个参数是c语言模式
c标准中为这个函数提供了两种参数:一种是:标准模式,对应的参数:" C"
                                第二种是  本地模式:" "    
                                标准模式即英语环境下的c语言版本
                                本地模式即适配当前所在地区的c语言版本
 可以用setlocale函数返回当前C语言的模式,只需要将函数第二个参数置为NULL即可

我们就以打印宽字符为例:

#include<stdio.h>
#include<locale.h>  //setlocale函数包含在locale.h文件中
int main() {
	//我们将当前模式先设置成标准模式
	char* ret = setlocale(LC_ALL, "C");
	wchar_t a = L'张';  //wchar_t是宽字符的数据类型,汉字是宽字符的一种
	                    //在宽字符之前需要加上L,否则会被当做窄字符处理
	printf("%s\n", ret);
	wprintf(L"%c\n", a);//在格式串之前也要加上L
	return 0;
}

在这里插入图片描述
此时的结果:C代表C语言当前模式是标准模式,?代表无法解析字符是什么,这是此时程序执行完的结果。
下面我们改变当前C语言的模式,修改成本地模式:

#include<stdio.h>
#include<locale.h>  //setlocale函数包含在locale.h文件中
int main() {
	//我们将当前模式先设置成标准模式
	//char* ret = setlocale(LC_ALL, "C");
	char* ret = setlocale(LC_ALL, "");
	wchar_t a = L'张';  //wchar_t是宽字符的数据类型
	                    //在宽字符之前需要加上L,否则会被当做窄字符处理
	printf("%s\n", ret);
	wprintf(L"%c\n", a);//在格式串之前也要加上L
	return 0;
}

在这里插入图片描述
此时的结果表明当前的模式是本地在中国,输出宽字符‘张’。

如果我们函数的第一个参数不是LC-ALL全部类项,而是某一类项呢?,比如LC_TIME,那我们还能打印宽字符吗?

#include<stdio.h>
#include<locale.h>  //setlocale函数包含在locale.h文件中
int main() {
	//改变此时的类项
	char* ret = setlocale(LC_TIME, ""); 
	wchar_t a = L'张';  //wchar_t是宽字符的数据类型
	                    //在宽字符之前需要加上L,以做标记
	printf("%s\n", ret);
	wprintf(L"%c\n", a);
	return 0;
}

在这里插入图片描述
结果显示不能,也就是说此时函数只能调整程序对时间格式的操作,而不能改变其他!

上面我们讲到需要打印★,●,□三个宽字符

找到这三个字符

但是键盘上并没有这三个字符,我们需要用搜狗输入法输入
下载搜狗输入法后:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
就完成了。

打印的方式有两种:

第一种方式就是我们上面所讲的通过locale.h文件,setlocale函数调整C语言当前模式来使得程序能够打印宽字符
第二种方式就是直接通过printf函数,直接用字符串的形式打印:

#include<stdio.h>
#include<locale.h>  //setlocale函数包含在locale.h文件中
int main() {
	printf("□\n");
	printf("ab\n");
	return 0;
}

在这里插入图片描述

控制台屏幕的长宽特性:

#include<windows.h>
int main() {
	system("mode con cols=30 lines=30");
	return 0;
}

在这里插入图片描述
问: 为什么行与高均为30,则屏幕会是这样?
是因为X轴的一个单位是一个字节!
而Y轴的一个单位是两个字节!

在这里插入图片描述

游戏代码实现:

我们要设计一个27行,58列的地图:

项目结构:

在这里插入图片描述
Snake.h:

#define KEY_PRESS(vkey) ((GetAsyncKeyState(vkey)&1)?1:0) 

#include<Windows.h>
#include<stdio.h>
#include<locale.h>
#include<time.h>
#include<stdbool.h>
#define POS_X 26
#define POS_Y 10
//关于游戏的状态
enum STATUS {
  OK = 1,      //开始
  END_NORMAL,  //正常结束
  KILL_BY_WALL,//墙撞结束
  KILL_BY_SELF //撞到自己结束    


};

//关于蛇方向的枚举
enum DERECTION
{
	UP = 1,
	DOWN,
	LEFT,
	RIGHT

};

//定义一个蛇身节点
typedef struct SnakeNode
{
	int x;
	int y;
	struct SnakeNode* Next; //下一个节点指针!
}SnakeNode,*PSnakeNode;

//对于一次游戏的数据封装到一个类当中
typedef struct Snake
{
    //对于一次游戏中的数据有:
	PSnakeNode head ;              //指向蛇的指针	
	enum DERECTION derection;      //蛇转向的方向:                    
	int sumscore;                  //总分数
	int foodscore;	               //单个事物的分数
	PSnakeNode  foodposition;      //食物的位置
	enum STATUS status;            //游戏的状态——开始,撞墙结束,撞到自己结束,正常结束
	int SleepTime;                 //停顿的时间——(游戏执行停顿的时间。)

}Snake,*PSnake;
//函数的声明
//设置光标的位置
void SetPos(short x, short y);
//打印游戏欢迎界面
void WelcomeToGame(PSnake sn);

//游戏的准备工作:
void GameStart(PSnake sn);
//游戏开始运行:
void GameRunning(PSnake sn);
//游戏结束:
void GameEnd(PSnake sn);

Snake.c:

#include"Snake.h"
//设置光标的位置
void SetPos(short x,short y) {

	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE); //获取屏幕标准输出的句柄
	//封装光标的位置
	COORD pos = { x,y };
	//设置光标位置
	SetConsoleCursorPosition(houtput, pos);
}
//打印游戏地图
void GameMap(PSnake sn) {
	//打印游戏地图:
	//打印一个27行58列的游戏地图:
	//打印上届!
	for (int i = 0; i < 29; i++) {
		wprintf(L"%lc", L'□');
	}
	//打印下界
	SetPos(0, 26);
	for (int k = 0; k < 29; k++) {
		wprintf(L"%lc", L'□');
	}
	//打印左界
	for (int j = 1; j < 27; j++) {
		SetPos(0, j);
		wprintf(L"%lc", L'□');
	}
	//打印右界
	//需要将光标设置在地图右上角
	SetPos(56, 0);
	for (int x = 1; x < 27; x++) {
		SetPos(56, x);
		//根据光标的位置进行打印符号,光标的位置随着x变化
		wprintf(L"%lc",L'□');
	}
}
//打印欢迎界面与提示信息
void WelcomeToGame(PSnake sn) {
	//先打印第一个欢迎页面!
	SetPos(40, 14);
	printf("欢迎来到贪吃蛇游戏!!!");   
	//再打印第二个欢迎界面
	SetPos(40, 27);
	system("pause");   
	//将打印在屏幕上的第一个页面清除掉。
	system("cls");
	SetPos(25, 13);
	printf("用↑.↓.←.→ 分别控制蛇的移动,F3为加速,F4为减速\n");
	SetPos(25, 14);
	printf("加速能得到更高的分数!");
    SetPos(25, 20);
	system("pause");
	system("cls");
	//打印游戏地图:
	GameMap(sn);
    
}
//设置创建食物
void SetFoodPosition(PSnake sn) {
	int x = 0;
	int y = 0;
//需要为食物设置随机坐标:
//这个随机也需要限制,x坐标不能为奇数,
// 食物坐标必须在地图墙之内,且食物不能出现在蛇的体内
// 食物的x坐标也不能为奇数



//地图大小为58列,x属于0-57,去除两边的字符,一个字符占两个字节,所以x的范围应该是2-54;
//地图大小为27行,y属于0-26,去除上下的字符,行的宽度为1个字符,所以y的范围应该是1-25
//先获取随机值
again: do {
	
	x = rand() % 53 + 2;   //x的坐标范围为2-54:  
	y = rand() % 25 + 1;
}       //y的坐标范围为1-25
//当x为奇数时,就重新获取
	while (x % 2 == 1);
	
//判断获取的坐标是否与蛇的身体重复
PSnakeNode tmp = sn->head;
while (tmp != NULL) {
	if (tmp->x == x && tmp->y == y) {
	    //此时说明食物与蛇身位置相撞。
		//使用goto语句重新生成食物位置
		goto  again;
	}
		tmp = tmp->Next;
}
//为食物创建一个节点
PSnakeNode cur = (PSnakeNode)malloc(sizeof(SnakeNode));
if (cur == NULL) {

	perror("SetFoodPositon::malloc");
	return;

}
//当食物位置确定后:
sn->foodposition = cur;
sn->foodposition->x = x;
sn->foodposition->y = y;
//在指定位置打印食物字符
SetPos(x, y);
 wprintf(L"%lc",L'◇');
}
//初始化蛇身
void InitializeSnake(PSnake sn) {
	//初始化蛇身
	for (int i = 0; i < 5; i++) {
		PSnakeNode cur = (PSnakeNode)malloc(sizeof(SnakeNode));

		if (cur == NULL) {
			perror("Intialize::malloc");
			return;
		}
		cur->Next = NULL;
		cur->x = i * 2 + POS_X;
		cur->y = POS_Y;

		//选择头插法
		if (sn->head == NULL) {
			sn->head = cur;
		}
		else {
			//进行头插法
			cur->Next = sn->head;
			sn->head = cur;
		}
	}
	PSnakeNode cur = sn->head; 
	while (cur !=NULL) {
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", L'㊣');
		cur = cur->Next;
	}

}
//初始化游戏信息
void GameStart(PSnake sn) {

	 //1.欢迎界面的打印与功能介绍与地图的绘制!
	 WelcomeToGame(sn);
	 //2.初始化贪吃蛇的信息
	 // 创建蛇
	 InitializeSnake(sn);
	 //设置蛇最开始的方向:向右
	 sn->derection = RIGHT;
	 //设置游戏的状态:
	 sn->status = OK;
	 //设置食物的分数:10
	 sn->foodscore = 10;
	 //设置当前的总分数:
	 sn->sumscore = 0;
	 //设置食物的位置:
	 SetFoodPosition(sn);
	 //设置游戏停顿的时间
	 sn->SleepTime = 200;
}
//打印游戏的帮助信息!
void PrintHelpInfo() {
	 SetPos(65, 17);
	 printf("不能穿墙,不能咬到自己!");
	 SetPos(65, 18);
	 printf("用↑.↓.←.→来控制蛇的移动!");
	 SetPos(65, 19);
	 printf("按F3加速,F4减速");
	 SetPos(65, 20);
	 printf("按ESC退出游戏,按空格暂停游戏");
 }
//判断下一个节点是否是食物:
int IsFoodNode(PSnakeNode PNextNode,PSnake sn) {
	//判断是否是食物:
	return PNextNode->x == sn->foodposition->x && PNextNode->y == sn->foodposition->y;
}
//蛇吃掉食物
void EatFood(PSnakeNode PNextNode,PSnake sn) {
	//头插法插入节点
	sn->foodposition->Next = sn->head;
	sn->head = sn->foodposition;
	不可以只打印新增的节点。
	//SetPos(PNextNode->x,PNextNode->y);
	PSnakeNode tmp = sn->head;
	while (tmp != NULL) {
		SetPos(tmp->x, tmp->y);  
		wprintf(L"%lc", L'㊣');
		tmp = tmp->Next;
	}
	sn->sumscore += sn->foodscore; //在吃掉一个食物后,分数+单个食物的分数!
    //释放掉旧的节点:
	free(PNextNode);
}
//判断是否撞墙!
int  IsKillByWall(PSnakeNode PNextNode) {
return  PNextNode->x == 0 || PNextNode->x == 56 || PNextNode->y == 0 || PNextNode->y == 26;
	
}
//判断是否撞到自己:
int  IsKillBySelf(PSnakeNode PNextNode,PSnake sn) {
	PSnakeNode tmp = sn->head->Next;
	while (tmp != NULL) {
		//如果与蛇身的某一个节点相同
		if (PNextNode->x == tmp->x && PNextNode->y == tmp->y) { 
			return 1;
		}
		tmp = tmp->Next;
	}
	return 0;
}
//当遇到空白处时!
void   IsBlank(PSnakeNode PNextNode,PSnake sn) {
	PNextNode->Next = sn->head;
	sn->head = PNextNode;
	//找到尾节点
	PSnakeNode  tmp = sn->head;
	while (tmp->Next->Next != NULL) {
		SetPos(tmp->x, tmp->y);
		wprintf(L"%lc", L'㊣');
		tmp = tmp->Next;
	}
	//当找到倒数第二个节点时:
	SetPos(tmp->Next->x, tmp->Next->y);
	printf(" ");
	printf(" ");
    //释放尾结点
	free(tmp->Next);
	tmp->Next = NULL;

}
//蛇移动一步的操作
 void SnakeMove(PSnake sn) {
	 //先找到当前蛇头的坐标与蛇头的方向,判断下一步是什么!
	 int x = 0;
	 int y = 0;
	 //用switch语句显得更简洁:
	 switch (sn->derection) {
	 case UP:
		 //此时下一个节点的坐标即:
		 x = sn->head->x;
		 y = sn->head->y - 1;
		 break;
	 case DOWN:
		 //下一个节点的坐标:
		 x = sn->head->x;
		 y = sn->head->y + 1;
		 break;
	 case LEFT:
		 //下一个节点的坐标:
		 x = sn->head->x - 2;
		 y = sn->head->y;
		 break;
	 case RIGHT:
		 //下一个节点的坐标
		 x = sn->head->x + 2;
		 y = sn->head->y;
		 break;
	 }
	 //创建一个新的节点
	 PSnakeNode cur = (PSnakeNode)malloc(sizeof(SnakeNode));
	 if (cur == NULL) {
		 perror("NextPace::malloc");
		 return;
	 }
	 cur->x = x;
	 cur->y = y;

	 //要判断此节点是否是墙
	 if (IsKillByWall(cur)) {
		 sn->status = KILL_BY_WALL;
		 //释放掉申请的节点
		 free(cur);
		 return;
	 }
	 //判断是否是食物
	  if (IsFoodNode(cur,sn)){
		  //吃掉食物!
		  EatFood(cur, sn);
		 //当吃掉食物时,需要再随机生成一个食物,
		 SetFoodPosition(sn);
		 return;
	 }

	 //判断是否撞到了自己
	  if (IsKillBySelf(cur, sn)) {
		  sn->status = KILL_BY_SELF;
		  //释放掉申请的节点
		  free(cur);
		  return;
      }
	 //如果程序执行到这里,说明下一节点是空白处:
	//执行遇到空白时的函数。 
	  IsBlank(cur, sn);
 }
 //游戏暂停
 void Pause() {
	//让游戏暂停即一直sleep即可!
	 while (1) {
		 Sleep(200);//单位为毫秒。
		 //如果再按一次空格,则停止暂停!
		 if (KEY_PRESS(VK_SPACE)) {
			 break;
		 }
	 }
 } 
 //游戏运行
 void GameRunning(PSnake sn) {
	//游戏运行的逻辑就是每走一步,就观察一下蛇的状态。
    //根据按键的选项,进行对应的操作:
     //ESC,空格,↑,↓,←,→ F3,F4 这些键的虚拟值为:
	 //

	 do {
		 //打印游戏的帮助信息。
		 PrintHelpInfo();
		 SetPos(65, 14);
		 printf("总分数:%2d", sn->sumscore);
		 SetPos(65, 15);
		 printf("当前食物的分数:%2d", sn->foodscore);
		 //检测当前所按的键!
		 //↑按键
		 if (KEY_PRESS(VK_UP)&&sn->derection!=DOWN) {//按键不能与当前蛇的方向进行冲突
			 //在按上键时,方向改变
			 sn->derection = UP;
		
		 }
		 //↓按键
		 else if (KEY_PRESS(VK_DOWN)&&sn->derection!=UP) {
			 sn->derection = DOWN;
		 }
		 //←按键
		 else if (KEY_PRESS(VK_LEFT)&&sn->derection!=RIGHT) {
			 sn->derection = LEFT;
		 }
		 //→按键
		 else if (KEY_PRESS(VK_RIGHT)&&sn->derection!=LEFT) {
			 sn->derection = RIGHT;
		 }
		 //空格
		 else if (KEY_PRESS(VK_SPACE))
		 {  
			 //游戏暂停
			 Pause();
		 }
		 //ESC 
		 else if (KEY_PRESS(VK_ESCAPE))
		 {
			 sn->status = END_NORMAL;
		 }
		 //F3
		 else if (KEY_PRESS(VK_F3))
		 {
			 //F3是加速
			 //游戏休眠的时间不能为负数
			 if (sn->SleepTime > 80) {
				 sn->SleepTime -= 30;
				 sn->foodscore += 2;
			 }		 
		 }
		 //F4
		 else if (KEY_PRESS(VK_F4))
		 {
			 //F4是减速
			 //游戏休眠的时间也不能极其长
			 if (sn->foodscore > 2) {
				 sn->SleepTime += 30;
				 sn->foodscore -= 2;
			 }
		 }
		 SnakeMove(sn);
		 Sleep(sn->SleepTime);

	 } while (sn->status == OK);
 }
 //游戏结束的善后工作
 void GameEnd(PSnake sn) {
	  SetPos(24, 12);
	 switch (sn->status) {
	 case END_NORMAL:
		 printf("您主动退出了游戏!!!\n");
		 break;
	 case KILL_BY_SELF:
		 printf("您撞到了墙,游戏结束!!!\n");
		 break;
	 case KILL_BY_WALL:
		 printf("您撞到了自己,游戏结束!!!\n");
		 break;
	  }
	
//释放蛇身的节点
  //选择头删,
	 PSnakeNode cur = sn->head;
	 while (cur) {
		 //保证删除前面的节点能够找到后面的节点
		 PSnakeNode del = cur;
		 cur = cur->Next;
		 free(del);
	 }
 }

test.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include"Snake.h"
void test() {
	char ch = 0;
	do {
		Snake snake1 = { 0 };
		//设置屏幕
		system("mode con cols=100 lines=30");
		system("title 贪吃蛇游戏");
		
		HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
		//隐藏光标的操作:
		CONSOLE_CURSOR_INFO cursorinfo;
		GetConsoleCursorInfo(houtput, &cursorinfo);//获取当前屏幕光标的信息
		cursorinfo.bVisible = false;               //隐藏控制台光标!
		SetConsoleCursorInfo(houtput, &cursorinfo);//设置控制台光标状态
		//初始化游戏信息
		GameStart(&snake1);
		//运行游戏
		GameRunning(&snake1);
		//结束游戏
		GameEnd(&snake1);
		SetPos(20, 15);
		printf("再来一局吗?(Y/N)");
		 ch =  getchar();
		getchar(); //用于吸收\n,即吸收掉按回车键
	} while (ch == 'Y' || ch == 'y');
	SetPos(12, 26);
}
int main() {
	setlocale(LC_ALL, "");
	//产生随机数
	srand((unsigned int)time(NULL));
	test();
	return 0; 
}

总结:

  1. 自己的调试能力比较差,没有认真地进行调试,监视变量!
  2. 缺乏错误经验,一个野指针便让自己摸不着头脑!
  3. 这种做项目的思维方式有问题,后面的出现问题,又不断地修改前面的内容,如果是大项目,很容易崩盘!
  4. 具体:在函数中修改尾结点时,不需要使用二级指针,可以通过->next->next的方式进行修改。
  5. 尽量将一个个的功能用函数封装起来,即使没有减少代码冗余的地方,也可以使得代码简洁,可读性更高,便于修改与扩展功能!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[JAVASE] 异常 与 SE阶段知识点补充

目录 一. 异常 1.1 什么是异常? 1.2 异常的本质 1.3 异常的分类 1.4 如何处理异常? 1.5 自定义异常 1.6 受查异常 与 非受查异常 与 Error(重要) 二. Object类 三. 内部类 2.1 什么是内部类? 2.2 内部类的分类 2.3 常用内部类的使用 四. 总结 一. 异常 1.1 什么是异…

容声冰箱启动“以旧换新”活动,将掀起绿色消费新热潮

日前&#xff0c;容声冰箱正式启动了新一轮家电“以旧换新”活动&#xff0c;宣布从6月1日至8月31日&#xff0c;凡是通过容声自有渠道参与活动的用户&#xff0c;最高可获换新补贴1000元&#xff0c;并还有多重好礼相送。 此举旨在打造低碳、绿色、智能、时尚的家电消费新生态…

做项目管理,有哪些证书值得考?

考证可以提升技能水平&#xff0c;增强职场竞争力。 01PMP认证 PMP是受全球认可的项目管理专业人士资格认证&#xff0c;在国际上具有权威性&#xff0c;被媒体公认为继MBA、MPA之后的三大就业金字招牌。 在国内认可度也很高&#xff0c;中石油、中国石化、中兴通讯等大型企…

webf 框架源码、开发工具、数据库脚本、用户手册(233页)下载

用户手册将介绍 webf 的技术体系以及使用方法&#xff0c;便于用户快速配置出一致的开发环境&#xff0c;并能够将webf配置运行使用。 资料列表&#xff08;仅供学习参考&#xff09; webf源码持久层生成工具数据库脚本用户手册 说明&#xff1a;下载地址见文章尾部。 资源…

一图看懂 | 蓝卓热电行业解决方案

能源是人类社会发展过程中的永恒话题,热电联产作为电能和热能同时生产的能源利用形式,相较传统的火力发电具有能源利用效率高等优点,可以高效解决能源及环境问题。目前&#xff0c;世界各国都将热电联产作为更高效、更环保的能源供给体系而有效措施大力推广。 如何降本增效、减…

NeuralForecast 多变量的处理 包括训练和推理

NeuralForecast 多变量的处理 包括训练和推理 flyfish 两个excel表格合并后的结果 unique_id ds y ex_1 ex_2 ex_3 ex_4 0 HUFL 2016-07-01 00:00:00 -0.041413 -0.500000 0.166667 -0.500000 -0.001370 1 …

“滴滴打车,用友入账”,YonSuite商旅费控助力企业“降低成本”更进一步

在当今竞争激烈的商业环境中&#xff0c;企业对于成本控制和效率提升的需求日益迫切。特别是在商旅管理方面&#xff0c;如何有效整合资源、优化流程、降低费用&#xff0c;成为了成长型企业关注的焦点。用友YonSuite商旅费控作为用友集团旗下的重要产品&#xff0c;凭借其卓越…

SolidWorks功能强大的三维设计软件下载安装,SolidWorks最新资源获取!

SolidWorks&#xff0c;它凭借出色的三维建模能力&#xff0c;使得设计师们能够轻松构建出复杂且精细的机械模型&#xff0c;大大提升了设计效率和质量。 在机械设计领域&#xff0c;SolidWorks凭借其丰富的工具和特性&#xff0c;让设计师们能够随心所欲地挥洒创意。无论是零…

Linuxftp服务002本地登入

本期主要讲述的是ftp服务中的本地用户登入。 操作系统 CentOS Stream 9 操作步骤 首先我们先建立一个ftp组的用户&#xff0c;并设置密码。 [rootlocalhost ~]# useradd -g ftp wq [rootlocalhost ~]# echo 1 |passwd --stdin wq 更改用户 wq 的密码 。 passwd&#xff1a…

SpringBoot中的WebMvcConfigurationSupport和WebMvcConfigurer

在SpringBoot中可以通过以下两种方式来完成自定义WebMvc的配置&#xff1a; &#xff08;1&#xff09;继承WebMvcConfigurationSupport类 &#xff08;2&#xff09;实现WebMvcConfigurer接口 通过这两种方式完成的WebMvc配置存在差异&#xff0c;本文将对此作简单说明与区…

Selenium with Python Behave(BDD)

一、简介 Python语言的行为驱动开发&#xff0c;Behavior-driven development&#xff0c;简称BDD. "Behavior-driven development (or BDD) is an agile software development technique that encourages collaboration between developers, QA and non-technical or bu…

顶顶通呼叫中心中间件-区号号码自动加0(mod_cti基于FreeS WITCH)

顶顶通呼叫中心中间件-区号号码自动加0(mod_cti基于FreeSWITCH) 本地区号。如果配置了本地区号&#xff0c;被叫手机号码归属地和本地区号不同会自动加0 一、导入号码归属地 1、下载ccadmin安装包并且把手机号码归宿地解压出来 1、下载ccadmin安装包 Windows版本下载地址&…

小短片创作-理论知识(五)

1、网格体绘制 1.UE5打开Megascan插件的材质混合器&#xff0c;创建混合材质&#xff0c;最多选择3个材质进行混合&#xff0c; 2.通过模式->网格体绘制&#xff0c;进入网格体绘制模式&#xff0c;通过select选择一个平面进行绘制&#xff0c;然后通过paint进行绘制&am…

opencv笔记(13)—— 停车场车位识别

一、所需数据介绍 car1.h5 是训练后保存的模型 class_directionary 是0&#xff0c;1的分类 二、图像数据预处理 对输入图片进行过滤&#xff1a; def select_rgb_white_yellow(self,image): #过滤掉背景lower np.uint8([120, 120, 120])upper np.uint8([255, 255, 255])#…

09、进程和计划任务管理

9.1 查看和控制进程 程序是保存在外部存储介质(如硬盘)中的可执行机器代码和数据的静态集合&#xff0c;而进程是在 CPU 及内存中处于动态执行状态的计算机程序。在 Linux操作系统中&#xff0c;每个程序启动后可以创建一个或多个进程。例如&#xff0c;提供 Web 服务的 httpd …

计算机网络学习记录 网络层 Day4(下)

计算机网络学习记录 网络层 Day4 &#xff08;下&#xff09; 你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner &#x1f339; 如果本篇文章帮到了你 不妨点个赞吧~ 我…

期权懂题库免费!期权开户测试难吗?多少分算合格通过?

今天带你了解期权懂题库免费&#xff01;期权开户测试难吗&#xff1f;多少分算合格通过&#xff1f;期权开户测试通常要求投资者达到一定的合格分数&#xff0c;以确保他们具备足够的理解和知识来参与期权交易。 期权开户测试难吗&#xff1f; 期权开户测试的难度因人而异&am…

PW1558A规格探秘:为何它是电源系统不可或缺的6A双向保护芯片?

描述 PW1558A 是一款先进的 28V 6A 额定双向负载开关&#xff0c; 提供过载、 短路、 输入电压浪涌、 过大冲击电流和过热保护&#xff0c; 为系统供电。 内置的 24mΩ超低 RDS(ON)电源开关有助于减少正常操作期间的功率损耗。 该设备具有两个输入/输出端口 VBUS1 和 VBUS2&…

LSDFi协议赛道4大稳定币项目,以bitget钱包为例

纵览 LSDfi 生态繁荣的基石&#xff0c;LSD 稳定币赛道全解析 近期有许多建立在流动性质押通证的稳定币借贷协议开始出现在大众眼里&#xff0c;今天文章就要带大家来一一了解这些 LSDfi 协议究竟是如何争夺这块诱人的大饼。 LybraFinanceLSD 它透过抵押stETH/ETH 铸造&#…

二叉树系列题

OJ104&#xff1a;二叉树的最大深度 1.题目 2.注意 这里要用left和right接收递归的结果&#xff0c;如果不接收&#xff0c;直接用递归来比较&#xff0c;会出现效率问题。 3.参考代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* str…