大二必做项目贪吃蛇超详解之中篇游戏设计与分析

news2024/11/15 1:38:34

贪吃蛇系列文章

上篇win32
中篇设计与分析

文章目录

  • 贪吃蛇系列文章
  • 1. 地图
    • 1. 1 `<locale.h>`本地化
    • 1. 2 类项
    • 1. 3 setlocale函数
    • 1. 4 宽字符的打印
    • 1. 5 地图坐标
  • 2. 蛇身和食物
  • 3. 数据结构设计
  • 4. 游戏流程设计
  • 5. 核心逻辑实现分析
    • 5. 1 游戏主逻辑
    • 5. 2 GameStart
      • 5. 2. 1 SetInit
      • 5. 2. 2 Welcome
      • 5. 2. 3 InitMap
      • 5. 2. 4 InfoPrint
      • 5. 2. 5 SnakeInit
      • 5. 2. 6 CreatFood


1. 地图

我们最终的贪吃蛇界面是这个样子,可以发现这和之前写的C语言项目的最大不同就在于文字不是依次排列的,那我们的地图应该如何布置呢?
1
2
3
这里回顾一下控制台窗口的一些知识,如果想在控制台的窗口中指定位置输出信息,我们得知道该位置的坐标,所以首先介绍一下控制台窗口的坐标知识。
控制台窗口的坐标如下所示,横向的是X轴,从左向右依次增长,纵向是Y轴,从上到下依次增长
1
在游戏地图上,我们打印墙体使用宽字符□,打印蛇使用宽字符●,打印食物使用宽字符★(这些字符都可以在输入法中打出来)
普通的字符是占一个字节的,这类宽字符是占用2个字节
这里再简单的讲一下C语言的国际化特性相关的知识,过去C语言并不适合非英语国家(地区)使用,因为C语言最初假定字符都是单字节的。但是这些假定并不是在世界的任何地方都适用。

C语言字符默认是采用ASCI编码的,ASCI字符集采用的是单字节编码,且只使用了单字节中的低7位,最高位是没有使用的,可表示为0xxxxxxx;可以看到,ASCII字符集共包含128个字符,在英语国家中,128个字符是基本够用的,但是,在其他国家语言中,比如,在法语中,字母上方有注音符号,它就无法用 ASCI码表示。于是,一些欧洲国家就决定,利用字节中闲置的最高位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国家使用的编码体系,可以表示最多256个符号。但是,这里又出现了新的问题。不同的国家有不同的字母,因此,哪怕它们都使用256个符号的编码方式,代表的字母却不一样。比如,130在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel(汉),在俄语编码中又会代表另一个符号。但是不管怎样,所有这些编码方式中,0–127表示的符号是一样的,不一样的只是128–255的这一段。至于亚洲国家的文字,使用的符号就更多了,汉字就多达10万左右。一个字节只能表示256种符号,肯定是不够的,就必须使用多个字节表达一个符号。比如,简体中文常见的编码方式是 GB2312,使用两个字节表示一个汉字,所以理论上最多可以表示 256x256=65536 个符号。

后来为了使C语言适应国际化,C语言的标准中不断加入了国际化的支持。比如:加入了宽字符的类型wchar_t宽字符的输入和输出函数,加入了<locale.h>头文件,其中提供了允许程序员针对特定地区(通常是国家或者说某种特定语言的地理区域)调整程序行为的函数。

1. 1 <locale.h>本地化

<locale.h>提供的函数用于控制C标准库中对于不同的地区会产生不一样行为的部分。
在标准中,依赖地区的部分有以下几项:

数字量的格式
货币量的格式
字符集
日期和时间的表示形式

1. 2 类项

通过修改地区,程序可以改变它的行为来适应世界的不同区域。但地区的改变可能会影响库的许多部分,其中一部分可能是我们不希望修改的。所以C语言支持针对不同的类项进行修改,下面的一个宏指定一个类项:
LC_COLLATE:影响字符串比较函数 strcoll()strxfrm()
LC_CTYPE:影响字符处理函数的行为。
LC_MONETARY:影响货币格式
LC_NUMERIC:影响 printf()的数字格式。
LC_TIME:影响时间格式 strftime()wcsftime()
LC_ALL:针对所有类项修改,将以上所有类别设置为给定的语言环境。

微软开发文档对类项的介绍

1. 3 setlocale函数

char*setlocale(int category,const char* locale);

setlocale 函数用于修改当前地区,可以针对一个类项修改,也可以针对所有类项。
setlocale 的第一个参数可以是前面说明的类项中的一个,那么每次只会影响一个类项,
如果第一个参数是LC_ALL,就会影响所有的类项。
C标准给第二个参数仅定义了2种可能取值:"C"(正常模式)和""(空字符串,本地模式)。
在任意程序执行开始,都会隐藏式执行调用:

setlocale(LC ALL,"C");

当地区设置为"C"时,设置为C语言默认的模式,这时库函数按正常方式执行。
当程序运行起来后如果想改变地区,就需要调用setlocale函数。用""作为第2个参数,调用setlocale函数就可以切换到本地模式,这种模式下程序会适应本地环境。
比如:切换到我们的本地模式(汉字是宽字符)后就支持宽字符的输出等

setlocale(LC_ALL,"");//切换到本地环境

setlocale 的返回值是一个字符串指针,表示已经设置好的格式。如果调用失败,则返回空指针NULL
setlocale也可以用来查询当前地区,第二个参数设为NULL就可以了。

#include <locale.h>
#include<stdio.h>
int main()
{
	char* loc;
	loc = setlocale(LC_ALL, NULL);
	printf("默认的本地信息:%s\n", loc);

	loc = setlocale(LC_ALL, "");
	printf("设置后的本地信息: %s\n", loc);
	return 0;
}

1

1. 4 宽字符的打印

那如果想在屏幕上打印宽字符,怎么打印呢?
宽字符的字面量必须加上前缀L,否则C语言会把字面量当作窄字符类型处理。
前缀L在单引号前面,表示宽字符,宽字符的打印使用 wprintf,对应 wprintf()的占位符为 %lc
前缀L在双引号前面,表示宽字符串,对应 wprintf()的占位符为 %ls

#include <stdio.h>
#include<locale.h>
int main() {
	setlocale(LC_ALL, "");
	wchar_t ch1 = L'●';
	wchar_t ch2 = L'微';	//汉字也是宽字符
	wchar_t ch3 = L'软';	
	wchar_t ch4 = L'★';

	printf("ab\n");
	wprintf(L"%lc\n", ch1);	//不要忘记带L
	wprintf(L"%lc\n", ch2);
	wprintf(L"%lc\n", ch3);
	wprintf(L"%lc\n", ch4);
	return 0;
}

2
从输出的结果来看,我们发现一个普通字符占一个字符的位置,但是打印一个汉字字符或者宽字符,占用2个字符的位置,那么我们如果要在贪吃蛇中使用宽字符,就得计算好坐标,让X坐标一直为偶数,不然会出现一些问题。
3

1. 5 地图坐标

我们以实现一个棋盘27行,58列的棋盘分析,再围绕地图画出墙,
如下:
4

2. 蛇身和食物

初始化状态:假设蛇的长度是5,蛇身的每个节点是●,在固定的一个坐标处,比如(24,5)处开始出现蛇,连续5个节点。
注意:蛇的每个节点的x坐标必须是2个倍数,否则可能会出现蛇的一个节点有一半儿出现在墙体中,另外一般在墙外的现象,坐标不好对齐。
关于食物,就是在墙体内随机生成一个坐标(x坐标必须是2的倍数),坐标不能和蛇的身体重合,然后打印★。
2

3. 数据结构设计

在游戏运行的过程中,蛇每次吃一个食物,蛇的身体就会变长一节,那么使用链表存储蛇的信息就比较方便了,蛇的每一节其实就是链表的每个节点。每个节点只要记录好蛇身节点在地图上的坐标就行所以蛇节点结构如下:

typedef struct SnakeNode
{
	int x;
	int y;
	struct SnakeNode* next;
}SnakeNode,* pSnakeNode;

要管理整条贪吃蛇,我们再封装一个Snake的结构来维护整条贪吃蛇:
那么Snake中应该有哪些数据呢?

  1. 作为一个链表,头结点是必须要保存下来的
  2. 贪吃蛇可以改变方向,那么贪吃蛇的方向也应该要存储下来
  3. 如果我们想判断贪吃蛇是否死亡,并在游戏结束时告诉玩家是如何死亡的,可以把游戏状态也存储起来
  4. 在游戏中当然少不了分数
  5. 每次吃食物的分数,这个会随着速度的改变而改变,所以也要存储起来
  6. 食物的位置,这个贪吃蛇每次只会在场上生成一个食物,将食物的信息放在Snake中,可以方便开发
  7. 睡眠时间,这个实际上是速度,我们在游戏运行函数中再介绍

另外可以发现,方向只有四个,可以一一列举出来,所以我们可以使用枚举

enum DERCTION	//方向
{
	UP = 1, 
	DOWN,
	LEFT,
	RIGHT
};

状态实际上也是有限的:正常,撞墙,撞到自己,玩家自行退出,也可以一一列举:

enum STATUS
{
	NORMAL,
	KILL_BY_WALL,
	KILL_BY_SELF,
	ESC
};

那么Snake结构体就可以写成这样,在变量名称前加上_方便与外部变量区分

typedef struct Snake
{
	pSnakeNode _Head;	//头
	enum DERCTION _Dir;	//方向
	enum STATUS _Sta;	//状态
	pSnakeNode _Food;	//食物
	int _FoodAdd;		//食物加的分数
	int _Score;			//当前分数
	int _SleepTime;		//睡眠时间
}Snake,*pSnake;

4. 游戏流程设计

5
那么至此,前期准备基本完成,接下来我们开始完成游戏的核心逻辑

5. 核心逻辑实现分析

5. 1 游戏主逻辑

程序开始就设置程序支持本地模式,然后进入游戏的主逻辑。
主逻辑分为3个过程

游戏开始(GameStart)完成游戏的初始化
游戏运行(GameRun)完成游戏运行逻辑的实现
游戏结束(GameOver)完成游戏结束的工作

注意:setlocale(LC_ALL, "");不需要放在上面的逻辑中,因为上面的逻辑会随着游戏的再来一把反复执行,而这个代码并不需要反复运行。

<test.h>

#include"game.h"

void game()
{
	char input = 'y';		//用于判断是否再来一把
	do
	{
		Snake s = { 0 };	//做出一条蛇,将其中的内容都置为空
		srand((unsigned int)time(NULL));	//食物的生成需要随机数,我们在这里设置一下
		//开始游戏
		GameStart(&s); 
		//进行游戏
		GameRun(&s);
		//结束游戏
		GameOver(&s); 
 

		//这个代码用于解决一个bug,在后面介绍
		//这是AI给出的解决办法,就不多介绍了,<conio.h>是这两个函数需要的头文件
		//这个while循环是用来读取蛇运行的时候按下的VK虚拟键的循环,
		//把在蛇运行的时候按下的VK键的键值全面读走(包括上键的键值)
		while (_kbhit())	//_kbhit()检测是否有按键被按下
		{
			//使用 _getch() 获取按下的键
			_getch();
		}

		//如果是主动退出的,就不需要询问是否再来一把了
		if (s._Sta == ESC)
		{
			input = 'n';
			getchar();	//这个getchar用于在release版本下阻止程序直接退出
		}
		//在结束之后,询问是否要再来一把
		else
		{
			SetPos(15, 15);
			printf("要再来一把吗?(Y/y)");
			input = getchar();
			while (getchar() != '\n');	//清理'\n'
		}
	} while (input=='y'||input=='Y');
	SetPos(10, 27);		//程序退出时,会有一个xxx程序已正常退出的提示,我们让它不要破坏游戏地图
}

int main()
{
	setlocale(LC_ALL, "");//设置能输出长字符
	game();
}

在游戏过程中我们会用到非常多次SetPos来设置光标位置,至于这些位置的具体坐标可以自行不断尝试来找到较好的位置,博客中的是我个人觉得比较好的。

5. 2 GameStart

这个部分要完成的任务:

控制台窗口大小的设置
控制台窗口名字的设置
鼠标光标的隐藏
打印欢迎界面
创建地图
初始化蛇
创建第一个食物

我们将其中的每一个任务分别封装成一个函数:

void GameStart(pSnake ps)
{
	//设置控制台大小,隐藏光标
	SetInit();
	//打印欢迎界面
	Welcome();
	//布置地图
	InitMap();
	//打印介绍信息
	InfoPrint();
	//放蛇
	SnakeInit(ps);
	//放食物
	CreatFood(ps);
	//getchar();	//可以用来停止代码执行,方便调试,项目完成后要注释掉
}

5. 2. 1 SetInit

void SetInit()
{
	system("mode con cols=100 lines=30");
	system("title 贪吃蛇");

	HANDLE Houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO stdoutinfo;
	GetConsoleCursorInfo(Houtput, &stdoutinfo);
	stdoutinfo.bVisible = false;
	SetConsoleCursorInfo(Houtput, &stdoutinfo);
}

这个函数就是上一篇文章的主要内容,这里就不再赘述了。

5. 2. 2 Welcome

void Welcome()
{
	//打印欢迎界面
	SetPos(40, 15);
	wprintf(L"欢迎来到贪吃蛇");
	
	SetPos(40, 25);
	system("pause");	//这个代码相当于打印一个"请按任意键继续...",和 getchar();
	system("cls");		//清空屏幕
	
	SetPos(25, 12);
	wprintf(L"按↑↓←→控制方向,F1加速,F2减速,速度越快,分数越高");	//打印汉字也可以使用 printf
	SetPos(25, 13);
	wprintf(L"空格键暂停,ESC退出");
	
	SetPos(40, 25);
	system("pause");
	system("cls");
}

这个函数就是游戏最开始的两个界面。

5. 2. 3 InitMap

我们在这个函数中会用许多次宽字符,为了方便使用,我们可以在头文件中进行宏定义

#define WALL L'□'
#define SNAKE_BODY L'●'
#define FOOD L'★'

这样,比如我们要打印墙体,我们就可以直接:

wprintf(L"%lc",WALL);

参考代码:

void InitMap()
{
	for (int i = 0; i < 60; i += 2)
		wprintf(L"%lc",WALL);	//打印第一行

	SetPos(0, 28 - 1);
	for (int i = 0; i < 60; i += 2)
		wprintf(L"%lc", WALL);	//打印最下面一行

	for (int i = 1; i < 28; i++)
	{
		SetPos(0, i);
		wprintf(L"%lc", WALL);	//打印左边一列
	}

	for (int i = 1; i < 28; i++)
	{
		SetPos(60 - 2, i);
		wprintf(L"%lc", WALL);	//打印右边一列
	}
}

5. 2. 4 InfoPrint

可以在这里打印上自己的名字做个防伪认证:)

void InfoPrint()
{
	//打印提示信息
	SetPos(64, 15);
	printf("不能穿墙,不能咬到自己\n");
	SetPos(64, 16);
	printf("用 ↑. ↓. ←. → 分别控制蛇的移动.");
	SetPos(64, 17);
	printf("F1 为加速,F2 为减速\n");
	SetPos(64, 18);
	printf("ESC :退出游戏.space:暂停游戏.");
	SetPos(64, 20);
	printf("CSDN:fhvyxyci");
}

分数和每次吃食物的得分由于要刷新,就不在初始化的时候打印了。

5. 2. 5 SnakeInit

void SnakeInit(pSnake ps);

初始化蛇的步骤:

  1. 头插出一个有5个节点的链表
  2. 把这5个节点打印出来
  3. 初始化结构体其他数据
void SnakeInit(pSnake ps)
{
	pSnakeNode cur = NULL;
	for (int i = 0; i < 5; i++)	//初始设置长度为5
	{
		//创建一个节点,这一步也封装成 BuyNode
		pSnakeNode cur = (pSnakeNode)malloc(sizeof(SnakeNode));
		if (!cur)
		{
			perror("SnakeInit()::malloc()");
			exit(1);
		}
		cur->x = X_INIT + 2 * i;	//X_INIT和Y_INIT是宏定义,方便修改初始坐标
		cur->y = Y_INIT;
		cur->next = NULL;

		//头插
		if (!ps->_Head)
		{
			ps->_Head = cur;
		}
		else
		{
			cur->next = ps->_Head;
			ps->_Head = cur;
		}
	}

	//打印蛇
	cur = ps->_Head;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", SNAKE_BODY);
		cur = cur->next;
	}
	
	//初始化数据
	ps->_Dir = RIGHT;		//初始方向为右
	ps->_FoodAdd = 10;		//初始食物的分数为10
	ps->_Score = 0;			//初始分数
	ps->_SleepTime = 200;	//_SleppTime与速度有关
	ps->_Sta = NORMAL;		//初始状态是正常
}

5. 2. 6 CreatFood

这个函数不是只在初始化的时候调用,写的时候可能要注意一下。

void CreatFood(pSnake ps)
{
	int x = 0, y = 0;
again:
	do
	{
		x = rand() % 55 + 2;	//注意范围
		y = rand() % 26 + 1;
	} while (x % 2 == 1);	//x必须是偶数
	
	pSnakeNode cur = ps->_Head;
	while (cur)
	{
		//检查食物是否与身体重合
		if (cur->x == x && cur->y == y)
			goto again;		//当然,goto语句一般不推荐使用,你可以改造一下这里的逻辑,换成循环
		cur = cur->next;
	}
	
	//食物要有x,y坐标,那不如直接把它做成一个SnakeNode,这样还可以方便后面吃食物
	pSnakeNode food = (pSnakeNode)malloc(sizeof(SnakeNode));
	if(!food)
	{
		perror("CreatFood()::malloc()");
		exit(1);
	}
	
	food->x = x;
	food->y = y;
	food->next = NULL;
	ps->_Food = food;

	//打印食物
	SetPos(ps->_Food->x, ps->_Food->y);
	wprintf(L"%c", FOOD);
}

剩下的逻辑在后面的博客中介绍。
谢谢你的阅读,喜欢的话来个点赞收藏评论关注吧!
我会持续更新更多优质文章

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

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

相关文章

51单片机——蜂鸣器

1、蜂鸣器简介 蜂鸣器是一种将电信号转换为声音信号的器件&#xff0c;常用来产生设备的按键音、报警音等提示信号。 蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器 。 有源蜂鸣器&#xff1a;内部自带振荡源&#xff0c;将正负极接上直流电压即可持续发声&#xff0c;频率…

Python青少年简明教程:列表(List)、元组(tuple)和字典(dict)

Python青少年简明教程&#xff1a;列表&#xff08;List&#xff09;、元组&#xff08;tuple&#xff09;和字典&#xff08;dict&#xff09; 在Python中&#xff0c;列表&#xff08;List&#xff09;、元组&#xff08;Tuple&#xff09;和字典&#xff08;Dict&#xff09…

防火墙基本原理入门篇,小白一看就懂!

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330&scene21#wechat_redirect 《网安面试指南》…

基于FPGA实现SD卡的数据读写(SD NAND FLASH)

文章目录 存储芯片 SD卡 FPGA实现SD NAND读写 设计思路 程序架构 代码实现 实验结果 存储芯片 目前市面上的存储芯片&#xff0c;大致可以将其分为3大类&#xff1a; EEPROM EEPROM (Electrically Erasable Programmable read only memory)是指带电可擦可编程只读存储器…

package.json文件解析

【图书介绍】《Node.jsMongoDBVue.js全栈开发实战》-CSDN博客 《Node.jsMongoDBVue.js全栈开发实战&#xff08;Web前端技术丛书&#xff09;》(邹琼俊)【摘要 书评 试读】- 京东图书 (jd.com) 本节主要介绍package.json文件的作用及文件中各个选项的含义。 2.4.1 node_mod…

【一个简单的整数问题】

问题 TLE代码 #include <bits/stdc.h> using namespace std; const int N 1e510; int b[N]; void add(int l, int r, int d) {b[r1] - d;b[l] d; } int query(int x) {int retval 0;for(int i 1; i < x; i){retval b[i];}return retval; } int main() {int n, m…

【Kubernetes】持久卷声明 PVC

持久卷声明 PVC 1.持久卷和持久卷声明的区别2.在 Pod 中使用持久卷声明3.storageClass 详解 持久卷声明&#xff08;Persistent Volume Claim&#xff0c;PVC&#xff09;&#xff0c;是用户对 Kubernetes 存储资源的一种请求。 通过使用 持久卷声明&#xff08;PVC&#xff0…

yolo训练策略--使用 Python 和 OpenCV 进行图像亮度增强与批量文件复制

简介 在计算机视觉和深度学习项目中&#xff0c;数据增强是一种常用的技术&#xff0c;通过对原始图像进行多种变换&#xff0c;可以增加数据集的多样性&#xff0c;从而提高模型的泛化能力。本文将介绍如何使用 Python 和 OpenCV 实现图像的亮度增强&#xff0c;并将增强后的…

驱动(RK3588S)第二课时:引导程序和内核

目录 一、引导程序&#xff08;uboot&#xff09;1、uboot介绍2、A 系列通用芯片启动流程3、uboot的配置与使用 二、内核&#xff08;kernel&#xff09;1、内核的介绍2、内核的配置、裁剪和编译 三、其他知识点 一、引导程序&#xff08;uboot&#xff09; 1、uboot介绍 ubo…

PDF转CAD必备工具:四款转换神器对比推荐

随着数字办公的普及&#xff0c;我们常常需要处理不同格式的文档。在工程和设计领域&#xff0c;PDF转CAD的转换工具更是必备之选。本文将为大家介绍四款高效、便捷的PDF转CAD工具&#xff1a; 一、福昕PDF在线转换器 直通车&#xff08;粘贴到浏览器打开&#xff09;&#x…

软件测试 - 性能测试 (概念)(并发数、吞吐量、响应时间、TPS、QPS、基准测试、并发测试、负载测试、压力测试、稳定性测试)

一、性能测试 目标&#xff1a;能够对个人编写的项目进行接口的性能测试。 一般是功能测试完成之后&#xff0c;最后做性能测试。性能测试是一个很大的范围&#xff0c;在学习过程中很难直观感受到性能。 以购物软件为例&#xff1a; 1&#xff09;购物过程中⻚⾯突然⽆法打开…

PCB设计中” 铺铜的方式“导致电焊机设计失败

发现这个问题的背景 在看到网上视频设计一个小电池的点焊机很容易&#xff0c;在一些需要电力的小设计少不了点焊&#xff0c;就想尝试一下。当然其中遇到很多坑&#xff0c;后面会一起总结。这里遇到的一个小坑&#xff0c;但让人有点苦笑不得。 首先&#xff0c;点焊需要大…

【SQL】统一字符格式

目录 语法 需求 示例 分析 代码 语法 substring(column_name, start, length)用于从一个字符串中提取子字符串 column_name&#xff08;或任何字符串表达式&#xff09;&#xff1a;这是要从中提取子字符串的列名或字符串表达式。start&#xff1a;这是子字符串开始的位置…

用Python实现时间序列模型实战——Day 3: 时间序列数据预处理

一、学习内容 1. 时间序列的差分运算 差分运算&#xff1a; 差分运算是时间序列平稳化的一种方法&#xff0c;通过计算相邻时间点的差值来消除序列中的趋势和季节性成分。 一阶差分用于去除线性趋势&#xff0c;公式为&#xff1a; 其中&#xff1a; 是时间 的原始值&…

【网络安全】服务基础第一阶段——第三节:Windows系统管理基础----服务器远程管理与安全权限

服务器远程管理是一种技术&#xff0c;服务器远程管理是指通过远程连接来监控、配置和维护服务器的过程&#xff0c;而无需直接在物理服务器前操作。它允许IT管理员在不同的地点对服务器进行配置、监控和维护&#xff0c;无需物理上接触到服务器本身。这种能力对于管理分布在多…

LLaVA-MoLE:解决多模态大型语言模型指令微调中的数据冲突问题

人工智能咨询培训老师叶梓 转载标明出处 多模态大模型&#xff08;MLLMs&#xff09;通过指令微调&#xff08;instruction finetuning&#xff09;&#xff0c;能够执行各种任务&#xff0c;如理解图表、处理文档和回答基于图像的问题。但是&#xff0c;当从不同领域混合指令…

算法——K-means算法和算法改进

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 一、什么是K-means算法&#xff1f; K-means算法是一种无监督的聚类算法&#xff0c;用于将一组数据点分为K个簇&#xff08;cluster&#xff09;。其核心目标是将数据点划分到K个不同的簇中&…

CAS单点登录安装文档

CAS单点登录安装文档 目录 1、 下载CAS 2、 下载xmlsectool 3、 安装xmlsectool 4、 打包CAS 5、 部署CAS 6、 访问CAS 1.下载CAS 在CAS官方Github下载&#xff1a;https://codeload.github.com/apereo/cas/zip/v5.3.0 2.下载xmlsectool 在MVNREPOSITORY下载xm…

JavaWeb JavaScript ⑨ 正则表达式

生命的价值在于你能够镇静而又激动的欣赏这过程的美丽与悲壮 —— 24.8.31 一、正则表达式简介 正则表达式是描述字符模式的对象。正则表达式用简单的API对字符串模式匹配及检索替换&#xff0c;是对字符串执行模式匹配的强大工具。 1.语法 var pattnew RegExp(pattern,modi…

【软考】IO软件

目录 1. 说明2. 读硬盘文件3. IO 系统的层次结构与每层的主要功能4. 例题4.1 例题1 1. 说明 1.设备管理软件的设计水平决定了设备管理的效率。2.从事I0 设备管理软件的结构&#xff0c;其基本思想是分层构造&#xff0c;也就是说把设备管理软件组织成为一系列的层次。3.低层与…