推箱子大冒险(SDL/C)

news2024/10/7 12:22:47

前言

欢迎来到小K的SDL专栏第三小节,本节将为大家带来小项目~C语言SDL版坤坤推箱子详细讲解,这里也为大家上传了源码和图片资源,需要的自取看完以后,希望对你有所帮助

✨效果如下


文章目录

    • 前言
    • 一、推箱子思路讲解
    • 二、加SDL绘图代码
    • 三、完整代码
    • 四、总结


一、推箱子思路讲解

第一步,我们先用枚举把下图中的元素表示出来,分别为空地、墙、目的地、箱子、玩家

enum MyEnum { SPACE, WALL, DEST, BOX, PLAYER };

在这里插入图片描述


第二步我们就需要自己定义一个地图来使用,我这里写的推箱子就三关,所以定义了一个三页的二维数组

//定义一个地图
	int map[3][ROW][COL] =
	{
		{
			{0,0,0,0,0,0,0,0,0,0},
			{0,0,0,1,1,1,0,0,0,0},
			{0,0,0,1,2,1,0,0,0,0},
			{0,0,0,1,3,1,1,1,1,0},
			{0,1,1,1,0,3,0,2,1,0},
			{0,1,2,3,4,0,1,1,1,0},
			{0,1,1,1,1,3,1,0,0,0},
			{0,0,0,0,1,2,1,0,0,0},
			{0,0,0,0,1,1,1,0,0,0},
			{0,0,0,0,0,0,0,0,0,0}
		},
		{
			{0,0,0,0,0,0,0,0,0,0},
			{0,0,1,1,0,0,1,1,0,0},
			{0,1,2,0,1,1,0,2,1,0},
			{1,0,0,0,0,0,0,0,0,1},
			{1,0,0,3,4,0,3,0,0,1},
			{0,1,0,0,0,3,0,0,1,0},
			{0,0,1,0,3,0,0,1,0,0},
			{0,0,0,1,2,2,1,0,0,0},
			{0,0,0,0,1,1,0,0,0,0},
			{0,0,0,0,0,0,0,0,0,0}
		},
		{
			{1,1,1,1,0,0,1,1,1,1},
			{1,2,0,1,0,0,1,0,2,1},
			{1,0,0,1,0,0,1,0,0,1},
			{1,0,0,1,0,0,1,0,0,1},
			{1,0,0,1,0,0,1,0,0,1},
			{1,0,3,1,1,1,1,3,0,1},
			{1,0,0,3,4,0,3,0,0,1},
			{1,0,0,0,0,0,0,0,0,1},
			{1,2,0,0,0,0,0,0,2,1},
			{1,1,1,1,1,1,1,1,1,1}
		}
	};

第三步我们就需要一个推箱子的逻辑思维,比方说,前面是空地要怎么操作,前面是箱子又要怎么办?不要着急,和我先打两个半球~

⭐既然是推箱子,那我们肯定要知道谁推箱子,所以第一小步就是找人,这就好办了,我们直接遍历地图,无非只有两种情况,要么是人站在空地上,由于空地为0,所以只需要判断人,要么是人站在目的地上

//玩家的当前的下标
	int r = -1;
	int c = -1;
	//找到玩家的下标
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			if (map[i][k] == PLAYER || map[i][k] == DEST + PLAYER)
			{
				r = i;
				c = k;
				goto endLoop;
			}
		}
	}
endLoop:;

⭐第二小步就是推箱子的具体逻辑了,这里我们以上为例

玩家前面是箱子玩家前面是空地
箱子的前面是空地或者目的地前面空地+PLAYER,本来人站的地方减去PLAYER
⭐1,把箱子移动到前面 ⭐2,把箱子从原来的位置删掉 ⭐3.把玩家移动到箱子原来的位置⭐4,把玩家从原来的位置删掉
case SDLK_w:
			//如果玩家的前面是空地
			if (map[r - 1][c] == SPACE || map[r - 1][c] == DEST)
			{
				map[r - 1][c] += PLAYER;
				map[r][c] -= PLAYER;
			}
			//如果玩家的前面是箱子
			else if (map[r - 1][c] == BOX || map[r - 1][c] == BOX + DEST)
			{
				//如果箱子的前面是空地或者目的地
				if (map[r - 2][c] == SPACE || map[r - 2][c] == DEST)
				{
					//1,把箱子移动到前面
					map[r - 2][c] += BOX;
					//2,把箱子从原来的位置删掉
					map[r - 1][c] -= BOX;
					//3,把玩家移动到箱子原来的位置
					map[r - 1][c] += PLAYER;
					//4,把玩家从原来的位置删掉
					map[r][c] -= PLAYER;
				}
			}
			break;

完整的推箱子逻辑代码

//推箱子
void pushBox(int map[][COL], int key)
{
	//玩家的当前的下标
	int r = -1;
	int c = -1;
	//找到玩家的下标
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			if (map[i][k] == PLAYER || map[i][k] == DEST + PLAYER)
			{
				r = i;
				c = k;
				goto endLoop;
			}
		}
	}
endLoop:;

	switch (key)
	{
		case SDLK_w:
			//如果玩家的前面是空地
			if (map[r - 1][c] == SPACE || map[r - 1][c] == DEST)
			{
				map[r - 1][c] += PLAYER;
				map[r][c] -= PLAYER;
			}
			//如果玩家的前面是箱子
			else if (map[r - 1][c] == BOX || map[r - 1][c] == BOX + DEST)
			{
				//如果箱子的前面是空地或者目的地
				if (map[r - 2][c] == SPACE || map[r - 2][c] == DEST)
				{
					//1,把箱子移动到前面
					map[r - 2][c] += BOX;
					//2,把箱子从原来的位置删掉
					map[r - 1][c] -= BOX;
					//3,把玩家移动到箱子原来的位置
					map[r - 1][c] += PLAYER;
					//4,把玩家从原来的位置删掉
					map[r][c] -= PLAYER;
				}
			}
			break;
		case SDLK_s:
			if (map[r + 1][c] == SPACE || map[r + 1][c] == DEST)
			{
				map[r + 1][c] += PLAYER;
				map[r][c] -= PLAYER;
			}
			else if (map[r + 1][c] == BOX || map[r + 1][c] == BOX + DEST)
			{
				if (map[r + 2][c] == SPACE || map[r + 2][c] == DEST)
				{
					map[r + 2][c] += BOX;
					map[r + 1][c] -= BOX;
					map[r + 1][c] += PLAYER;
					map[r][c] -= PLAYER;
				}
			}
			break;
		case SDLK_a:
			if (map[r][c - 1] == SPACE || map[r][c - 1] == DEST)
			{
				map[r][c - 1] += PLAYER;
				map[r][c] -= PLAYER;
			}
			else if (map[r][c - 1] == BOX || map[r][c - 1] == BOX + DEST)
			{
				if (map[r][c - 2] == SPACE || map[r][c - 2] == DEST)
				{
					map[r][c - 2] += BOX;
					map[r][c - 1] -= BOX;
					map[r][c - 1] += PLAYER;
					map[r][c] -= PLAYER;
				}
			}
			break;
		case SDLK_d:
			if (map[r][c + 1] == SPACE || map[r][c + 1] == DEST)
			{
				map[r][c + 1] += PLAYER;
				map[r][c] -= PLAYER;
			}
			else if (map[r][c + 1] == BOX || map[r][c + 1] == BOX + DEST)
			{
				if (map[r][c + 2] == SPACE || map[r][c + 2] == DEST)
				{
					map[r][c + 2] += BOX;
					map[r][c + 1] -= BOX;
					map[r][c + 1] += PLAYER;
					map[r][c] -= PLAYER;
				}
			}
			break;
	}

}


第四步也是最后一步,我们还需要判断一下过关没有,这个好判断,我们直接遍历整个地图,看看还有没有箱子

//判断是否过关
bool passLevel(int map[][COL])
{
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			if (map[i][k] == BOX)
			{
				return false;
			}
		}
	}
	return true;
}

二、加SDL绘图代码

第一步我们先搭建一下我们的绘图框架,具体的可以看我的SDL专栏第二小节

int main(int argc,char* argv[])
{
	//初始化
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
	{
		SDL_Log("Init failed%s\n", SDL_GetError());
		return -1;
	}
	//创建窗口
	SDL_Window* window = SDL_CreateWindow("pushBox", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, SDL_WINDOW_SHOWN);
	if (!window)
	{
		SDL_Log("create window failed!%s\n", SDL_GetError());
		return -1;
	}
	//创建渲染器
	SDL_Renderer* render = SDL_CreateRenderer(window, -1, 0);
	if (!render)
	{
		SDL_Log("create Renderer failed!%s\n", SDL_GetError());
		return -1;
	}
	/*****************************/
	//接下来的操作//
	/*****************************/
	//销毁窗口
	SDL_DestroyWindow(window);
	//销毁渲染器
	SDL_DestroyRenderer(render);
	//清理并退出SDL库
	SDL_Quit();
	return 0;
}

第二步加载图片,可以看到这里准备的图片编号刚刚好就是0~6,一会在绘图上有大用,这里也有大用,这里我们直接创建一个数组,然后用SDL_snprintf在一个for循环中直接把七张图片显示加载出来
在这里插入图片描述

//加载图片
	SDL_Texture* tex[7];
	char fillname[50] = { 0 };
	for (int i = 0; i < 7; i++)
	{
		SDL_snprintf(fillname, 50, "./assets/images/%d.bmp", i);
		tex[i] = loadTexture(render, fillname);
	}
	
SDL_Texture* loadTexture(SDL_Renderer* ren, const char* fillname)
{
	SDL_Surface* sfc = SDL_LoadBMP(fillname);
	if (!sfc)
	{
		SDL_Log("loadBMP failed!%s\n", SDL_GetError());
		return NULL;
	}
	SDL_Texture* tex = SDL_CreateTextureFromSurface(ren, sfc);
	if (!tex)
	{
		SDL_Log("Texture failed!%s\n", SDL_GetError());
		SDL_FreeSurface(sfc);
		return NULL;
	}
	SDL_FreeSurface(sfc);
	return tex;
}

最后一步绘制图案,注意这里有一个小坑,二维数组横向是Y,纵向是X,而绘图窗口横向是X,纵向是Y,所以绘图的时候要刚好反一下,如下图
在这里插入图片描述

//绘制界面
void drawMap(SDL_Renderer* render, int map[][COL], SDL_Texture** texs)
{
	for (int r = 0; r < ROW; r++)
	{
		for (int c = 0; c < COL; c++)
		{
			SDL_Rect dstRect = { c * 64 ,r * 64,64,64 };
			SDL_RenderCopy(render, texs[map[r][c]], NULL, &dstRect);
		}
	}
}

三、完整代码

#include<conio.h>
#include<SDL.h>
#include<iostream>
#include<cstdio>
using namespace std;

#define ROW 10
#define COL 10

enum MyEnum { SPACE, WALL, DEST, BOX, PLAYER };

//提前声明
void pushBox(int map[][COL], int key);
bool passLevel(int map[][COL]);
SDL_Texture* loadTexture(SDL_Renderer* ren, const char* fillname);
void drawMap(SDL_Renderer* render, int map[][COL], SDL_Texture** texs);

int main(int argc,char* argv[])
{
	//初始化
	if (SDL_Init(SDL_INIT_VIDEO) != 0)
	{
		SDL_Log("Init failed%s\n", SDL_GetError());
		return -1;
	}
	//创建窗口
	SDL_Window* window = SDL_CreateWindow("pushBox", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, SDL_WINDOW_SHOWN);
	if (!window)
	{
		SDL_Log("create window failed!%s\n", SDL_GetError());
		return -1;
	}
	//创建渲染器
	SDL_Renderer* render = SDL_CreateRenderer(window, -1, 0);
	if (!render)
	{
		SDL_Log("create Renderer failed!%s\n", SDL_GetError());
		return -1;
	}
	//加载图片
	SDL_Texture* tex[7];
	char fillname[50] = { 0 };
	for (int i = 0; i < 7; i++)
	{
		SDL_snprintf(fillname, 50, "./assets/images/%d.bmp", i);
		tex[i] = loadTexture(render, fillname);
	}

	//定义一个地图
	int map[3][ROW][COL] =
	{
		{
			{0,0,0,0,0,0,0,0,0,0},
			{0,0,0,1,1,1,0,0,0,0},
			{0,0,0,1,2,1,0,0,0,0},
			{0,0,0,1,3,1,1,1,1,0},
			{0,1,1,1,0,3,0,2,1,0},
			{0,1,2,3,4,0,1,1,1,0},
			{0,1,1,1,1,3,1,0,0,0},
			{0,0,0,0,1,2,1,0,0,0},
			{0,0,0,0,1,1,1,0,0,0},
			{0,0,0,0,0,0,0,0,0,0}
		},
		{
			{0,0,0,0,0,0,0,0,0,0},
			{0,0,1,1,0,0,1,1,0,0},
			{0,1,2,0,1,1,0,2,1,0},
			{1,0,0,0,0,0,0,0,0,1},
			{1,0,0,3,4,0,3,0,0,1},
			{0,1,0,0,0,3,0,0,1,0},
			{0,0,1,0,3,0,0,1,0,0},
			{0,0,0,1,2,2,1,0,0,0},
			{0,0,0,0,1,1,0,0,0,0},
			{0,0,0,0,0,0,0,0,0,0}
		},
		{
			{1,1,1,1,0,0,1,1,1,1},
			{1,2,0,1,0,0,1,0,2,1},
			{1,0,0,1,0,0,1,0,0,1},
			{1,0,0,1,0,0,1,0,0,1},
			{1,0,0,1,0,0,1,0,0,1},
			{1,0,3,1,1,1,1,3,0,1},
			{1,0,0,3,4,0,3,0,0,1},
			{1,0,0,0,0,0,0,0,0,1},
			{1,2,0,0,0,0,0,0,2,1},
			{1,1,1,1,1,1,1,1,1,1}
		}
	};
	//当前所在关卡
	int level = 0;
	SDL_bool isDown = SDL_FALSE;
	while (!isDown)
	{
		drawMap(render, map[level], tex);
		SDL_RenderPresent(render);
		if (passLevel(map[level]))
		{
			level++;
			if (level >= 3)
			{
				std::cout << "game over,你通过了所有关卡~" << endl;
				level = 0;
				break;
			}
			std::cout << "恭喜你,通过了第" << level - 1 << "关!" << endl;
		}
		SDL_Event ev = { 0 };
		if (SDL_PollEvent(&ev))
		{
			if (SDL_QUIT == ev.type)
			{
				isDown = SDL_TRUE;
			}
			else if (ev.type == SDL_KEYDOWN)
			{
				pushBox(map[level], ev.key.keysym.sym);
			}
		}
	}

	//销毁窗口
	SDL_DestroyWindow(window);
	//销毁渲染器
	SDL_DestroyRenderer(render);
	//清理并退出SDL库
	SDL_Quit();
	return 0;
}


//绘制界面
void drawMap(SDL_Renderer* render, int map[][COL], SDL_Texture** texs)
{
	for (int r = 0; r < ROW; r++)
	{
		for (int c = 0; c < COL; c++)
		{
			SDL_Rect dstRect = { c * 64 ,r * 64,64,64 };
			SDL_RenderCopy(render, texs[map[r][c]], NULL, &dstRect);
		}
	}
}

//推箱子
void pushBox(int map[][COL], int key)
{
	//玩家的当前的下标
	int r = -1;
	int c = -1;
	//找到玩家的下标
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			if (map[i][k] == PLAYER || map[i][k] == DEST + PLAYER)
			{
				r = i;
				c = k;
				goto endLoop;
			}
		}
	}
endLoop:;

	switch (key)
	{
		case SDLK_w:
			//如果玩家的前面是空地
			if (map[r - 1][c] == SPACE || map[r - 1][c] == DEST)
			{
				map[r - 1][c] += PLAYER;
				map[r][c] -= PLAYER;
			}
			//如果玩家的前面是箱子
			else if (map[r - 1][c] == BOX || map[r - 1][c] == BOX + DEST)
			{
				//如果箱子的前面是空地或者目的地
				if (map[r - 2][c] == SPACE || map[r - 2][c] == DEST)
				{
					//1,把箱子移动到前面
					map[r - 2][c] += BOX;
					//2,把箱子从原来的位置删掉
					map[r - 1][c] -= BOX;
					//3,把玩家移动到箱子原来的位置
					map[r - 1][c] += PLAYER;
					//4,把玩家从原来的位置删掉
					map[r][c] -= PLAYER;
				}
			}
			break;
		case SDLK_s:
			if (map[r + 1][c] == SPACE || map[r + 1][c] == DEST)
			{
				map[r + 1][c] += PLAYER;
				map[r][c] -= PLAYER;
			}
			else if (map[r + 1][c] == BOX || map[r + 1][c] == BOX + DEST)
			{
				if (map[r + 2][c] == SPACE || map[r + 2][c] == DEST)
				{
					map[r + 2][c] += BOX;
					map[r + 1][c] -= BOX;
					map[r + 1][c] += PLAYER;
					map[r][c] -= PLAYER;
				}
			}
			break;
		case SDLK_a:
			if (map[r][c - 1] == SPACE || map[r][c - 1] == DEST)
			{
				map[r][c - 1] += PLAYER;
				map[r][c] -= PLAYER;
			}
			else if (map[r][c - 1] == BOX || map[r][c - 1] == BOX + DEST)
			{
				if (map[r][c - 2] == SPACE || map[r][c - 2] == DEST)
				{
					map[r][c - 2] += BOX;
					map[r][c - 1] -= BOX;
					map[r][c - 1] += PLAYER;
					map[r][c] -= PLAYER;
				}
			}
			break;
		case SDLK_d:
			if (map[r][c + 1] == SPACE || map[r][c + 1] == DEST)
			{
				map[r][c + 1] += PLAYER;
				map[r][c] -= PLAYER;
			}
			else if (map[r][c + 1] == BOX || map[r][c + 1] == BOX + DEST)
			{
				if (map[r][c + 2] == SPACE || map[r][c + 2] == DEST)
				{
					map[r][c + 2] += BOX;
					map[r][c + 1] -= BOX;
					map[r][c + 1] += PLAYER;
					map[r][c] -= PLAYER;
				}
			}
			break;
	}

}

//判断是否过关
bool passLevel(int map[][COL])
{
	for (int i = 0; i < ROW; i++)
	{
		for (int k = 0; k < COL; k++)
		{
			if (map[i][k] == BOX)
			{
				return false;
			}
		}
	}
	return true;
}

//加载图片
SDL_Texture* loadTexture(SDL_Renderer* ren, const char* fillname)
{
	SDL_Surface* sfc = SDL_LoadBMP(fillname);
	if (!sfc)
	{
		SDL_Log("loadBMP failed!%s\n", SDL_GetError());
		return NULL;
	}
	SDL_Texture* tex = SDL_CreateTextureFromSurface(ren, sfc);
	if (!tex)
	{
		SDL_Log("Texture failed!%s\n", SDL_GetError());
		SDL_FreeSurface(sfc);
		return NULL;
	}
	SDL_FreeSurface(sfc);
	return tex;
}

四、总结

本节带来的推箱子小游戏不仅可以让你对数组等语法更加熟练,也会让你的图形库知识更上一层楼,本节就到这里啦~期待下一节和大家的相遇🌞

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

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

相关文章

chatgpt赋能python:Python字符串颠倒:如何用Python实现字符串颠倒操作

Python字符串颠倒&#xff1a;如何用Python实现字符串颠倒操作 在Python中&#xff0c;字符串颠倒是一种常见的操作。我们可以使用Python内置的方法和函数来轻松地完成字符串颠倒操作。在本篇文章中&#xff0c;我们将深入探讨Python字符串颠倒操作的实现方法。 什么是字符串…

Fiddler抓包MuMu模拟器中app的数据

第1步&#xff1a;下载Fiddler&#xff0c;并安装。 下载链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/105XDJ_KD54PUnsHM-BsZLQ?pwd0t8q 提取码&#xff1a;0t8q 第2步&#xff1a;配置Fiddler。 点击“Tools”→点击“Options” → 重启生效 设置HTTPS: …

chatgpt赋能python:Python如何排序

Python 如何排序 Python 是一门强大的编程语言&#xff0c;拥有许多常用的排序算法。在本文中&#xff0c;我们将介绍Python 中的常用排序算法&#xff0c;包括插入排序、选择排序、冒泡排序、快速排序和归并排序。 插入排序 插入排序是最简单的排序算法之一。它将列表分为已…

chatgpt赋能python:Python字符串的首字母小写是什么?

Python字符串的首字母小写是什么&#xff1f; Python是一种广泛使用的编程语言&#xff0c;被许多工程师和开发者用于各种应用程序的开发。字符串操作是Python中常见的任务之一&#xff0c;其中一个常见的需求是将字符串中的第一个字符小写。本文将介绍如何在Python中实现这个…

mysql window安装教程

官网下载 https://dev.mysql.com/downloads/mysql/解压后根目录新建mysqlConfig.ini[mysqld] # 设置3306端口 port3306 # 设置mysql的安装目录 basedirE:\Soft\MySQL\mysql-8.0.27-winx64 # 设置mysql数据库的数据的存放目录 datadirE:\Soft\MySQL\mysql-8.0.27-winx64\da…

【实现一个简单的前后端交互页面】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 客户端与服务器之间的通信流程 理解当前案例…

【短信业务】阿里云可以发送带变量的链接短信

阿里云配置短信业务1.在账号管理中的 Accesskey管理中申请accessKeyId和accessKeySecret2.进入短信服务管理3.进入快速学习和测试申请签名&#xff1a;按照要求填写信息&#xff0c;审核一般两三个小时左右申请模板 &#xff1a;按照要求填写信息&#xff0c;审核一般两三个小时…

python+django高校就业求职招聘信息服务系统_8ryq3

本文论述了高校就业信息服务系统的设计和实现&#xff0c;该网站从实际运用的角度出发&#xff0c;运用了计算机网站设计、数据库等相关知识&#xff0c;基于系统管理和Mysql数据库设计来实现的&#xff0c;网站主要包括用户、企业、人才库、面试邀请、岗位分类、招聘信息、应聘…

【IM群发推内容参考iMessage苹果推】下面的 mailto、news 和 isbn URI 都是 URN 的示例。

要实现APNs认证以用于iMessage推送&#xff0c;以下是一样平常的步调&#xff1a; 建立苹果开发者账户&#xff1a;确保你具有苹果开发者账户。若是没有&#xff0c;请注册一个开发者账户。 登录到苹果开发者中间&#xff1a;利用你的开发者账户登录到苹果开发者中心&#xf…

凭据收集工具 Legion 瞄准额外的云服务

黑客在受感染的 Web 服务器上部署的名为 Legion 的商业恶意软件工具最近已更新&#xff0c;可以提取额外云服务的凭据以通过 SSH 进行身份验证。 这个基于 Python 的脚本的主要目标是获取存储在电子邮件提供商、云服务提供商、服务器管理系统、数据库和支付系统的配置文件中的…

【Python】循环语句 ③ ( while 嵌套循环案例 - 打印乘法表 | print 不换行打印 | tab 制表符 )

文章目录 一、print 不换行打印二、tab 制表符三、while 嵌套循环案例 - 打印乘法表 一、print 不换行打印 使用 print 函数打印字符串 , 会进行自动换行 ; Python 中的 print 函数原型如下 : def print(self, *args, sep , end\n, fileNone): 默认情况下 , print 打印字符串…

MVC模式和三层架构(附综合案例增删改查)

MVC模式和三层架构 MVC模式 MVC 是一种分层开发的模式&#xff0c;其中&#xff1a; M&#xff1a;Model&#xff0c;业务模型&#xff0c;处理业务 V&#xff1a;View&#xff0c;视图&#xff0c;界面展示 C&#xff1a;Controller&#xff0c;控制器&#xff0c;处理请求…

【ISO14229_UDS刷写】-5-$38诊断服务RequestFileTransfer理论部分

总目录&#xff1a;&#xff08;单击下方链接皆可跳转至专栏总目录&#xff09; 《UDS/OBD诊断需求编辑工具》总目录https://blog.csdn.net/qfmzhu/article/details/123697014 目录 1 $0x38 RequestFileTransfer诊断服务描述 2 0x38服务请求消息 2.1 0x38服务请求消息定义…

MongoDB window安装教程

官网下载 MongoDB&#xff1a;https://www.mongodb.com/try/download/community MongoDB shell脚本&#xff1a;https://www.mongodb.com/try/download/shell&#xff0c;下载后解压到MongoDB安装目录创建数据库文件的存放位置 在data文件夹下创建 db 文件夹&#xff08;启动 …

【composer】如何在本地开发、调试Composer包

1、准备工作 创建两个空文件夹 |- TestProject # 用于composer引入测试 |- TestPackage # composer的自定义扩展包1.1 初始化 在TestProject和TestPackage分别执行&#xff1a; composer init一路默认或者自己按需修改引导中的参数完成composer初始化 例如&#xff1a; Pa…

C++11常用的一部分新特性

C11 统一的列表初始化&#xff5b;&#xff5d;初始化std::initializer_list 声明autodecltypenullptr STL中一些变化新容器已有容器的新接口 右值引用和移动语义左值引用和右值引用右值引用使用场景和意义右值引用引用左值及其一些更深入的使用场景分析完美转发 新的类功能默认…

【ISO14229_UDS刷写】-4-$37诊断服务RequestTransferExit理论部分

总目录&#xff1a;&#xff08;单击下方链接皆可跳转至专栏总目录&#xff09; 《UDS/OBD诊断需求编辑工具》总目录https://blog.csdn.net/qfmzhu/article/details/123697014 目录 1 $0x37 RequestTransferExit诊断服务描述 2 0x37服务请求消息 2.1 0x37服务请求消息定义…

经典 SQL 数据库笔试题及答案整理

马上又是金三银四啦&#xff0c;有蛮多小伙伴在跳槽找工作&#xff0c;但对于年限稍短的软件测试工程师&#xff0c;难免会需要进行笔试&#xff0c;而在笔试中&#xff0c;基本都会碰到一道关于数据库的大题&#xff0c;今天这篇文章呢&#xff0c;就收录了下最近学员反馈上来…

PLX31-EIP-MBTCP 以太网/IP到Modbus TCP/IP

PLX31-EIP-MBTCP ProSoft Technology的EtherNet/IP to Modbus TCP/IP通信网关允许在支持EtherNet/IP的控制器或设备与Modbus TCP/IP控制器或设备之间进行高速双向数据传输。 我们的Modbus TCP/IP驱动程序具有多种客户端和服务器功能&#xff0c;可实现更快的数据传输。此外&a…

策略路由+静态路由+ip link+healthcheck检测外网物理链路提高网络的可靠性

一、适用环境 1、外网链路有防火墙Firewall出口&#xff0c;外网也有路由器Router出口。 2、用户量大需要多条外网链路负载均衡&#xff0c;多条链路也可以互为主备。 3、有ip专线网络&#xff08;上下行对称&#xff09;与拨号光纤&#xff08;上下行非对称&#xff09;网络配…