HarmonyOS 3.1上实现游戏万能卡片

舒尔特方格游戏,是注意力训练方法之一,可以帮助孩子纠正上课分心走神、回家做作业拖拉毛病,但不能贪玩哦,玩多了,对眼睛,视力不好。
①消息通知栏,通知用户当前最优成绩,也就是当前最快时间。
②元服务卡片,在桌面上添加 2x2 或 2x4 或 2x4 规格元服务卡片,能看到不同布局随机数字,根据左上角红色字提示,快速完成点击,用时最少为最优成绩。
③1x2 规格元服务卡片,只显示当前最优成绩,点击可以查看 2x2 或 2x4 或 2x4 规格元服务卡片最快用时游戏记录。
关系型数据库,用于查询,添加,更新,删除元服务卡片信息和各卡片游戏用时成绩数据。
效果图如下:
知识点
消息通知:提供通知管理的能力,包括发布、取消发布通知,创建、获取、移除通知通道,订阅、取消订阅通知,获取通知的使能状态、角标使能状态,获取通知的相关信息等。 关系型数据库:关系型数据库基于 sqlite 组件提供了一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查等接口,也可以直接运行用户输入的 sql 语句来满足复杂的场景需要。 元服务卡片开发:卡片是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达、减少体验层级的目的。 卡片提供方:显示卡片内容,控制卡片布局以及控件点击事件。 卡片使用方:显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。 卡片管理服务:用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等。
软件要求:
deveco studio 版本:deveco studio 3.1 release 及以上版本。
harmonyos sdk 版本:api version 9 及以上版本。
硬件要求:
设备类型:华为手机 3.1 系统或运行在 deveco studio 上的远程模拟器api9。
harmonyos 系统:3.1.0 developer release 及以上版本。
卡片讲解
1x2 卡片主要显示所有卡片最优成绩,也就是用时最少的,同时点击卡片,跳转到主界面,查看卡片游戏记录。
2x2 卡片显示的是 3x3 布局随机生成 1~9 数字,正上方标题显示挑战成功或失败提示,左上角红色字提示下一个要点击的数字按钮,右上角显示当次完成后用时和此卡片用时最少成绩。
当此次的用时少于最好用时,挑战成功,并更新数据库此卡片记录,如果此次用时大于最好用时,提示挑战失败,不用更新数据库。
2x4 卡片显示的是 7x2 布局随机生成 1~14 数字,显示内容和游戏规则与 2x2 卡片一样。
4x4 卡片显示的是 6x6 布局随机生成 1~36 数字,显示内容和游戏规则与 2x2 卡片一样。
首次启动或点击 1x2 卡片进入到主界面,主界面显示各卡片游戏成绩记录。
通知显示效果:
代码讲解
数据库操作后端项目结构图:
formdata.ets 实体类代码如下:
export default class formdata {  // 卡片id  formid: string;  // 距阵数 3x3  matrixnum: string;  // 最优成绩  bestscore: number;  // 总最优成绩  totalbestscore: number;}   
form.ets 数据库卡片表如下:
export default class form {  // 卡片id  formid: string;  // 卡片名称  formname: string;  // 卡片描述  dimension: number;  /**   * 封装卡片数据   * @returns   */  tovaluesbucket() {    return {      'formid': this.formid,      'formname': this.formname,      'dimension': this.dimension    };  }}   
scoredata.ets 游戏记录成绩表如下:
export default class scoredata {  // 卡片  formid: string;  // 距阵数 3x3  matrixnum: string;  // 最优成绩  bestscore: number;  /**   * 获取插入成绩记录数   * @returns   */  tovaluesbucket() {    return {      'formid': this.formid,      'matrixnum': this.matrixnum,      'bestscore': this.bestscore    };  }}   
databaseutils.ets 数据库操作类部分代码如下:
export class databaseutils {  /**   * 创建rdb数据库   *   * @param{context}上下文   * @return{globalthis.rdbstore}return rdbstore rdb数据库   */  async createrdbstore(context: context) {    console.info(commonconstants.database_tag, 'xx databaseutils-createrdbstore 开始...')    // 如果全局变量rdbstore不存在,创建    if (!globalthis.rdbstore) {      console.info(commonconstants.database_tag, 'xx databaseutils-createrdbstore 新创建!')      await datardb.getrdbstore(context, commonconstants.rdb_store_config)        .then((rdbstore) => {          console.info(commonconstants.database_tag, 'xx rdb store回调')          if (rdbstore) {            // 创建卡片表            rdbstore.executesql(commonconstants.create_table_form).catch((error) => {              console.error(commonconstants.database_tag, 'xx databaseutils 创建卡片表失败:' + json.stringify(error))              logger.error(commonconstants.database_tag, 'executesql form error ' + json.stringify(error));            });            // 创建成绩表            rdbstore.executesql(commonconstants.create_table_score_data).catch((error) => {              console.error(commonconstants.database_tag, 'xx databaseutils 创建成绩表失败:' + json.stringify(error))              logger.error(commonconstants.database_tag, 'executesql sensor error ' + json.stringify(error));            });            // 存储rdbstore到全局变量            globalthis.rdbstore = rdbstore;            console.info(commonconstants.database_tag, 'xx databaseutils-createrdbstore 创建成功!')          }        }).catch((error) => {          console.error(commonconstants.database_tag, 'xx databaseutils 创建rdb数据库失败:' + json.stringify(error))          logger.error(commonconstants.database_tag, 'createrdbstore error ' + json.stringify(error));        });    }else {      console.info(commonconstants.database_tag, 'xx databaseutils-createrdbstore 已经存在!')    }    console.info(commonconstants.database_tag, 'xx databaseutils-createrdbstore 结束...')    return globalthis.rdbstore;  }  /**   * 插入卡片数据。   *   * @param{form}form表单实体。   * @param{datardb.rdbstore}rdb存储rdb数据库。   * @return返回操作信息。   */  insertform(form: form, rdbstore: datardb.rdbstore) {    rdbstore.insert(commonconstants.table_form, form.tovaluesbucket()).catch((error) => {      logger.error(commonconstants.database_tag, 'insertform error ' + json.stringify(error));    });  }    /**   * 将成绩插入数据库。   *   * @param{scoredata}scoredata。   * @param{datardb.rdbstore}rdb存储rdb数据库。   */  insertvalues(scoredata: scoredata, rdbstore: datardb.rdbstore) {    rdbstore.insert(commonconstants.table_score, scoredata.tovaluesbucket()).catch((error) => {      logger.error(commonconstants.database_tag, 'insertvalues error ' + json.stringify(error));    });  }    /**   *  更新成绩到数据库   * @param scoredata   * @param rdbstore   */  updatevalues(scoredata: scoredata, rdbstore: datardb.rdbstore) {}  /**   * 删除卡片数据。   *   * @param{string}formid表单id。   * @param{datardb.rdbstore}rdb存储rdb数据库。   */  deleteformdata(formid: string, rdbstore: datardb.rdbstore) {}  /**   * 更新卡片   *   * @param{datardb.rdbstore}rdb存储rdb数据库。   */  updateforms(rdbstore: datardb.rdbstore) {}  /**   * 发送通知   *   * @param{string}steps显示的值步数。   */  async sendnotifications(score: number) {}}   
卡片前端项目结构图:
entryability.ets 程序入口初始化数据库代码如下:
oncreate(want, launchparam) {    // 数据库初始化    globalthis.abilitywant = want;    globalthis.abilityparam = launchparam;    console.info(commonconstants.entry_ability_tag, 'xx oncreate 创建rdb数据库')    // 创建rdb数据库    databaseutils.createrdbstore(this.context).then((rdbstore) => {        console.info(commonconstants.entry_ability_tag, 'xx oncreate rdb成功')    }).catch((error) => {        console.error(commonconstants.entry_ability_tag, 'xx oncreate 创建数据库失败:' + json.stringify(error))        logger.error(commonconstants.entry_ability_tag, 'oncreate rdb error ' + json.stringify(error));    });}   
entryformability.ets 卡片生命周期代码如下:
onaddform(want) {    // 获取卡片id:ohos.extra.param.key.form_identity    let formid: string = want.parameters[commonconstants.form_param_identity_key] as string;    // 获取卡片名称:ohos.extra.param.key.form_name    let formname: string = want.parameters[commonconstants.form_param_name_key] as string;    // 获取卡片规格:ohos.extra.param.key.form_dimension    let dimensionflag: number = want.parameters[commonconstants.form_param_dimension_key] as number;    console.info(commonconstants.entry_form_ability_tag, `xx 添加卡片是:${formid} ${dimensionflag} ${dimensionflag}`)    databaseutils.createrdbstore(this.context).then((rdbstore) => {      // 卡片信息      let form: form = new form();      form.formid = formid;      form.formname = formname;      form.dimension = dimensionflag;      console.info(commonconstants.entry_form_ability_tag, 'xx onaddform 新增卡片信息:' + json.stringify(form))      // 保存卡片信息到数据库      databaseutils.insertform(form, rdbstore);      // 获取最优成绩      getbestscore(rdbstore, dimensionflag, formid);    }).catch((error) => {      console.error(commonconstants.entry_form_ability_tag, 'xx onaddform 添加卡片失败:' + json.stringify(error))      logger.error(commonconstants.entry_form_ability_tag, 'onaddform rdb error ' + json.stringify(error));    });    // 每五分钟刷新一次    formprovider.setformnextrefreshtime(formid, commonconstants.form_next_refresh_time, (error, data) => {      if (error) {        console.error(commonconstants.entry_form_ability_tag, 'xx onaddform 更新卡片失败:' + json.stringify(error))        logger.error(commonconstants.entry_form_ability_tag, 'refreshtime, error:' + json.stringify(error));      } else {        console.info(commonconstants.entry_form_ability_tag, 'xx onaddform 更新卡片成功')        logger.info(commonconstants.entry_form_ability_tag, 'refreshtime success ' + json.stringify(data));      }    });    // 返回初始化卡片数据    let formdata: formdata = new formdata();    formdata.formid = formid;    formdata.bestscore = 0;    formdata.matrixnum = '1x1';    formdata.totalbestscore = 0;    return formbindingdata.createformbindingdata(formdata);  }   
卡片页面部分代码,这里就显示 2x2 卡片代码如下:
build() {    column(){      text(this.message)        .width('100%')        .fontsize(12)        .textalign(textalign.center)        .fontweight(700)        .margin({top: 6, bottom: 6})      row(){        text(`下一个:${this.flagnum == 0 ? 1 : this.flagnum}`)          .fontsize(10).fontweight(400)          .fontcolor(color.red)        row(){          text(`此次:${this.currentscore}`)            .fontsize(10).fontweight(400)          text(`最好:${this.bestscore}`)            .fontsize(10).fontweight(400)        }      }      .width('100%')      .padding({left: 10, right: 10})      .alignitems(verticalalign.center)      .justifycontent(flexalign.spacebetween)      flex({justifycontent: flexalign.center, alignitems: itemalign.center, wrap: flexwrap.wrap}){        // 循环显示数字按钮        foreach(this.numarray, (day: string) => {          button(day, { type: buttontype.circle, stateeffect: true })            .width(40)            .height(40)            .padding(1)            .margin(4)            .fontsize(12)            .backgroundcolor(color.gray)            .statestyles({              normal: this.normalstyles,              pressed: this.pressedstyles            })            .onclick(() => { this.startgame(number(day)) })        }, day => day)      }      .width('100%')      .height('100%')      .padding({ top: 2, left: 5, right: 5 })    }    .width('100%')    .height('100%')  }     
总结
    通过开发这个小游戏元服务,学习到不少知识,其实我有尝试过把数据库操作类写到动态共享包里,这样元服务打包后不就更小了,然而启动后白屏了,进步问题,等华为相关技术人员回复,想学习动态共享包的,可以参考关系型数据库-动态共享包开发。 总结这个项目用到以下知识点:
使用 notification 发布通知。
使用关系型数据库插入、更新、删除卡片数据。
使用 formextensionability 创建、更新、删除元服务卡片。


TheFuck:Python写的超实用命令纠正工具
关于电机驱动MCU通用功能和技术点的解析
人工智能助力脑动脉瘤检测
合肥协调海关助力长鑫存储设备进口
汉威科技任红军:物联网时代传感器就好比触须
HarmonyOS 3.1上实现游戏万能卡片
联动天翼与台联电5G触控系统等41个超亿元“未来产业”项目成功签约
RF功率器件的设计及应用
iPhone13Pro黄金版起售价27万
通用自动驾驶公司Cruise开始在旧金山进行无人驾驶测试
人工智能和物联网是如何对网络有影响的
新时代的党国情——VR红色教育科普
dds技术的基本原理
三星将推两款Bada2.0智能手机
2018年将是8K的元年,全球8K电视出货量将达到20万台
iQOO Z1x携手闪送,续航大电量让“拼搏不断电”
台积电计划将在2023年初涨价
5G消息的主要业务价值体现在哪里?
霍尔电流传感器的检测与补偿原理
美国的军情机构也在野心勃勃朝着人工智能方向发展