瓦片编辑器成功移植到小熊猫C++ 2.25.1版本,解决_findnext移植问题

 移植之后出现绿色屏幕闪退

查了版本回滚直到不闪退,发现是在读取自定义文件上出问题

然后在找读取自定义文件函数,发现是读取图片部分出问题

然后就卡住了

调试半天,不是数据溢出,于是就看 函数_findnext,网上搜 ———_findnext 函数,发现有如下链接

解决Win10下_findnext()异常_findnext 异常-CSDN博客

在win10中,使用文件遍历函数_findnext会报0xC0000005错误
原因:
_findnext()第一个参数”路径句柄”,返回的类型为intptr_t(long long),如果定义为long,在win7中是没有问题,但是在win10中就要改为long long或者intptr_t
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/hemmingway/article/details/73716980

仅有一处不同,long fHandle 变成 long long fHandle

于是更新的代码如下

 


// 程序:2D RPG 地图编辑器
// 作者:民用级脑的研发记录
// 邮箱:1309602336@qq.com
// 编译环境:Devc++/VC 2010/Visual Studio 2022,EasyX_20220901/Easyx_2023 大暑版
// 编写日期:-2024-2-22 2024-4-14至2024-4-22 2024-4-26
// 
#undef UNICODE
#undef _UNICODE
#pragma warning(disable : 4996)		// VS2022 对某些函数警告,但是为了方便移植,就无视这些警告 这样 Devc++ VC2010 VS2022 都能跑
//#include <graphics.h>
#include <easyx/graphics.h>			// 移植到小熊猫 C++2.25.1 后,查找 MinGW 的bin 文件下的easyx文件里的 graphics.h
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <direct.h>
//30.使用时发现像素putimage刷新界面未修改,pentable系列问题如瓦片重叠部分,30的瓦片放在20的网格导致的覆盖
// 2024.4.22 修改——以bkmeshcopywidth,替换边界,以bkhieght替换鼠标按键的if边界检测与视口大小,原始数据是 30像素正方形瓦片边长,2708270 的原始视口与 3*270宽高的缓存区 。如今已自适应,可以多种像素边长
// 从默认文件夹中读取自定义图片
void loadfile(IMAGE*** bentablev2,int pixnum);
// 加载自定义图片
void loadfile_scanf(char* dirname, char* next, char* kind, IMAGE** pentablev2,int pixnum);
// 保存自定义文件
void savepersonalfile(char* DLC, IMAGE*** pentablev2);
// 保存自定义瓦片贴图
void savelocal(char* DLC, char* dirname, char* next, char* kind, char* sign, IMAGE** files);
// 实时渐变色小动画
inline void animation(int chararcterflag, int bkgameleft, int bkgametop, int bkmeshgameleft, int bkmeshgametop, int bkmeshdeskleft, int bkmeshdesktop);
// 边界检查,move 是平移大小,单位:像素,若使得寄存区在九宫格中心,move 的大小就是寄存区的边长,相应的 size 的大小是 move 的两倍。这样无论长宽都是 3 倍。size 是大小区域,代表不会触发缓冲区更新的范围,单位:像素
inline void checkboundary(int* bkgameleft, int* bkgametop, int gamelimitright, int gamelimitbuttom, int* bkmeshleft, int* bkmeshtop, int* meshlimit, int* meshlimitbutton, int bkmeshcopywidth, int bkmeshcopyheight);
// 保存游戏地图贴图数据
void savegamemap(int** map, int gamemapi, int gamemapj, IMAGE* pentable, IMAGE*** pentablev2, int pixnum, int imagenum);
// 导入游戏地图贴图数据
void loadgamemap(int** map, int* gamemapi, int* gamemapj, IMAGE* pentable, int* pixnum, int* imagenum);
// 使用关键字 inline 声明为内联函数,减少贴图函数频繁调用的开销导致的卡顿。
// 缓冲区纹理映射函数:bkmesh 映射目标,map 映射总网格,pentable:纹理集,bkmeshmapi,bkmeshmapj:映射起始点,tilenum:横,纵映射的数量,pixnum:一个映射块的边长,单位:像素。defaultnum,默认未绘制网格的标号,defaultcolor 未绘制网格的颜色
inline void freshmesh(int** oldmesh, IMAGE* bkmesh,  int** map, IMAGE* pentable, IMAGE*** pentablev2, int bkmeshmapi, int bkmeshmapj, int bkmeshfreshi,int bkmeshfreshj,int pixnum,int defaultnum,int defaultcolor)
{int kind = 0;											// 存储代号第一位:类型int number = 0;											// 存储代号第二位:序列号int pennumber = -1;										// 暂存每一次循环的映射代号IMAGE* pen = NULL;										// 所找到的纹理int left = 0;											// 这是每次循环所找到的纹理对应映射地址int top = 0;SetWorkingImage(bkmesh);								// 设置绘图目标为游戏背景采样区,刷新采样区,刷新寄存区
//	cleardevice();											// 当时没注意导致一直重绘制,并且当时原版cleardevice失效,数组功能不确定。却由此能跑项目,可知当时问题根源不定导致的修改困难int sidei=bkmeshmapi + bkmeshfreshi;					// 计算变量,每次循环就不用再次计算了,表达式在for循环中会一直重复计算,用side替换for的表达式int sidej=bkmeshmapj + bkmeshfreshj;for (int i = bkmeshmapi; i <sidei; i++){left = 0;for (int j = bkmeshmapj; j < sidej; j++){// 注意数组越界pennumber = map[i][j];						// 读取游戏大地图数组序号if(oldmesh[i-bkmeshmapi][j-bkmeshmapj]==pennumber&&pennumber==defaultnum)							// 性能优化,如果相同位置瓦片序号相同,就不用重新绘制了,即缓存区只选择部分像素重新绘制{		// 2024.4.22 重整,增加pennumber==defaultnum,只对空的瓦片不绘制,因为之后有的瓦片绘制一次会有残留直线边界,所以需要重绘解决 }else{oldmesh[i-bkmeshmapi][j-bkmeshmapj]=pennumber;if (pennumber == defaultnum){setfillcolor(BGR(defaultcolor));fillrectangle(left, top, left + pixnum, top + pixnum);				// 修正,如果是rectangle则会有黑色不完全打印}else{kind = pennumber / 10 - 6;						// 剥离第一位number = pennumber % 10;						// 剥离最后一位if (pennumber < 10)pen = &pentable[pennumber];elsepen = pentablev2[kind][number];				// 根据序号查找对应贴图putimage(left, top, pen);						// 把贴图画到采样区}}left += pixnum;										// 往右移动,准备下一次绘制位置,此处贴图就会覆盖白色边框。为保证坐标变换和网格对应,算上网格宽度,也在贴图矩形内}top += pixnum;											// 往下移动,准备下一次绘制位置,此处就会覆盖白色边框,方便定位}SetWorkingImage();
}
// 修改为常数即只显示窗口大小的图像
inline void freshbk(IMAGE* bk, IMAGE* bkmesh, int gamex, int gamey, int bkmeshmapi, int bkmeshmapj, int bkwidth,int bkheight, int pixnum)
{SetWorkingImage(bkmesh);getimage(bk, gamex - bkmeshmapj * pixnum, gamey - bkmeshmapi * pixnum, bkwidth, bkheight);		// 计算去除平移多个bkmeshmapj对应的像素距离,从刚刚绘制好的采样区取样,刷新游戏背景寄存区。SetWorkingImage();
}
// 在屏幕显示截图
inline void showbk(IMAGE* bk, int bkdeskx, int bkdesky)
{SetWorkingImage();putimage(bkdeskx, bkdesky, bk);
}
// 在屏幕上显示缓冲区
inline void showbkmesh(IMAGE* bkmesh, int bkmeshdeskx, int bkmeshdesky)
{SetWorkingImage();putimage(bkmeshdeskx, bkmeshdesky, bkmesh);
}
// 初始化游戏地图
int** initmap(int wide, int high,int defaultnum)
{int** map = new int* [high];					// 二维数组动态初始化,先给二级指针挂上一个长度为 10 的指针数组for (int i = 0; i < high; i++){map[i] = new int[wide];						// 然后数组里的每个指针都挂上一个长度为 10 的 int 类型数组}for (int i = 0; i < high; i++){for (int j = 0; j < wide; j++){map[i][j] = defaultnum;							// 初始化游戏大地图 map 的参数,参数 1 默认黑色}}return map;
}
int main()
{initgraph(1640, 980, 1);setbkcolor(GREEN);setlinecolor(WHITE);cleardevice();// 这里是当时重整的起点,复制粘贴这部分以前的变量去改写 ,写一块新的就注释一块旧的int defaultnum;								// 地图初始化时,默认空地图的序号defaultnum=9999;int defaultcolor=0x00CCCCCC;				// 00 是完全不透明,FF是完全透明00-FF刚好是0-255。 ARGB 0x 00: alpha + 00: red + 00: green + 00: blue ,但是绘制时 setfillcolor的格式是 BGR,所以使用时需要 BGR()转换。int pixnum;pixnum = 30;
//	pixnum = 60;
//	pixnum=15;// 规定上限参数// 进行初始化,规定各位置具体数字int bkmeshMaxwidth;							// 缓冲区自适应宽度,用于不同pixnum 下缓存九宫格的边界适应int bkmeshMaxheight;						// 缓冲区自适应高度,用于不同pixnum 下缓存九宫格的边界适应int mapMaxwidth;							// 游戏地图自适应高度网格数,用于选取最接近上限的网格数,用于不同的 pixnum 下游戏网格数目是九宫格的每一格的整数倍int mapMaxheight;int bkmeshcopyMaxheight;					// 自适应九宫格其中的一格格子的宽高上限。int bkmeshcopyMaxwidth;int bkMaxwidth;								// 用于限制窗口大小 ,这是在窗口可以拖住拉伸之后用的变量int bkMaxheight;							// 用于限制窗口大小 ,这是在窗口可以拖住拉伸之后用的变量// 上限的一种参考bkmeshcopyMaxheight=1000;					// 测试当宫格小于游戏视口时,绘制的边界检测bkmeshcopyMaxwidth=1000;
//	bkmeshcopyMaxheight=300;					// 测试数据,用于测试视口比单个宫格大的情况——出现黑边 
//	bkmeshcopyMaxwidth=300;
//	bkmeshcopyMaxheight=900;
//	bkmeshcopyMaxwidth=1460;bkMaxheight=bkmeshcopyMaxheight;bkMaxwidth=bkmeshcopyMaxwidth;bkmeshMaxwidth=bkmeshcopyMaxwidth*3;						// 宽的上限界限是 九宫格其中一格宽的三倍像素bkmeshMaxheight=bkmeshcopyMaxheight*3;						// 高的上限界限是 九宫格其中一格高的三倍像素
//	mapMaxheight=bkmeshMaxheight*100;								// 游戏地图高度的像素上限是九宫格的高度的300倍
//	mapMaxwidth=bkmeshMaxwidth*100;								// 游戏地图宽度的像素上限是九宫格的宽度的300倍
//	mapMaxheight=bkmeshMaxheight*1;								// 测试发现边界闪退,越界数组刷新发现。游戏地图高度的像素上限是九宫格的高度的1倍
//	mapMaxwidth=bkmeshMaxwidth*1;								// 游戏地图宽度的像素上限是九宫格的宽度的1倍mapMaxheight=bkmeshMaxheight*2;								// 测试发现边界闪退,越界数组刷新发现。游戏地图高度的像素上限是九宫格的高度的2倍mapMaxwidth=bkmeshMaxwidth*2;// 实际自适应于瓦片的大小,用于保证不同的 background bk 都能在九宫格的每个宫格边缘切换地图时不错位。int bkheight;												// 2024.4.21修改,发现需要适配屏幕高度,增大面积,新增变量替换常数 270 ,先原样替换,验证替换正常,再继续改数据int bkwidth;
//	bkheight=370;
//	bkwidth=370;bkheight=470;												// 如果小于一个宫格的最大bkwidth=470;if(bkMaxheight<bkheight||bkMaxwidth<bkwidth){printf("测试阶段:视口比单个宫格大,会在边界出现黑边情况\n");}else{printf("正常运行,视口比单个宫格小,不会在边界出现黑边情况\n");}IMAGE* bk;										// 背景图片寄存区bk = new IMAGE(bkwidth,bkheight);int bkmeshheight;int bkmeshwidth;int bkmeshcopywidth;							// 2024.4.21修改,增加copywidth,发现需要适配屏幕高度,增大面积,新增变量替换常数 270 ,先原样替换,验证替换正常,再继续改数据int bkmeshcopyheight;							// 九宫格的其中一格高度,采样越过九宫格左上四个块的边界,就进行更新九宫格,从原来的九宫格右边边界变成左边固定边界,实现不同大小的游戏背景 bk 不会因为边界检测距离变化而导致需要重新计算int bkmeshcopyi;								// 九宫格上下平移一次的网格个数,就是一格宫格竖着数有几个瓦片int bkmeshcopyj;								// 九宫格左右平移一次的网格个数,就是一格宫格横着数有几个瓦片int** map;int mapi;										// 读取 DLC 文件,需要变量记录循环次数,单位 瓦片贴图个数int mapj;int safemapi;									// 一个安全的贴图范围,避免阅读超过 10000 导致的越界闪退问题。int safemapj;int safemapright;								// 游戏右边界像素坐标,左边界坐标默认是0int safemapbottom;								// 游戏下边界像素坐标,上边界坐标默认是0int gamelimitright;								// 用于减少比较时的计算,存储游戏大地图边界范围int gamelimitbottom;int meshlimitright;								// 使用变量暂存边界,不用每次来回计算边界int meshlimitbottom;int bkmeshfreshi;								// 九宫格高有多少个瓦片,用于刷新缓存区时确定游戏网格宽的采样次数int bkmeshfreshj; 								// 九宫格宽有多少个瓦片,用于刷新缓存区时确定游戏网格高的采样次数// 开始自适应,各个存储区大小以及边界bkmeshcopyi= bkmeshcopyMaxheight/pixnum;		// 一格高度能按瓦片高度分,能分成几份,就是一格宫格横着数有几个瓦片bkmeshcopyj=bkmeshcopyMaxheight/pixnum;			// 一格宽度能按瓦片宽度分,能分成几份,就是一格宫格竖着数有几个瓦片bkmeshcopyheight=bkmeshcopyi*pixnum;			// 整除之后乘像素算出实际一格像素宽度,用于计算九宫格实际宽度bkmeshcopywidth=bkmeshcopyj*pixnum;bkmeshheight=bkmeshcopyheight*3;				// 九宫格的像素高度bkmeshwidth=bkmeshcopywidth*3;					// 九宫格的像素宽度bkmeshfreshi=bkmeshheight/pixnum;				// 计算九宫格横着一行有几个瓦片bkmeshfreshj=bkmeshwidth/pixnum;				// 计算九宫格竖着一列有几个瓦片meshlimitright=bkmeshcopywidth*2;				// 计算 bk 采样到右边界时更新所需的边界,是像素坐标,checkboundary 会更新这个边界meshlimitbottom=bkmeshcopyheight*2;				// 计算 bk 采样到下边界时更新所需的边界,是像素坐标,checkboundary 会更新这个边界mapi=mapMaxheight/bkmeshcopyheight*bkmeshcopyi;	// 计算实际游戏地图长有多少个瓦片,就是游戏最大高度整除瓦片高度,算出有几个宫格,然后在乘一个宫格竖着数瓦片个数mapj=mapMaxwidth/bkmeshcopywidth*bkmeshcopyj;	// 计算实际游戏地图宽有多少个瓦片,就是游戏最大宽度整除瓦片宽度,算出有几个宫格,然后在乘一个宫格横着数瓦片个数
//	safemapi=mapi-bkmeshcopyi*2;	// 测试倒数第一个九宫格左上角坐标		// 适配旧代码的同名变量,旧代码测试出来数据的位置被标记为safemapi,根据 地图和缓存区一样大时,越界检测,九宫格的最后一格宫格是地图边界时对应左上角,差两个宫格此时到边境了,不能再往右刷新。
//	safemapj=mapj-bkmeshcopyj*2;	// 测试倒数第一个九宫格左上角坐标		// 适配旧代码的同名变量,旧代码测试出来数据的位置被标记为safemapj,根据 地图和缓存区一样大时,越界检测,九宫格的最后一格宫格是地图边界时对应左上角,差两个宫格此时到边境了,不能再往下刷新。safemapi=mapi-1;										// 绘制的时候确定下网格界限,数据-1是因为数组的第 0 个对应左边第一个瓦片,于是等同于数组下标是总数-1 ,初始化n个,数组对应序号 0~n-1safemapj=mapj-1;										// 绘制的时候确定右网格边界,数据-1是因为数组的第 0 个对应左边第一个瓦片,于是等同于数组下标是总数-1 ,初始化n个,数组对应序号 0~n-1safemapbottom=mapi*pixnum-bkmeshcopyheight;			// 计算出采样区距离最后一格的像素距离,因为采样区的移动控制缓存区的移动,这样的设计导致只有采样区停止移动,缓存区才能停止移动,就需要把缓存区停止移动的位置换算成采样区停止移动的距离safemapright=mapj*pixnum-bkmeshcopywidth;			// 计算出采样区距离最后一格的像素距离,因为采样区的移动控制缓存区的移动,这样的设计导致只有采样区停止移动,缓存区才能停止移动,就需要把缓存区停止移动的位置换算成采样区停止移动的距离gamelimitright=safemapright;					// 换算出对应像素位置,就是玩家视口左上角坐标的极限,同样说明视口的最大不超过宫格,但实际上可以,只不过就是看到黑边但不闪退gamelimitbottom=safemapbottom;printf("mapj,i=%d,%d\n",mapj,mapi);printf("safemapj,safemapi %d,%d\n",safemapj,safemapi);printf("gamelimitrx,gamelimitry %d %d",gamelimitright,gamelimitbottom);map = initmap(mapj, mapi,defaultnum);			// 初始化游戏网格大地图!			j对应函数第一个参数,i对应第二个参数,否则会闪退IMAGE* bkmesh;									// 背景图片采样区bkmesh = new IMAGE(bkmeshwidth, bkmeshheight);int bkgameleft;								// 背景图片寄存区左上角坐标,是在游戏里的像素坐标。(0,0)可以理解为游戏大地图的左上角顶点。int bkgametop;int bkmeshgameleft;							// 背景图片采样区左上角坐标,是在游戏里的像素坐标。int bkmeshgametop;int bkmeshmapi;								// 背景图片采样区左上角所对应的 map 数组序号。从 map[0][0]开始,按照 map[i][j],其中 bkmeshmapi=bkmeshtop/pixnumint bkmeshmapj;bkgameleft = 0;								// 由于 bkgame 控制 mesh 坐标移动,(0,0)则游戏背景完全在当前采样区移动bkgametop = 0;bkmeshgameleft = 0;bkmeshgametop = 0;bkmeshmapi = bkmeshgametop / pixnum;				// 缓存区左上角所在的游戏网格的哪一行bkmeshmapj = bkmeshgameleft / pixnum;				// 缓存区左上角所在的游戏网格的哪一列int bkdeskleft;								// 规定在屏幕上显示游戏背景寄存区,此处记录其左上角在屏幕上的像素坐标int bkdesktop;int bkmeshdeskleft;							// 规定在屏幕上显示游戏背景采样区,此处记录其左上角在屏幕上的像素坐标int bkmeshdesktop;bkdeskleft = 200;							// 游戏背景左上角将会在屏幕的(200,200) 处bkdesktop = 200;bkmeshdeskleft = 700;						// 游戏背景缓冲区左上角将会在屏幕的(700,0)处bkmeshdesktop = 0;// 自此为止就是变量自适应结束int** oldmesh;oldmesh=new int*[bkmeshfreshi];for(int i=0; i<bkmeshfreshi; i++){oldmesh[i] =new int[bkmeshfreshj];for(int j=0; j<bkmeshfreshj; j++){oldmesh[i][j]=999999;						// 正数}}// 提出来的性能优化代码,用于freshmesh时刷新过滤相同的数字的瓦片,这样数字相同,瓦片相同,就不用绘制了int pentableleft;								// 忘了初始化调色盘了,这里设置调色盘左上角在屏幕的坐标int pentabletop;int imagenum;									// 调色板数量上限,用于文件读取控制循环次数IMAGE* pentable;								// 调色板其实就是贴图数组pentableleft = 0;								// 调色盘左上角将会在屏幕的(0,0)处pentabletop = 0;imagenum = 10;int pentablev2left;								// 自定义贴图插槽int pentablev2top;int pentablev2high;								// 自定义贴图的容量大小int pentablev2wide;pentablev2left = 10;pentablev2top = 300;pentablev2high = 10;pentablev2wide = 4;IMAGE*** pentablev2;pentablev2 = new IMAGE **[pentablev2wide];for (int i = 0; i < pentablev2wide; i++)pentablev2[i] = new IMAGE * [pentablev2high];for (int i = 0; i < pentablev2wide; i++)for (int j = 0; j < pentablev2high; j++)pentablev2[i][j] = NULL;loadfile(pentablev2,pixnum);							// 加载本地图片// 调色盘加载数据,需要调整,可以加载任意大小的图片,然后切割成多个小图片然后导出。
// 绘制的时候,可以选中多个瓦片,一次绘制多个瓦片,mesh除以选中的网格数。画区分线,每四个画一个网格线。
// 瓦片设计的时候,需要一个再绘图板实现数组刷新。原图放缩小图笔刷pentable = new IMAGE[imagenum];for (int i = 0; i < imagenum; i++){pentable[i] = IMAGE(pixnum,pixnum);				// 默认调色板也自适应像素高度SetWorkingImage(&pentable[i]);					// 给调色板绘制颜色setfillcolor(RGB(i * 20, i * 20, i * 20));		// 这里初始化调色盘的颜色fillrectangle(-1, -1, pixnum, pixnum);				// 在调色板上绘制颜色(纹理)要从 -1,-1 开始绘制,把边框画到外部,不保留边框。}int left;												// 初始化绘制采样区所需的坐标,相对于采样区,(0,0)就是采样区左上角顶点坐标int top;left = 0;top = 0;//	往缓冲区刷入贴图SetWorkingImage(bkmesh);								// 设置绘图目标为游戏背景采样区,刷新采样区,刷新寄存区setbkcolor(RGB(200, 200, 200));							// 设置瓦片边线颜色,图片没有覆盖的背景就是边线cleardevice();for (int i = bkmeshmapi; i < bkmeshmapi + bkmeshfreshi; i++){left = 0;for (int j = bkmeshmapj; j < bkmeshmapj + bkmeshfreshj; j++){int pennumber = map[i][j];							// 读取游戏大地图数组序号if (pennumber == 9999){rectangle(left, top, left + pixnum, top + pixnum);}left += pixnum;										// 往右移动,准备下一次绘制位置,}top += pixnum;											// 往下移动,准备下一次绘制位置}getimage(bk, bkgameleft, bkgametop, bkwidth,bkheight);				// 从刚刚绘制好的采样区取样,刷新游戏背景寄存区。//	开始往屏幕上绘图SetWorkingImage();															// 设置电脑屏幕为绘制对象for (int j = 0; j < 10; j++){putimage(pentableleft + 10, pentabletop + j * pixnum, &pentable[j]); 		// 绘制绘图板}for (int i = 0; i < pentablev2wide; i++)									// 绘制自定义贴图,印自定义笔刷for (int j = 0; j < pentablev2high; j++)if (pentablev2[i][j] != NULL)putimage(pentablev2left + i * pixnum, pentablev2top + j * pixnum, pentablev2[i][j]);						// pixnum 替换 30putimage(bkdeskleft, bkdesktop, bk);										// 绘制游戏背景putimage(bkmeshdeskleft, bkmeshdesktop, bkmesh); 							// 显示游戏背景缓冲区// 此时绘制完成,以上 刷贴图,采样,粘贴就是实现 RPG 游戏大地图的压缩//	开始检测鼠标键盘功能int drawflag;															// 设置长按 flagint drawoldmx;															// 记录上一次绘制时的鼠标坐标,用于检测是否重复点击相同像素,来减少重复绘制int drawoldmy;int drawx;																// 画笔在游戏里的位置,单位像素int drawy;int olddrawi;															// 记录上一次绘制的瓦片,判断是否需要重新绘制int olddrawj;int drawsmallflag;														// 在 drawflag=1 时,检测是否刷新drawsmallflag = 0;olddrawi = 0;olddrawj = 0;drawx = 0;drawy = 0;drawflag = 0;drawoldmx = 0;drawoldmy = 0;int pentake;															// 设置不绘制时贴图代号为 -1pentake = 9;															// 默认白色笔刷,对应黑色背景int draftoldmx;															// 记录刚刚拖拽时的鼠标的位置,用于坐标变换计算位移int draftoldmy;int draftoldgamex;														// 记录刚刚拖拽时的游戏地图位置,用于坐标变换计算新的游戏坐标int draftoldgamey;int draftflag;															// 设置拖拽 flagdraftoldmx = 0;draftoldmy = 0;draftoldgamex = 0;draftoldgamey = 0;draftflag = 0;int moveflag;															// 是否键盘控制移动int flag_x;																// 记录位移int flag_y;int speed;																// 键盘控制视口的移动速度speed = 5;flag_x = 0;flag_y = 0;moveflag = 0;int mousex;																// 记录鼠标位置int mousey;mousex = 0;mousey = 0;int oldbkmeshgamex;														// 判断拖拽时是否需要刷新 bkmesh 网格int oldbkmeshgamey;oldbkmeshgamex = -1;oldbkmeshgamey = -1;int i = -1;																// 用于暂存 mesh 网格坐标int j = -1;int characterflag;														// 用于按键时游戏小人的颜色变化characterflag = 5;ExMessage m;while (1){while (peekmessage(&m, EX_KEY | EX_MOUSE))		// 一次性处理完鼠标消息,参考自 https://codebus.cn/zhaoh/handle-mouse-messages-correctly{switch (m.message){case WM_LBUTTONDOWN:																				// 鼠标左键按下,有两种情况,一是选择贴图,另外就是绘制贴图if (drawflag == 0 && m.x > bkdeskleft && m.y > bkdesktop && m.x < bkdeskleft + bkwidth && m.y < bkdesktop + bkheight)		// 如果之前不是长按状态	且按下左键时,鼠标在游戏背景区域内{drawflag = 1;																				// 记录为正在绘制的状态mousex = m.x;																				// 记录坐标用于绘制mousey = m.y;}else if (drawflag == 0 && draftflag == 0 && m.x > 0 && m.y > 10 && m.x < 40 && m.y < 300){pentake = m.y / pixnum;																			// 选择贴图对应的代号printf("pentake: %d\n", pentake);}else if (drawflag == 0 && draftflag == 0 && m.x > 10 && m.y > 300 && m.x < 10 + pentablev2wide * 30 && m.y < 300 + pentablev2high * 30){if (pentablev2[(m.x - pentablev2left) / pixnum][(m.y - pentablev2top) / pixnum] != NULL)pentake = ((m.x - pentablev2left) / pixnum + 6) * 10 + (m.y - pentablev2top) / pixnum;	// 计算 map 的二位数代号printf("pentakev2: %d\n", pentake);}break;case WM_LBUTTONUP:drawflag = 0;drawsmallflag = 0;olddrawi = -1;olddrawj = -1;drawoldmx = -1;																					// 清除坐标记录,保证下次按键一定绘制drawoldmy = -1;break;case WM_RBUTTONDOWN:																				// 鼠标右键拖动if (draftflag == 0 && m.x > bkdeskleft && m.y > bkdesktop && m.x < bkdeskleft + bkwidth && m.y < bkdesktop + bkheight){draftflag = 1;draftoldmx = m.x;																			// 记录鼠标坐标draftoldmy = m.y;mousex = m.x;mousey = m.y;draftoldgamex = bkgameleft;																	// 记录游戏背景寄存区左上角坐标draftoldgamey = bkgametop;}break;case WM_RBUTTONUP:draftflag = 0;bkgameleft = draftoldgamex - (m.x - draftoldmx);												// bkgameleft - draftoldgamex =- (m.x - draftoldmx)bkgametop = draftoldgamey - (m.y - draftoldmy);													// bkgametop - draftoldgamey =- (m.y - draftoldmy)mousex = -1;																					// draft 和 draw 共用 mousex mouseymousey = -1;break;case WM_KEYDOWN:switch (m.vkcode)				// 键盘移动控制{case 0x41:						// Aif (flag_x - speed > -10)	// 限制范围,减少内存读写flag_x -= speed;characterflag = 1;break;case 0x57:						// Wif (flag_y - speed > -10)flag_y -= speed;characterflag = 2;break;case 0x44:						// Dif (flag_x + speed < 10)flag_x += speed;characterflag = 3;break;case 0x53:						// Smoveflag = 1;if (flag_y + speed < 10)flag_y += speed;characterflag = 4;break;case VK_F1:savegamemap(map, mapi, mapj, pentable, pentablev2, pixnum, imagenum);break;case VK_F2:loadgamemap(map, &mapi, &mapj, pentable, &pixnum, &imagenum);gamelimitright = pixnum * safemapi;gamelimitbottom = pixnum * safemapj;for (int i = 0; i < imagenum; i++)					// 刷新绘图板颜色{pentable[i] = IMAGE(pixnum, pixnum);SetWorkingImage(&pentable[i]);					// 给调色板绘制颜色setfillcolor(RGB(i * 20, i * 20, i * 20));		// 这里初始化调色盘的颜色fillrectangle(-1, -1, pixnum, pixnum);			// 在调色板上绘制颜色(纹理)要从 -1,-1 开始绘制,把边框画到外部,不保留边框。}SetWorkingImage();freshmesh(oldmesh,bkmesh, map, pentable, pentablev2, bkmeshmapi, bkmeshmapj, bkmeshfreshi,bkmeshfreshj, pixnum, defaultnum, defaultcolor);			// 刷新,重新映射,其实就是开头初始化的代码,这里是给了一个封装示例,用了一个数组过滤重复位置进行性能优化-2024.4.21freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, bkwidth, bkheight, pixnum);								// 2024.4.21修改showbk(bk, bkdeskleft, bkdesktop);showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);break;}break;case WM_KEYUP:switch (m.vkcode){case 0x41:						// Aflag_x = 0;break;case 0x57:						// Wflag_y = 0;break;case 0x44:						// Dflag_x = 0;break;case 0x53:						// Sflag_y = 0;break;}if (flag_x == 0 && flag_y == 0)characterflag = 5;break;case WM_MOUSEMOVE:if (mousex != m.x || mousey != m.y){mousex = m.x;mousey = m.y;}break;}}//		开始根据指令运行坐标变化if (draftflag == 1){if (flag_x != 0)																	// 实现拖拽时键盘也能控制移动draftoldgamex += flag_x;if (flag_y != 0)draftoldgamey += flag_y;bkgameleft = draftoldgamex - (mousex - draftoldmx);									// bkgameleft-draftoldgamex=-(mousex-draftoldmx)bkgametop = draftoldgamey - (mousey - draftoldmy);									// bkgametop-draftoldgamey=-(mousey - draftoldmy)if (drawflag == 1 && mousex > bkdeskleft && mousey > bkdesktop && mousex < bkdeskleft + bkwidth && mousey < bkdesktop + bkheight)		// 实现边拖拽边移动边绘制{drawx = bkgameleft + (mousex - bkdeskleft);										// drawx-bkgameleft=m.x-bkdeskleft	横坐标方向移动距离相同drawy = bkgametop + (mousey - bkdesktop);										// drawy-bkgametop=m.y-bkdesktop	纵坐标方向移动距离相同i = drawy / pixnum;j = drawx / pixnum;if (olddrawi != i || olddrawj != j){if (i > safemapi)															// map 数组越界检测i = safemapi;else if (i < 0)i = 0;if (j > safemapj)j = safemapj;else if (j < 0)j = 0;drawsmallflag = 1;map[i][j] = pentake;											// 注意 map[y][x],而不是 map[x][y],因为判断第几行,是通过 y 来控制上下移动的,判断第几列,是通过 x 左右移动的。olddrawi = i;olddrawj = j;}else{drawsmallflag = 0;												// 检测到是上一次绘制的瓦片,则不再刷新贴图与缓冲区。}}}else if (drawflag == 1 && flag_x == 0 && flag_y == 0 && (drawoldmx != mousex || drawoldmy != mousey) && mousex > bkdeskleft && mousey > bkdesktop && mousex < bkdeskleft + bkwidth && mousey < bkdesktop + bkheight){// 注意不要越界,否则 gamex 为负数,导致数组越界闪退。// 通过实现坐标变换与赋值达到修改游戏大地图(数组)moveflag = 0;drawoldmx = mousex;drawoldmy = mousey;drawx = bkgameleft + (mousex - bkdeskleft);										// drawx-bkgameleft=mousex-bkdeskleft	横坐标方向移动距离相同drawy = bkgametop + (mousey - bkdesktop);										// drawy-bkgametop=mousey-bkdesktop	纵坐标方向移动距离相同i = drawy / pixnum;j = drawx / pixnum;if (olddrawi != i || olddrawj != j){if (i > safemapi)															// map 数组越界检测,放内部则边界检测会多写,放外部则绘制时会多写消耗i = safemapi;else if (i < 0)i = 0;if (j > safemapj)j = safemapj;else if (j < 0)j = 0;drawsmallflag = 1;map[i][j] = pentake;														// 注意 map[y][x],而不是 map[x][y],因为判断第几行,是通过 y 来控制上下移动的,判断第几列,是通过 x 左右移动的。olddrawi = i;olddrawj = j;}else{drawsmallflag = 0;															// 检测到是上一次绘制的瓦片,则不再刷新贴图与缓冲区。}}	//	对绘制进行分类计算数据,剥离特殊情况的重复绘制,仅仅是 flag_x,或者 flag_y 不为零时取消重复绘制判断else if (drawflag == 1 && mousex > bkdeskleft && mousey > bkdesktop && mousex < bkdeskleft + bkwidth && mousey < bkdesktop + bkheight){moveflag = 1;bkgameleft += flag_x;															// 更新游戏背景寄存区左上角坐标bkgametop += flag_y;drawx = bkgameleft + (mousex - bkdeskleft);										// drawx-bkgameleft=m.x-bkdeskleft	横坐标方向移动距离相同drawy = bkgametop + (mousey - bkdesktop);										// drawy-bkgametop=m.y-bkdesktop	纵坐标方向移动距离相同i = drawy / pixnum;j = drawx / pixnum;if (olddrawi != i || olddrawj != j){if (i > safemapi)															// map 数组越界检测i = safemapi;else if (i < 0)i = 0;if (j > safemapj)j = safemapj;else if (j < 0)j = 0;printf("draw j,i=%d,%d\n",j,i);												// 测试数据 printf("bkgamex,y %d %d\n",bkgameleft,bkgametop);printf("bkmeshmapi,bkmeshmapj %d %d\n",bkmeshmapi,bkmeshmapj);drawsmallflag = 1;map[i][j] = pentake;											// 注意 map[y][x],而不是 map[x][y],因为判断第几行,是通过 y 来控制上下移动的,判断第几列,是通过 x 左右移动的。olddrawi = i;olddrawj = j;}else{drawsmallflag = 0;												// 检测到是上一次绘制的瓦片,则不再刷新贴图与缓冲区。}}else if ((drawflag == 0 && flag_x != 0 )|| flag_y != 0){moveflag = 1;bkgameleft += flag_x;bkgametop += flag_y;}else{// 既不绘制也不移动也不拖拽}// 根据计算出的坐标数据进行绘制,分多种情况分别绘制,减少函数重复调用与无效调用if (drawsmallflag == 1 && moveflag == 0){freshmesh(oldmesh, bkmesh,map, pentable, pentablev2, bkmeshmapi, bkmeshmapj, bkmeshfreshi,bkmeshfreshj, pixnum,defaultnum, defaultcolor);			// 刷新,重新映射,其实就是开头初始化的代码,这里是给了一个封装示例,用了一个数组过滤重复位置进行性能优化-2024.4.21freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, bkwidth, bkheight, pixnum);showbk(bk, bkdeskleft, bkdesktop);showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);}else if (moveflag == 1 && drawsmallflag == 1){checkboundary(&bkgameleft, &bkgametop, gamelimitright, gamelimitbottom, &bkmeshgameleft, &bkmeshgametop, &meshlimitright, &meshlimitbottom, bkmeshcopyheight, bkmeshcopywidth);			// move =pixnum * 9, size = 2*9* pinxum 2024.4.22 替换 bkmeshcopyheightbkmeshmapi = bkmeshgametop / pixnum;bkmeshmapj = bkmeshgameleft / pixnum;freshmesh(oldmesh, bkmesh,map, pentable, pentablev2, bkmeshmapi, bkmeshmapj, bkmeshfreshi,bkmeshfreshj, pixnum,defaultnum, defaultcolor);			// 刷新,重新映射,其实就是开头初始化的代码,这里是给了一个封装示例,用了一个数组过滤重复位置进行性能优化-2024.4.21freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, bkwidth, bkheight, pixnum);showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);showbk(bk, bkdeskleft, bkdesktop);}else if (moveflag == 1 || draftflag)															// 分类渲染, drawflag==0 时,再选择性刷新缓冲区{checkboundary(&bkgameleft, &bkgametop, gamelimitright, gamelimitbottom, &bkmeshgameleft, &bkmeshgametop, &meshlimitright, &meshlimitbottom,bkmeshcopyheight, bkmeshcopywidth);			// move =pixnum * 9, size = 2*9* pinxumbkmeshmapi = bkmeshgametop / pixnum;bkmeshmapj = bkmeshgameleft / pixnum;if (oldbkmeshgamex != bkmeshgameleft || oldbkmeshgamey != bkmeshgametop)					// 判断是否更新采样区{freshmesh(oldmesh,bkmesh, map, pentable, pentablev2, bkmeshmapi, bkmeshmapj, bkmeshfreshi,bkmeshfreshj, pixnum,defaultnum, defaultcolor);			// 刷新,重新映射,其实就是开头初始化的代码,这里是给了一个封装示例,用了一个数组过滤重复位置进行性能优化-2024.4.21oldbkmeshgamex = bkmeshgameleft;oldbkmeshgamey = bkmeshgametop;showbkmesh(bkmesh, bkmeshdeskleft, bkmeshdesktop);}freshbk(bk, bkmesh, bkgameleft, bkgametop, bkmeshmapi, bkmeshmapj, bkwidth, bkheight, pixnum);showbk(bk, bkdeskleft, bkdesktop);}animation(characterflag, bkgameleft, bkgametop, bkmeshgameleft, bkmeshgametop, bkmeshdeskleft, bkmeshdesktop);Sleep(2);																		// 休眠 2 毫秒,减少 CPU 占用}return 0;
}
// 保存游戏地图的全部数据
void savegamemap(int** map, int gamemapi, int gamemapj, IMAGE* pentable, IMAGE*** pentablev2, int pixnum, int imagenum)
{FILE* fp;int i = 0;int j = 0;char dirpath[400] = { '\0' };char filepath[400] = { '\0' };for (i = 0; i < 100; i++){sprintf(dirpath, "DLC%d", i);if (access(dirpath, 0) == -1) 									// 检查 DLC 是否存在,不存在为 -1{break;}}mkdir(dirpath);														// 创建文件夹char filename[400] = "gamemap.txt";const char* next = "./";strcat(filepath, dirpath);strcat(filepath, next);strcat(filepath, filename);fp = fopen(filepath, "w+");											// 创建 .txt 文件fprintf(fp, "注意此导出的游戏文件为按键 F1 后自动生成 修改汉语字符或者英文字符 或导致该 .txt 文件不可读取\n");fprintf(fp, "warning this saved gamefile is automatically create after F1 pressed change Chinesse character or English character lead to read failed");fprintf(fp, "pixnum %d\n", pixnum);									// 正方形瓦片贴图边长信息:单位:像素fprintf(fp, "imagenum %d\n", imagenum);								// 瓦片个数char imageindix[400] = { '\0' };for (i = 0; i < imagenum; i++){sprintf(imageindix, "tile_%d.png", i);fprintf(fp, "%s\n", imageindix);}fprintf(fp, "gamemapi %d gamemapj %d\n", gamemapi, gamemapj);for (i = 0; i < gamemapi; i++){fprintf(fp, "%d", map[i][j]);for (j = 0; j < gamemapj; j++){fprintf(fp, " %d", map[i][j]);}fprintf(fp, "\n");}fclose(fp);char imagename[400] = { '\0' };char imagepath[400] = { '\0' };for (i = 0; i < imagenum; i++){sprintf(imagename, "tile_%d.png", i);							// 数字转字符串strcpy(imagepath, dirpath);										// 函数直接从头开始粘贴,自动清除开头的字符strcat(imagepath, next);strcat(imagepath, imagename);saveimage(imagepath, &pentable[i]);								// 批量导出贴图}savepersonalfile(dirpath, pentablev2);								// 创建默认文件夹并保存自定义贴图
}
// 读取 DLC 继续开发
void loadgamemap(int** map, int* gamemapi, int* gamemapj, IMAGE* pentable, int* pixnum, int* imagenum)
{FILE* fp;int i = 0;int j = 0;char dirpath[400] = { '\0' };char filepath[400] = { '\0' };for (i = 0; i < 100; i++){sprintf(dirpath, "DLC%d", i);if (access(dirpath, 0) == 0) 										// 检查 DLC 是否存在,存在为 0{break;}}if (i == 100)															// 100 次查找失败,则返回,不再读取return;char filename[400] = "gamemap.txt";const char* next = "./";strcat(filepath, dirpath);strcat(filepath, next);strcat(filepath, filename);fp = fopen(filepath, "r");											// 读取 .txt 文件fscanf(fp, "注意此导出的游戏文件为按键 F1 后自动生成 修改汉语字符或者英文字符 或导致该 .txt 文件不可读取\n");fscanf(fp, "warning this saved gamefile is automatically create after F1 pressed change Chinesse character or English character lead to read failed");fscanf(fp, "pixnum %d\n", pixnum);									// 正方形瓦片贴图边长信息:单位:像素fscanf(fp, "imagenum %d\n", imagenum);								// 瓦片个数char imageindix[400] = { '\0' };char imagepath[400] = { '\0' };for (i = 0; i < *imagenum; i++){fscanf(fp, "%s\n", imageindix);strcpy(imagepath, dirpath);strcat(imagepath, next);strcat(imagepath, imageindix);loadimage(&pentable[i], imagepath, *pixnum, *pixnum, false);	// 批量导入贴图}fscanf(fp, "gamemapi %d gamemapj %d\n", gamemapi, gamemapj);for (i = 0; i < *gamemapi; i++){fscanf(fp, "%d", &map[i][j]);for (j = 0; j < *gamemapj; j++){fscanf(fp, " %d", &map[i][j]);}fscanf(fp, "\n");}fclose(fp);
}
// 检查边界
inline void checkboundary(int* bkgameleft, int* bkgametop, int gamelimitright, int gamelimitbottom, int* bkmeshgameleft, int* bkmeshgametop, int* meshlimitright, int* meshlimitbuttom, int bkmeshcopywidth, int bkmeshcopyheight)
{if (*bkgameleft < 0)												// 网格越界检测并调整*bkgameleft = 0;else if (*bkgameleft > gamelimitright)								// 超过九宫格的边界就会刷新,所以要 gamelimiright = mapwidth - bkmeshcopywidth,这样就不超过九宫格边界了。*bkgameleft = gamelimitright;if (*bkgametop < 0)*bkgametop = 0;else if (*bkgametop > gamelimitbottom)								// 超过九宫格的边界就会刷新,所以要 gamelimitbottom = mapheight - bkmeshcopyheight,这样就不超过九宫格边界了。*bkgametop = gamelimitbottom;if (*bkgameleft < *bkmeshgameleft)									// 更新游戏采样区坐标,一些简单换算,由于频繁调用函数在这里产生了明显的卡顿影响,所以这里就不再封装成函数{*bkmeshgameleft -= bkmeshcopywidth;								// 追随玩家,九宫格左移一格宫格,则界限也左移一格宫格的像素宽度*meshlimitright -= bkmeshcopywidth;							// 缓存区网格左上角的像素坐标在右界限,移动相同距离,这里改完,发现需要在初始化时规定好边界距离整好是四宫格的宽高}else if (*bkgameleft > *meshlimitright){*meshlimitright += bkmeshcopywidth;*bkmeshgameleft += bkmeshcopywidth ;							// 缓存区网格左上角的像素坐标在右界限,移动相同距离,这里改完,发现需要在初始化时规定好边界距离整好是四宫格的宽高}if (*bkgametop < *bkmeshgametop){*bkmeshgametop -= bkmeshcopyheight;*meshlimitbuttom -= bkmeshcopyheight;							// 缓存区网格左上角的像素坐标在右界限,移动相同距离,这里改完,发现需要在初始化时规定好边界距离整好是四宫格的宽高}else if (*bkgametop > *meshlimitbuttom){*meshlimitbuttom += bkmeshcopyheight;*bkmeshgametop += bkmeshcopyheight;								// 缓存区网格左上角的像素坐标在右界限,移动相同距离,这里改完,发现需要在初始化时规定好边界距离整好是四宫格的宽高}
}
// 性能:CPU 2% 占有率,峰值 1.20GHz,核显 GPU 10% 使用率
inline void animation(int characterflag, int bkgameleft, int bkgametop, int bkmeshgameleft, int bkmeshgametop, int bkmeshdeskleft, int bkmeshdesktop)
{static int i = 1;static int x = 10;static int y = 10;if (i % 3 == 0){x = bkmeshdeskleft + bkgameleft - bkmeshgameleft;y = bkmeshdesktop + bkgametop - bkmeshgametop;i %= 125;														// i 的上限 * 放大倍数 不超过 255switch (characterflag)											// 选取颜色{case 1:setfillcolor(RGB(i * 2, i * 2, 0));break;case 2:setfillcolor(RGB(i * 2, 0, i * 2));break;case 3:setfillcolor(RGB(i * 2, 0, 0));break;case 4:setfillcolor(RGB(0, i * 2, 0));break;case 5:														// 如果没有按键,则使用默认颜色setfillcolor(RGB(0, 0, i * 2));break;}fillrectangle(x, y, x + 30, y + 30);}i++;
}
// 从默认文件夹中读取自定义图片
void loadfile(IMAGE*** pentablev2,int pixnum)
{char brick[100] = "aa_birck_6_family";char ground[100] = "ab_ground_7_family";char change[100] = "ac_change_8_family";char trick[100] = "ad_trick_9_family";char next[100] = "./";char png[100] = "*.png";loadfile_scanf(brick, next, png, pentablev2[0],pixnum);								// 加载用于当砖头类型的图片loadfile_scanf(ground, next, png, pentablev2[1],pixnum);loadfile_scanf(change, next, png, pentablev2[2],pixnum);loadfile_scanf(trick, next, png, pentablev2[3],pixnum);
}
// 加载自定义图片
void loadfile_scanf(char* dirname, char* next, char* kind, IMAGE** pentablev2,int pixnum)
{// 文件存储信息结构体struct _finddata_t fileinfo;// 保存文件句柄			// https://blog.csdn.net/hemmingway/article/details/73716980long long fHandle;		// win 10 win 11 fHandle 要从long 改成long long 否则闪退														
//	long fHandle;// 文件数记录器char dirpath[100];strcpy(dirpath, dirname);if (access(dirpath, 0) == -1)													// 检查文件夹是否存在,不存在为 -1{mkdir(dirpath);return;}else{int i = -1;																	// 记录文件数量char kindpath[100];strcpy(kindpath, dirpath);strcat(kindpath, next);strcat(kindpath, kind);if ((fHandle = _findfirst(kindpath, &fileinfo)) == -1L) 					// *是通配符,默认在当前文件夹内查找文件,这里查找 .png 文件{printf("当前目录: %s 下没有所需文件\n", dirname);return;}else{char path[100];do{i++;printf("在%s 下找到文件:%s,文件大小:%ld bit\n", dirname, fileinfo.name, fileinfo.size);strcpy(path, dirname);strcat(path, next);strcat(path, fileinfo.name);while (pentablev2[i] != NULL){i++;}// 导入新图片这里需要改动,自适应图片,用于各种大小图片加入,配合剪切pentablev2[i] = new IMAGE(pixnum, pixnum);loadimage(pentablev2[i], path, pixnum, pixnum);								// 根据名称读取文件}while (_findnext(fHandle, &fileinfo) == 0);}// 关闭文件_findclose(fHandle);printf("文件数量:%d\n", i + 1);}
}
// 在目标 DLC 里创建四个文件夹并保存
void savepersonalfile(char* DLC, IMAGE*** pentablev2)
{char brick[100] = "aa_birck_6_family";char ground[100] = "ab_ground_7_family";char change[100] = "ac_change_8_family";char trick[100] = "ad_trick_9_family";char next[100] = "./";char png[100] = ".png";if (access(DLC, 0) == -1)														// 检查文件夹是否存在,不存在为 -1{mkdir(DLC);}char sign[10] = {};strcpy(sign, "6");savelocal(DLC, brick, next, png, sign, pentablev2[0]);strcpy(sign, "7");savelocal(DLC, ground, next, png, sign, pentablev2[1]);strcpy(sign, "8");savelocal(DLC, change, next, png, sign, pentablev2[2]);strcpy(sign, "9");savelocal(DLC, trick, next, png, sign, pentablev2[3]);
}
// 保存自定义文件
void savelocal(char* DLC, char* dirname, char* next, char* kind, char* sign, IMAGE** files)
{char dirpath[100] = "";strcpy(dirpath, DLC);															// 字符串拼接出相对路径strcat(dirpath, next);strcat(dirpath, dirname);if (access(dirpath, 0) == -1)													// 检查 DLC 内的指定文件夹是否存在,不存在为 -1{mkdir(dirpath);}char filepath[100];char filepa[100];char num[10];strcpy(filepath, dirpath);														// 字符串拼接出文件名前缀strcat(filepath, next);strcat(filepath, sign);for (int i = 0; i < 10; i++){sprintf(num, "%d", i);strcpy(filepa, filepath);													// 从头粘贴,可以覆盖之前的信息,不受上一次保存的影响strcat(filepa, num);strcat(filepa, kind);if (files[i] != NULL){saveimage(filepa, files[i]);printf("file save %s\n", filepa);}}
}

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

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

相关文章

4.Docker本地镜像发布至阿里云仓库、私有仓库、DockerHub

文章目录 0、镜像的生成方法1、本地镜像发布到阿里云仓库2、本地镜像发布到私有仓库3、本地镜像发布到Docker Hub仓库 Docker仓库是集中存放镜像的地方&#xff0c;分为公共仓库和私有仓库。 注册服务器是存放仓库的具体服务器&#xff0c;一个注册服务器上可以有多个仓库&…

项目开发规范

Restful REST&#xff0c;表述性状态转换&#xff0c;他是一种软件架构风格 使用URL定位资源&#xff0c;HTTP动词描述操作 根据发出请求类型来区分操作 GET&#xff1a; 查询id为1的用户POST&#xff1a;新增用户PUT&#xff1a;修改用户DELETE&#xff1a;删除id为1的用户 …

springboot权限验证学习-上

创建maven项目 创建父工程 这类项目和原来项目的区别在于&#xff0c;打包方式是pom 由于pom项目一般都是用来做父项目的&#xff0c;所以该项目的src文件夹可以删除掉。 创建子工程 子工程pom.xml 父工程pom.xml 添加依赖 父工程导入依赖包 <!--导入springboot 父工程…

18.Nacos配置管理-微服务读取Nacos中的配置

需要解决的问题 1.实现配置更改热更新&#xff0c;而不是改动了配置文件还要去重启服务才能生效。 2.对多个微服务的配置文件统一集中管理。而不是需要对每个微服务逐一去修改配置文件&#xff0c;特别是公共通用的配置。 配置管理服务中的配置发生改变后&#xff0c;回去立…

病理组学+配对 mIHC 验证+转录组多组学

目录 病理DeepRisk网络模型构建 DPS和新辅助化疗 mIHC 验证 STAD转录组层面 病理DeepRisk网络模型构建 自有数据训练&#xff0c;TCGA数据进行验证&#xff0c;然后配对mIF验证&#xff0c;最后还在转录组层面分析。 该模型基于中山数据集&#xff08;n 1120&#xff09…

【AIGC调研系列】Sora级别的国产视频大模型-Vidu

Vidu能够达到Sora级别的标准。Vidu被多个来源认为是国内首个Sora级别的视频大模型[2][3][4]。它采用了团队原创的Diffusion与Transformer融合的架构U-ViT&#xff0c;能够生成长达16秒、分辨率高达1080P的高清视频内容[1][6]。此外&#xff0c;Vidu的一致性、运动幅度都达到了S…

【Spring】IOC/DI中常用的注解@Lazy、@Scope与@Conditional

目录 1、Lazy 懒加载bean 1.1、与component配合使用 1.2、与Bean注解配合使用 2、Scope bean的作用域 2.1、不指定Scope 2.2、指定Scope为 prototype 3、Conditional 条件注解 1、Lazy 懒加载bean Lazy用于指定单例bean实例化的时机&#xff0c;在没有指定此注解时&…

基于SpringBoot+Vue校园竞赛管理系统的设计与实现

项目介绍&#xff1a; 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;竞赛信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行…

安卓常用组件(启停活动页面、活动之间传递信息、收发应用广播、操作后台服务)

启停活动页面 Activity的启动和结束 页面跳转可以使用startActivity接口&#xff0c;具体格式为startActivity(new Intent(this, 目标页面.class));。 关闭一个页面可以直接调用finish();方法即可退出页面。 Activity的生命周期 页面在安卓有个新的名字叫活动&#xff0c;因…

微软ML Copilot框架释放机器学习能力

摘要&#xff1a;大模型席卷而来&#xff0c;通过大量算法模型训练推理&#xff0c;能根据人类输入指令产生图文&#xff0c;其背后是大量深度神经网络模型在做运算&#xff0c;这一过程称之为机器学习&#xff0c;本文从微软语言大模型出发&#xff0c;详解利用大型语言模型&a…

取得Claude模型的Key

目录 1.登录Claude \ Anthropic。需要美丽国IP。 2.取得Key 3.可用模型 4.帮助文档地址 5.使用这个key 6.取得Credit 1.登录Claude \ Anthropic。需要美丽国IP。 2.取得Key 3.可用模型 4.帮助文档地址 https://docs.anthropic.com/claude/docs/intro-to-claude --------…

前后端分离,使用sa-token作为安全框架快速搭建一个微服务项目

之前写过一个单体项目&#xff0c;现在想把它升级为微服务项目。在拆分升级的过程中发现了很多问题&#xff0c;本次就来记录一下遇到的问题和解决方法。&#xff08;这篇文章只是记录一下拆分项目的基础架构&#xff0c;并使用sa-token做微服务项目的安全框架&#xff0c;快速…

upload-labs后续(14-)

图片马 在图片中加入木马&#xff0c;然后上传让浏览器解析&#xff0c;达到上传木马的目的 制作图片马&#xff1a;可以在notepad或者winhex中打开文件&#xff0c;在文件头中加入图片的文件头&#xff0c;再在文件末尾加入木马即可。 图片文件头如下&#xff1a; 1.Png图片…

学生党学习亚马逊云科技AWS、求职上岸就申AWS Cloud Club队长!

毕业了怎么找工作&#xff1f;该怎么学AWS&#xff1f;这是同学们最关心的问题。最近AWS推出的Cloud Club校园社区计划就可以完美解决这些问题&#xff01; &#x1f3eb;AWS校园社区计划是在学校构建校园社团(全球学校)&#xff0c;带着大家学最热的开发、AI/ML技术&#xff0…

IDEA主题美化【保姆级】

前言 一款好的 IDEA 主题虽然不能提高我们的开发效率&#xff0c;但一个舒适简单的主题可以使开发人员更舒适的开发&#xff0c;时常换一换主题可以带来不一样的体验&#xff0c;程序员的快乐就这么简单。话不多说&#xff0c;先上我自己认为好看的主题设置。 最终效果图: 原…

《机器学习by周志华》学习笔记-线性模型-03

1、多分类学习 1.1、背景 我们在上一节介绍了「线性判别分析(LDA)」,LDA的从二分类任务可以推广到多分类任务中。 而现实中常遇到的多分类学习任务。有些二分类的学习方法可以直接推广到多分类,但是更多情况下是基于一些策略,利用二分类学习器来解决多分类的问题。 1.…

OpenVINO安装教程 Docker版

从 Docker 映像安装IntelDistribution OpenVINO™ 工具套件 本指南介绍了如何使用预构建的 Docker 镜像/手动创建镜像来安装 OpenVINO™ Runtime。 Docker Base 映像支持的主机操作系统&#xff1a; Linux操作系统 Windows (WSL2) macOS(仅限 CPU exectuion) 您可以使用预…

机器学习作业3____决策树(CART算法)

目录 一、简介 二、具体步骤 样例&#xff1a; 三、代码 四、结果 五、问题与解决 一、简介 CART&#xff08;Classification and Regression Trees&#xff09;是一种常用的决策树算法&#xff0c;可用于分类和回归任务。这个算法由Breiman等人于1984年提出&#xff0c;它…

如何让Ubuntu上的MySQL开发更便捷

前言 作为一款开源的数据库开发与数据库管理协同工具&#xff0c;&#xff08;OceanBase Developer Center&#xff0c;简称ODC&#xff09;&#xff0c;针对MySQL数据源&#xff0c;已提供了涵盖SQL开发、变更风险管控、数据安全合规等多个方面的功能&#xff0c;从而为MySQL…

新媒体运营-----短视频运营-----PR视频剪辑----视频调色

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1. Lumetri调色&#xff0c;明暗对比度2. Lumetri调色&#xff0c;创意与矢量示波器2.1 创意2.2 矢量示波器 3. L…