W801学习笔记十七:古诗学习应用——上

硬件驱动以及软件架构大体上已经完成,尚存一些遗漏之处,后续会寻找合适的时机进行补充。自此章起,将正式迈入软件应用阶段,尤其是游戏开发领域。

关于第一个应用,此前已有一些构想:

其一,随机选取一首唐诗,然后随机隐藏其中的一句。

其二,玩家从四个备选句子中挑选出一个正确答案。

现在开始:

一、诗词数据清洗及格式转换

        诗词数据的获取渠道很多,无论哪里来的,基本都要整理一下格式。

       1、先从网上某某地方下载唐诗300首。统一格式为:

标题行

作者行

正文N行

感遇其一
张九龄
孤鸿海上来,
池潢不敢顾;
侧见双翠鸟,
巢在三珠树。
矫矫珍木巅,
得无金丸惧?
美服患人指,
高明逼神恶。
今我游冥冥,
弋者何所慕?
感遇其二
张九龄
兰叶春葳蕤,
桂华秋皎洁;
欣欣此生意,
自尔为佳节。
谁知林栖者?
闻风坐相悦,
草木有本心,
何求美人折?
感遇其三
张九龄
幽人归独卧,
滞虑洗孤清,
持此谢高鸟,
因之传远情。
日夕怀空意,
人谁感至精?
飞沈理自隔,
何所慰吾诚?

        2、将来数据要保存在SD卡中,内存用PSRAM也是足够,所以我们以控件换时间,简化数据结构,统一每行的宽度:

标题行 64字节

作者行 64字节

正文N行 64字节

        3、为数据做一个索引:

格式为

4、扩展字符集

之前我们在代码中的字符串,编译时使用UFT编码。故而显示时需要先将UTF转为GB2312。

但是这里我们就不需要UTF,直接采用gb2312编码格式。

但是GB2312只包含国标一、二级汉字,而古诗词中含有一些三级汉字。所以我们实际使用的是gb2312的超集gb18030。

另一个问题是,gt30字库芯片中并没有三级汉字!所以我们在处理数据的时候,要把三级汉字挑出来,单独生成字库文件。

以上2、3、4 几步需要另外写个工具完成。

 5、现在可以用宏定位诗词了。

//读取数据指定行
#define dataLine(idx) ((const char*)DataBuff+((idx) * 64))
//获取索引指定诗所在数据行数
#define dataLineIdx(idx) (((u16*)DataBuffIndex)[(idx)*2+2])
//获取索引指定诗句子总数
#define dataLineCount(idx) (((u16*)DataBuffIndex)[(idx)*2+3])

//获取指定诗指定句子所在行数
#define TangshiLineIdx(x,y)  (dataLineIdx(x)+ y + 2 )
//获取指定诗指定句子所在数据位置
#define TangshiLine(x,y)  (dataLine(dataLineIdx(x)+ y + 2 ))
//获取指定诗标题所在数据位置
#define TangshiLineTitle(x)  (dataLine(dataLineIdx(x)))
//获取指定诗作者所在数据位置
#define TangshiLineAuthor(x)  (dataLine(dataLineIdx(x)+ 1))

二、生成问题选项

        1、先定义问题的结构:

typedef struct {
	uint16_t question; //问题诗索引
	uint8_t line;  //问题句子所在的行
    u16 answer [4];  // 4个选项对应的行
	uint8_t ans;  //正确选项
	
} TangShiQuestion;

question:随机选择一首诗做问题,比如第1首。

line:诗有若干句,我们以其中某一句作为问题进行提问。

answer [4]: 4个备选选项对应的句子位置。

ans: 正确答案对应的选项。

        2、根据上面定义,生成问题:

                i。随机选择一首诗(question)和一个句子(line),要求句子长度在15 - 25 之间。注意每个字两个字节。

                ii。随意一个选项作为答案ans

                iii。把每个选择指向每一个句子。要求句子长度相同。如果是正确选项,则使用原句子。

void YuWenTS::createTSQuestion()
{
	u8 len=0;
	offsetY=0;
	do{
		currentQuestion->question = ran_max(YuWenCount);
		currentQuestion->line = ran_max(dataLineCount(currentQuestion->question));
		len = strlen(TangshiLine(currentQuestion->question, currentQuestion->line));
	}while(len < 15 || len > 25);
	currentQuestion->ans = ran_max(4);

	for(u8 i=0;i<4;i++){
		if(i == currentQuestion->ans){
			currentQuestion->answer[i] = TangshiLineIdx(currentQuestion->question,currentQuestion->line);
		}else{
			do{
				currentQuestion->answer[i] = ran_max(YuWenItemCount);
			}while(len != strlen(dataLine(currentQuestion->answer[i])));
		}
	}
}

三、显示问题选项

        1、显示唐诗。

                i。清除显示区域

                ii。逐句显示。

如果当前行的空间无法完整呈现该句子,则另起新行。

如果当前行仅有一个字母“g”,则需手动换行,此处可根据实际情况自由定义,选择更合适的方式。

如果已到达显示区域底部,则停止显示,计算出已显示的行数,并绘制一个滚动条。

如果是问题所在的句子,则用下划线表示。

void YuWenTS::showTangshi(){
	Display_Fill_Rectangle2(TangshiBoxStartX,TangshiBoxStartY, TangshiBoxWidth, TangshiBoxHeight, BLACK);
	u16 offx = 0;
	int offy = offsetY;
	boxHeight=1;
	const char *sl;
	for(u8 i=0;i< dataLineCount(currentQuestion->question) ;i++){
		sl= TangshiLine(currentQuestion->question, i);
		u16 len = strlen(sl);
		if(sl[0] == 'g' ){
			offx = 0;
			offy += 20;
			boxHeight++;
			continue;
		}
		if(offx + len* 8 > TangshiBoxWidth){
			offx = 0;
			offy += 20;
			boxHeight++;
		}

		if(offy <0 || offy>TangshiBoxHeight-TangshiBoxLineHeight ){
			offx += len*8;
			continue;
		}

		if (i== currentQuestion->line){
				answerX=offx + TangshiBoxStartX;
				answerY=offy + TangshiBoxStartY;
				answerIdx = TangshiLineIdx(currentQuestion->question, i);
			for(u8 j=0;j< len; j++){
				Display_String(answerX+ j*8, answerY, &optionMiss, "_") ;
			}
		}else{
			Display_String(offx + TangshiBoxStartX, offy + TangshiBoxStartY, &optionLines, 
				TangshiLine(currentQuestion->question, i));
		}
		offx += len*8;
	}
	boxHeight = boxHeight*TangshiBoxLineHeight;
	
	if(boxHeight > TangshiBoxHeight){
		Display_Fill_Rectangle(TangshiBoxStartX + TangshiBoxWidth - 10, TangshiBoxStartY, 
			TangshiBoxStartX + TangshiBoxWidth -1, TangshiBoxStartY + TangshiBoxHeight, GRAY);


		double a = (double) (-offsetY) / boxHeight * TangshiBoxHeight;
		double b = (double) (-offsetY + TangshiBoxHeight) / boxHeight * TangshiBoxHeight;

		Display_Fill_Rectangle(TangshiBoxStartX + TangshiBoxWidth - 9,
			TangshiBoxStartY + a, 
			TangshiBoxStartX + TangshiBoxWidth -2,
			TangshiBoxStartY + b,
			GREEN);

	}
}

        2、显示答案选选项:

       

void YuWenTS::showTSQuetion(){
	Display_Fill_Rectangle(0,25, 480, 75, BLACK);
	Display_String(YUW_Quetion_LOC_A, &optionQuetion, TangshiLineTitle(currentQuestion->question));
	Display_String(YUW_Quetion_LOC_B, &optionZY, TangshiLineAuthor(currentQuestion->question));
	
	for(u8 i=0;i<4;i++){
		Display_Fill_Rectangle2(answerLocX, answerLocY[i]-2, SCREEN_WIDTH - answerLocX, 21 ,answerBGColor[i]);
		Display_String2(answerLocX, answerLocY[i], &optionAnswer[i], (const char *)answerTitle[i], dataLine(currentQuestion->answer[i]));
	}
}

这里,我们用到了问题及选择的几个文字格式定义:

// 字符串显示参数
typedef struct DisplayOption{
	uint8_t zk_num;
	uint16_t foreColor;
	uint16_t backColor;
	uint8_t isCenter;
	uint8_t isGB2312;
} DisplayOption;
		DisplayOption optionQuetion = {FONT_SIZE_2424, LIGHTBLUE, BLACK, 0, 1};
		DisplayOption optionZY = {FONT_SIZE_1516, GRAYBLUE, BLACK, 0, 1};
		DisplayOption optionLines = {FONT_SIZE_1516, WHITE, BLACK, 0, 1};
		DisplayOption optionMiss = {FONT_SIZE_1516, RED, DGRAY, 0, 1};
		DisplayOption optionAnswer[4] = {
			{FONT_SIZE_1516, WHITE, answerBGColor[0], 0, 1},
			{FONT_SIZE_1516, WHITE, answerBGColor[1], 0, 1},
			{FONT_SIZE_1516, WHITE, answerBGColor[2], 0, 1},
			{FONT_SIZE_1516, WHITE, answerBGColor[3], 0, 1},
			};  

四、开始游戏

        1、在初始化中,读取数据文件

int YuWenTS::scean_init(cJSON*  param){
	setKeyAdepterIntervalAll(200);
	setKeyAdepterInterval(KEY_GPIO_A, 65535);
	setKeyAdepterInterval(KEY_GPIO_B, 65535);
	setKeyAdepterInterval(KEY_GPIO_C, 65535);
	setKeyAdepterInterval(KEY_GPIO_D, 65535);
	
	。。。

		fatfs_readFile("project/tangshi300gb.txt", &DataBuff);
		fatfs_readFile("project/tangshi300index.txt", &DataBuffIndex);
		YuWenCount = dataLineIdx(-1);
		YuWenItemCount= dataLineCount(-1);

    。。。

	start();
	return 0;
}

        2、开始

void YuWenTS::start(){
    。。。
	createTSQuestion();
	showTSQuetion();
	showTangshi();
}

现在可以看看显示效果了:

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

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

相关文章

IO流-其他流:数据流,序列化流

import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream;public class DataOutputStream1 {public static void main(String[] args) {//创建一个数据输出流包装一个低级的字节输出流try (DataOutputStream dosnew DataOutp…

9.3.k8s的控制器资源(deployment部署控制器)

目录 一、deployment部署控制器概念 二、deployment资源的清单编写 三、小结 功能 使用场景 原理 四、deployment实现升级和回滚 1.编辑deployment资源清单&#xff08;v1版本&#xff09; 2.创建service资源用于访问 ​编辑 3.修改deploy清单中pod镜像版本为V2 4…

「C/C++ 01」scanf()与回车滞留问题

目录 〇、scanf()接收用户输入的流程 一、回车的缓冲区滞留问题是什么&#xff1f; 二、为什么&#xff1f; 三、四个解决方法&#xff1a; 1. 在前面的scanf()中加上\n 2. 在scanf("%c")中添加空格 3. 使用getchar()来吸收回车 4. 使用fflush()清空缓冲区 〇、scan…

2.spring security 简单入门

创建springboot 项目&#xff0c;引入spring security坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--spring security坐标--><dependency&g…

leecode每日一练

我一开始的思路也是dp&#xff0c;但是转移方程想错了&#xff0c;这个题目转移方程应该是dp[i] max(dp[i-2]nums[i],dp[i-1]) class Solution { public:int rob(vector<int>& nums) {int len nums.size();vector<int> dp(len);int ans 0;if(len>1)dp[0]…

IoTDB 入门教程 基础篇①——时序数据库为什么选IoTDB ?

文章目录 一、前文二、性能排行第一三、完全开源四、数据文件TsFile五、乱序数据高写入六、其他七、参考 一、前文 IoTDB入门教程——导读 关注博主的同学都知道&#xff0c;博主在物联网领域深耕多年。 时序数据库&#xff0c;博主已经用过很多&#xff0c;从最早的InfluxDB&a…

《Fundamentals of Power Electronics》——脉宽调制器建模

下图给出了一个简单脉宽调制器电路的原理图。 脉宽调制器电路产生一个用于指令转换器功率管导通和关断的逻辑信号δ(t)。该逻辑信号δ(t)是周期性的&#xff0c;其频率为fs&#xff0c;占空比为d(t)。脉宽调制器的输入是一个模拟控制信号vc(t)。脉宽调制器的作用是产生一个与模…

观测与预测差值自动变化系统噪声Q的自适应UKF(AUKF_Q)MATLAB编写

简述 基于三维模型的UKF&#xff0c;设计一段时间的输入状态误差较大&#xff0c;此时通过对比预测的状态值与观测值的残差&#xff0c;在相应的情况下自适应扩大系统方差Q&#xff0c;构成自适应无迹卡尔曼滤波&#xff08;AUKF&#xff09;&#xff0c;与传统的UKF相比&…

【人工智能Ⅱ】实验5:自然语言处理实践(情感分类)

实验5&#xff1a;自然语言处理实践&#xff08;情感分类&#xff09; 一&#xff1a;实验目的与要求 1&#xff1a;掌握RNN、LSTM、GRU的原理。 2&#xff1a;学习用RNN、LSTM、GRU网络建立训练模型&#xff0c;并对模型进行评估。 3&#xff1a;学习用RNN、LSTM、GRU网络做…

递归、搜索与回溯算法:记忆化搜索

例题一 解法&#xff08;暴搜 -> 记忆化搜索 -> 动态规划&#xff09;&#xff1a; 算法思路&#xff1a; 暴搜&#xff1a; a. 递归含义&#xff1a;给 dfs ⼀个使命&#xff0c;给他⼀个数 n &#xff0c;返回第 n 个斐波那契数的值&#xff1b; b. 函数体&…

JVM知识总汇(JVM面试题篇5.1)

个人理解&#xff0c;所学有限&#xff0c;若有不当&#xff0c;还请指出 1.JVM是由哪些部分组成&#xff0c;运行流程是什么&#xff1f; JVM为java虚拟机&#xff0c;是java程序的运行环境&#xff08;其实是java字节码文件的运行环境&#xff09;&#xff0c;能够实现一次编…

idea中使用GlassFish服务器启动项目

idea中使用GlassFish服务器进行测试 1.项目背景 当前在研究openMDM项目, 不过该项目不是springboot项目, 并且是使用GlassFish进行war部署的, 但是需要在idea中进行项目的二次开发,故需要进行idea启动项目并且进行开发和调试 2.GlassFish是什么 GlassFish是一个web服务器, …

分层解耦-三层架构

一、使用三层架构的原因 如果所有代码都写在controller类的方法中&#xff0c;这里面包含了数据访问的代码、逻辑处理的代码、接收请求和响应数据的代码&#xff0c;如图示例: 而我们在进行软件设计以及软件开发的时候&#xff0c;要尽量让每一个接口、类或者方法的职责更加单…

深入理解分布式事务⑧ ---->MySQL 事务的实现原理 之 MySQL 事务流程(MySQL 事务执行流程 和 恢复流程)详解

目录 MySQL 事务的实现原理 之 MySQL 事务流程&#xff08;MySQL 事务执行流程 和 恢复流程&#xff09;详解MySQL 事务流程1、MySQL 事务执行流程1-1&#xff1a;MySQL 事务执行流程如图&#xff1a; 2、MySQL 事务恢复流程2-1&#xff1a;事务恢复流程如下图&#xff1a; MyS…

西门子V90参数移植方法

西门子V90参数移植方法 应用方面 由于设备老化损坏&#xff0c;需要更换V90驱动器&#xff0c;但是由于新驱动器与旧驱动器出现版本不一样时参数就会无法直接下载到新的驱动器里面&#xff0c;为了保证更换驱动器的稳定性最好能使用之前设备的参数&#xff0c;所以写了关于V9…

车载电子电器架构 —— 如何理解和使用Update bit

车载电子电器架构 —— 如何理解和使用Update bit 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不…

2024抖音直播带货-直播间拆解:抖店运营从入门到精通(56节课)

起号原理方式以及节点处理 类目的选择选品思路 付费流量投放原理 直播间进阶玩法 课程内容 直播间搭建标准自然起号(0-1)原理 方式 以及节点处理 老号重启(0-1)原理 方式 以及节点处理 账号在线人数稳定 原理 方式 以及节点处理 账号销售额放大 原理 方式 以及节点处理…

ubuntu20配置深度学习环境

目录 系统环境安装anaconda文件的安装anaconda环境配置anaconda换中科大源常用的anaconda命令 安装显卡驱动安装CUDA下载cudnn安装pytorch更换conda源选择对应的pytorch版本进行安装 系统环境 ubuntu20&#xff0c;安装了ros noetic。 参考博客主要有&#xff1a; https://g…

【Trick】conda安装python依赖时出现429 Client Error

起因 我在根据yml文件安装依赖和创建虚拟环境时&#xff0c;出现报错&#xff0c;主要报错信息为以下两点&#xff1a; 【1】Collecting package metadata (repodata.json): failed 【2】requests.exceptions.HTTPError: 429 Client Error: Too Many Requests for url: https…

Git在无法访问github的访问方法

Git无法下载github上的源代码 代理的情况 问题&#xff1a;Failed to connect to github.com port 443 after 21100 ms: Couldnt connect to server 提示我们需要为Git单独配置代理。 查看我们的代理端口  为git 设置全局代理 git config --global http.proxy 127.0.0.1:&l…