如何使用HarmonyOS Next实现刮一刮应用 原创

wuyanghcoa
发布于 2024-12-1 16:30
浏览
0收藏

前言

突发奇想,写一个刮一刮应用,会不会可以在聚会的场合为我们的生活增添一些乐趣呢
如何使用HarmonyOS Next实现刮一刮应用-鸿蒙开发者社区
说干就干

开发

初始页

突发奇想,我脑海中浮现出一个充满创意与趣味的概念——开发一款独特的“刮一刮”应用,它不仅仅是一个简单的数字游戏,而是专为各类聚会场合量身定制的娱乐神器。这款应用的设计初衷,就是要在亲朋好友相聚的时刻,为大家带来一抹意想不到的快乐与惊喜,让每一次聚会都成为难以忘怀的记忆。

import { router } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  // 长有多少格
  @State long: number = 0;
  // 宽有多少格
  @State wide: number = 0;
  @State Input: string = ""
  // 奖项数组
  @State prize: string[] = []

  build() {
    Column() {
      // 选择规格
      Row() {
        Text("生成刮刮乐的大小:")
        TextInput()
          .width("50vp")
          .height("40vp")
          .textAlign(TextAlign.Center)
          .maxLength(2)
          .onChange((val) => {
            this.long = parseInt(val);
          })
        Text("X")
        TextInput()
          .width("50vp")
          .height("40vp")
          .textAlign(TextAlign.Center)
          .maxLength(2)
          .onChange((val) => {
            this.wide = parseInt(val);
          })
      }

      Text(`当前的尺寸共有${this.long * this.wide}个空格`)
        .height("40vp")
      // 输入奖项
      Row() {
        Text("请输入奖项:")
        TextInput({ text: this.Input })
          .width("200vp")
          .height("40vp")
          .textAlign(TextAlign.Center)
          .onChange((val) => {
            this.Input = val;
          })
        Button("添加")
          .onClick(() => {
            this.prize.push(this.Input)
            this.Input = ""
          })
      }

      Text(`当前已添加${this.prize.length}个奖项`)
      // 奖项
      List() {
        ForEach(this.prize, (item: string, index: number) => {
          ListItem() {
            Column() {
              prize_item({
                prize: item,
                // 删除奖励的函数
                delete: () => {
                  this.prize.splice(index, 1)
                }
              })
            }
            .size({ width: "100%", height: "100vp" })
            .justifyContent(FlexAlign.Center)
            .alignItems(HorizontalAlign.Center)

          }
        })
      }
      .width('100%')
      .height("1700px")

      Button("生成")
        .margin("20px")
        .onClick(()=>{
          router.pushUrl({
            url:"pages/scrape",
            params:{
              long:this.long,
              wide:this.wide,
              prize:this.prize
            }
          })
        })

    }
    .size({ height: "100%", width: "100%" })
  }
}
// 奖项组件
@Component
struct prize_item {
  @Prop prize: string
  delete = () => {
  }

  build() {
    Row() {
      Text(this.prize)
        .fontSize("100px")
      Text("x")
        .fontSize("100px")
        .fontColor("#ff0000")
        .onClick(() => {
          this.delete()
        })
    }
    .margin("10px")
    .borderRadius("20px")
    .backgroundColor("#F0FFF0")
    .justifyContent(FlexAlign.SpaceAround)
    .size({ width: "70%", height: "70%" })

  }
}

虽然代码确实写得有点长,但这也是为了确保我们最终能够得到一个既符合需求又比较合适的页面。通过这样一番细致的编写和调试,页面的布局、功能都能达到我们的预期。
如何使用HarmonyOS Next实现刮一刮应用-鸿蒙开发者社区
当我们浏览奖项列表时,如果发现有某个奖项不再需要或者想要进行清理,只需轻轻点击该奖项右侧那个醒目的叉号图标,系统便会立即响应我们的操作。随后,这个不再需要的奖项就会悄无声息地从列表中移除,整个页面也会相应地刷新,以确保所有展示的奖项都是我们当前所关注和需要的。

设置背景

在完成最基本的初始化设置,确保所有基础配置都已妥善安排之后,我们接下来就要进入核心环节——刮刮乐内容的生成。这一步骤至关重要,它决定了整个刮刮乐游戏的趣味性和吸引力。
我们的思路非常清晰:首先,我们需要根据预设的规则和规格,生成一个二维数组作为刮刮乐的底层结构。这个二维数组就像一张精心设计的地图,每一个格子都承载着可能的中奖机会。

function Generate_body(long: number, wide: number, prize: Array<string>, fail: string): Array<Array<string>> {
  // 初始化一个二维数组,所有元素都是0
  let array: Array<Array<string>> = Generate_arrays(long, wide, fail)
  let len = prize.length
  // 在二位数组中埋雷
  for (let i = 0; i < len; ) {
    // 生成随机行和列索引
    let row = Math.floor(Math.random() * wide);
    let col = Math.floor(Math.random() * long);
    if (array[row][col] == fail) {
      array[row][col] = prize[i];
      i++;
    }
  }
  return array;
}

function Generate_arrays(long: number, wide: number, value: string) {
  // 初始化一个二维数组,所有元素都是value
  const array: Array<Array<string>> = [];
  for (let index = 0; index < wide; index++) {
    let result: Array<string> = [];
    for (let i = 0; i < long; i++) {
      result.push(value);
    }
    array.push(result)
  }
  return array;
}

在完成奖项的随机分配之后,接下来我们就需要将这些丰富多样的内容呈现在屏幕上。为了实现这一目标,我采用了两层forEach循环来进行内容的渲染。

首先,外层的forEach循环会逐一遍历二维数组中的每一行。在这个过程中,它会为每一行创建一个对应的容器,以便后续放置具体的奖项内容。这样的设计确保了整个刮刮乐页面的结构清晰、有序。

紧接着,内层的forEach循环则负责处理每一行中的具体格子。它会根据二维数组中对应位置的值,动态地生成并渲染出每个格子的内容和样式。无论是奖项的图标、名称还是相关的描述信息,都会在这一步被精确地添加到页面上。

通过这两层forEach循环的紧密配合,我们能够高效地将刮刮乐的所有内容完整地呈现在用户的屏幕上。

      // 竖放向
      Flex({ wrap: FlexWrap.NoWrap, direction: FlexDirection.Row }) {
        ForEach(this.List, (item_y: Array<string>, index_y: number) => {
          // 横放向
          Flex({ wrap: FlexWrap.NoWrap, direction: FlexDirection.Column }) {
            ForEach(item_y, (item_x: string, index_x: number) => {
              scrape_item({
                prize: item_x,
                h:this.long,
                w:this.wide
              })
            })
          }
        })

      }
      .size({ width: 350, height: 350 })

显示的效果如下所示

如何使用HarmonyOS Next实现刮一刮应用-鸿蒙开发者社区

经过前面的一系列精心准备和细致处理,我们已经成功迈出了刮刮乐页面构建的大部分步伐。现在,即将迎来的是整个项目中的最后一个关键环节,也是将我们所有努力汇聚成最终成果的重要一步。

添加蒙版

当我们精心筹备并完美呈现了刮刮乐的所有内容后,整个项目便已接近尾声,但此时仍有一项至关重要的任务等待我们去完成,那就是为刮刮乐添加一层神秘的蒙版。
当然,在着手实现这一功能之前,我们首先需要构建一个奖项组件。这个组件将作为刮刮乐页面中的基本单元,承载着每个奖项的详细信息与展示效果。对于在座各位技术娴熟、经验丰富的大佬来说,轻松自如便能完成。

@Component
struct scrape_item {
  @Prop prize: string
  @Prop h: number
  @Prop w: number
  @State is_show: boolean = false

  build() {
    Column() {
      Column() {
        if (this.is_show) {
          Text(this.prize)
        }

      }
      .size({ width: "100%", height: "100%" })
      .backgroundColor(this.is_show ? "#F5F5F5" : "#DCDCDC")
      .alignItems(HorizontalAlign.Center)
      .justifyContent(FlexAlign.Center)
      .onClick(() => {
        this.is_show = true
      })
    }
    .padding("20px")
    .size({ width: 350 / this.w, height: 350 / this.h })
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)

  }
}

最后,当我们把所有的代码片段都精心地拼接在一起,就像组装起一块块精美的拼图,一个完整且功能齐全的刮刮乐页面就呈现在我们眼前了。

如何使用HarmonyOS Next实现刮一刮应用-鸿蒙开发者社区

刮一刮页的完整代码

最后,给各位附上完整的项目页面代码

import { router } from '@kit.ArkUI';

@Entry
@Component
struct scrap {
  // 接收到的数据
  @State long: number = (router.getParams() as object)?.["long"];
  @State wide: number = (router.getParams() as object)?.["wide"];
  @State prize: string[] = (router.getParams() as object)?.["prize"];
  @State fail: string = "空"
  // 主体数组列表
  @State List: Array<Array<string>> = Generate_body(this.long, this.wide, this.prize, this.fail)

  build() {
    Column() {

      // 竖放向
      Flex({ wrap: FlexWrap.NoWrap, direction: FlexDirection.Row }) {
        ForEach(this.List, (item_y: Array<string>, index_y: number) => {
          // 横放向
          Flex({ wrap: FlexWrap.NoWrap, direction: FlexDirection.Column }) {
            ForEach(item_y, (item_x: string, index_x: number) => {
              scrape_item({
                prize: item_x,
                h: this.long,
                w: this.wide,
              })
            })
          }
        })

      }
      .size({ width: 350, height: 350 })

      Button("重开")
        .margin("10px")
        .onClick(() => {
          this.List = Generate_body(this.long, this.wide, this.prize, this.fail)
        })

    }
    .justifyContent(FlexAlign.SpaceEvenly)
    .alignItems(HorizontalAlign.Center)
    .size({ width: "100%", height: "100%" })
  }
}

function Generate_body(long: number, wide: number, prize: Array<string>, fail: string): Array<Array<string>> {
  // 初始化一个二维数组,所有元素都是0
  let array: Array<Array<string>> = Generate_arrays(long, wide, fail)
  let len = prize.length
  // 在二位数组中埋雷
  for (let i = 0; i < len; ) {
    // 生成随机行和列索引
    let row = Math.floor(Math.random() * wide);
    let col = Math.floor(Math.random() * long);
    if (array[row][col] == fail) {
      array[row][col] = prize[i];
      i++;
    }
  }
  return array;
}

function Generate_arrays(long: number, wide: number, value: string) {
  // 初始化一个二维数组,所有元素都是value
  const array: Array<Array<string>> = [];
  for (let index = 0; index < wide; index++) {
    let result: Array<string> = [];
    for (let i = 0; i < long; i++) {
      result.push(value);
    }
    array.push(result)
  }
  return array;
}


@Component
struct scrape_item {
  @Prop prize: string
  @Prop h: number
  @Prop w: number
  @State is_show: boolean = false

  build() {
    Column() {
      Column() {
        if (this.is_show) {
          Text(this.prize)
        }

      }
      .size({ width: "100%", height: "100%" })
      .backgroundColor(this.is_show ? "#F5F5F5" : "#DCDCDC")
      .alignItems(HorizontalAlign.Center)
      .justifyContent(FlexAlign.Center)
      .onClick(() => {
        this.is_show = true
      })
    }
    .padding("20px")
    .size({ width: 350 / this.w, height: 350 / this.h })
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)

  }
}

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2024-12-1 16:44:08修改
收藏
回复
举报
回复
    相关推荐