游戏万能卡片—舒尔特方格游戏

想了解更多关于开源的内容,请访问:

 开源基础软件社区

https://ost.

前言

舒尔特方格游戏,是注意力训练方法之一,可以帮助孩子纠正上课分心走神、回家做作业拖拉毛病,但不能贪玩哦,玩多了,对眼睛,视力不好。

1. 消息通知栏,通知用户当前最优成绩,也就是当前最快时间。2. 元服务卡片,在桌面上添加2×2或2×4或2×4规格元服务卡片,能看到不同布局随机数字,根据左上角红色字提示,快速完成点击,用时最少为最优成绩,1×2规格元服务卡片,只显示当前最优成绩,点击可以3. 关系型数据库,用于查询,添加,更新,删除元服务卡片信息和各卡片游戏用时成绩数据。

B站高清演示视频

知识点

  • 消息通知:提供通知管理的能力,包括发布、取消发布通知,创建、获取、移除通知通道,订阅、取消订阅通知,获取通知的使能状态、角标使能状态,获取通知的相关信息等。
  • 关系型数据库:关系型数据库基于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及以上版本。

卡片讲解

 1. 1×2卡片主要显示所有卡片最优成绩,也就是用时最少的,同时点击卡片,跳转到主界面,查看卡片游戏记录。

2. 2×2卡片显示的是3×3布局随机生成1~9数字,正上方标题显示挑战成功或失败提示,左上角红色字提示下一个要点击的数字按钮,右上角显示当次完成后用时和此卡片用时最少成绩,当此次的用时少于最好用时,挑战成功,并更新数据库此卡片记录,如果此次用时大于最好用时,提示挑战失败,不用更新数据库。

3. 2×4卡片显示的是7×2布局随机生成1~14数字,显示内容和游戏规则与2×2卡片一样。

4. 4×4卡片显示的是6×6布局随机生成1~36数字,显示内容和游戏规则与2×2卡片一样。

5. 首次启动或点击1×2卡片进入到主界面,主界面显示各卡片游戏成绩记录。

6. 通知显示效果。

代码讲解

1. 数据库操作后端项目结构图。

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) {}

}

2. 卡片前端项目结构图。

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);
  }

卡片页面部分代码,这里就显示2×2卡片代码如下:

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%')
  }

总结

通过开发这个小游戏元服务,学习到不少知识,其实我有尝试过把数据库操作类写到动态共享包里,这样元服务打包后不就更小了,然而启动后白屏了,进步问题,等华为相关技术人员回复,想学习动态共享包的,可以参考关系型数据库-动态共享包开发, 总结这个项目用到以下知识点:

  1. 使用notification发布通知。
  2. 使用关系型数据库插入、更新、删除卡片数据。
  3. 使用FormExtensionAbility创建、更新、删除元服务卡片。

想了解更多关于开源的内容,请访问:

 开源基础软件社区

https://ost.

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/262003.html<

(0)
运维的头像运维
上一篇2025-05-03 21:46
下一篇 2025-05-03 21:48

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注