写点什么

【HarmonyOS】鸿蒙九宫格拼图游戏

作者:zhongcx
  • 2024-10-11
    广东
  • 本文字数:3748 字

    阅读完需:约 12 分钟

这段代码实现了一个基于 ArkUI 框架(OpenHarmony 的 UI 开发框架)的简单拼图游戏功能。以下是该代码实现的主要功能点:

  1. 图片选择器:用户可以通过点击“选择图片→”按钮来触发图片选择器,从而从设备中选择一张图片作为拼图游戏的原始图片。

  2. 图片处理:选择图片后,程序会对图片进行处理,将其裁剪成 9 个等大的小块(3x3 网格),并将这些小块打乱顺序存储起来。每个小块都是一个PuzzlePiece对象,包含了该块的像素地图(PixelMap)和它在原始图片中的索引位置(originalIndex)。

  3. 拼图游戏界面:游戏界面使用网格布局(Grid)显示这 9 个拼图块。用户可以点击拼图块来交换它们的位置,尝试还原原始图片。点击一个拼图块时,如果该块是首次被选中,它会缩小显示,表示已选中;如果再次点击已选中的块,它会恢复原始大小并取消选中状态;如果点击另一个未选中的块,则会交换这两个块的位置。

  4. 拼图完成检测:每次交换拼图块后,程序会检查拼图是否已经完成(即每个拼图块都回到了它在原始图片中的正确位置)。如果拼图完成,会弹出一个对话框显示“拼图完成!”的消息。

  5. UI 元素:界面上还包括了显示原始图片的区域(如果已选择图片),以及游戏区域(显示拼图块)。

import picker from '@ohos.file.picker';import fs from '@ohos.file.fs';import image from '@ohos.multimedia.image';import { common } from '@kit.AbilityKit';import { promptAction } from '@kit.ArkUI';// 定义拼图组件接口interface PuzzlePiece {  // 拼图块的像素地图  pixelMap: image.PixelMap;  // 原始图片中的索引位置  originalIndex: number;}
// 使用装饰器定义页面组件@Entry@Componentstruct Page30 { // 状态变量:选中图片的URI @State imgUri: string = ''; // 状态变量:原始图片的URI @State imgOriginal: string = ''; // 状态变量:存储拼图块的数组 @State puzzlePieces: Array<PuzzlePiece> = []; // 状态变量:记录当前选中的拼图块索引 @State selectedPieceIndex: number = -1;
// 弹出图片选择器方法 async openPicker() { try { // 设置图片选择器选项 const photoSelectOptions = new picker.PhotoSelectOptions(); // 限制只能选择一张图片 photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; photoSelectOptions.maxSelectNumber = 1; // 创建并实例化图片选择器 const photoViewPicker = new picker.PhotoViewPicker(); // 选择图片并获取图片URI let uris: picker.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions); if (!uris || uris.photoUris.length === 0) return; // 获取选中图片的第一张URI let uri: string = uris.photoUris[0];
// 打开文件读取流 let file = fs.openSync(uri, fs.OpenMode.READ_ONLY); // 获取当前上下文 let context = getContext(this) as common.UIAbilityContext; // 新建一个保存裁剪后图片的路径 let newUrl = context.filesDir + '/test' + new Date().getTime() + '.jpg'; // 复制图片到新的路径 fs.copyFileSync(file.fd, newUrl); // 关闭文件读取流 fs.closeSync(file);
// 更新状态变量:设置显示图片的URI this.imgUri = newUrl; // 更新状态变量:保存原始图片的URI this.imgOriginal = uri; // 图片更改时触发的方法 this.imgChange(); } catch (e) { console.error('openPicker', JSON.stringify(e)); } }
// 图片更改处理方法 async imgChange() { try { // 创建图片源对象 const imageSource: image.ImageSource = image.createImageSource(this.imgUri); // 图片解码选项 let decodingOptions: image.DecodingOptions = { editable: true, desiredPixelFormat: 3, }; // 创建像素地图 let mPixelMap: image.PixelMap = await imageSource.createPixelMap(decodingOptions); // 获取图片信息 let mImageInfo: image.ImageInfo = await mPixelMap.getImageInfo();
// 计算每个拼图块的大小 const cropSize: image.Size = { width: mImageInfo.size.width / 3, height: mImageInfo.size.height / 3, };
// 清空已有拼图块数据 this.puzzlePieces.splice(0);
// 遍历图片生成9个拼图块 let count = 0; for (let row = 0; row < 3; row++) { for (let col = 0; col < 3; col++) { // 创建基于原图的新图片源 const imageSource = image.createImageSource(this.imgUri); // 创建新像素地图 let mPixelMap = await imageSource.createPixelMap(decodingOptions); // 计算裁剪区域 const cropRect: image.Region = { x: col * cropSize.width, y: row * cropSize.height, size: cropSize, }; // 裁剪像素地图 await mPixelMap.crop(cropRect);
// 创建并添加拼图块至数组 const piece: PuzzlePiece = { pixelMap: mPixelMap, originalIndex: count++, }; this.puzzlePieces.push(piece); } }
// 打乱拼图块顺序 for (let i = this.puzzlePieces.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); let temp: PuzzlePiece = this.puzzlePieces[i]; this.puzzlePieces[i] = this.puzzlePieces[j]; this.puzzlePieces[j] = temp; } } catch (e) { console.error('imgChange', JSON.stringify(e)); } }
// 构建UI界面 build() { Column() { // 添加选择图片按钮,点击后调用打开图片选择器方法 Button('选择图片→').onClick(() => { this.openPicker(); });
// 显示原始图片(如果已选择) if (this.imgOriginal) { Text('原始图片↓'); Image(this.imgOriginal) .width('180lpx') .height('180lpx') .objectFit(ImageFit.Contain); }
// 如果有拼图块,则显示游戏区 if (this.puzzlePieces.length > 0) { Text('游戏图片↓'); // 游戏区域采用网格布局 Grid() { // 遍历所有拼图块并创建网格项 ForEach(this.puzzlePieces, (item: PuzzlePiece, index: number) => { GridItem() { // 显示拼图块图像 Image(item.pixelMap) .width('200lpx') .height('200lpx') .margin('5lpx') // 根据是否选中调整缩放比例 .scale(this.selectedPieceIndex == index ? { x: 0.5, y: 0.5 } : { x: 1, y: 1 }) // 添加点击事件处理 .onClick(() => { // 处理拼图交换逻辑 if (this.selectedPieceIndex == -1) { this.selectedPieceIndex = index; } else if (this.selectedPieceIndex == index) { this.selectedPieceIndex = -1; } else { let temp: PuzzlePiece = this.puzzlePieces[this.selectedPieceIndex]; this.puzzlePieces[this.selectedPieceIndex] = this.puzzlePieces[index]; this.puzzlePieces[index] = temp; this.selectedPieceIndex = -1;
// 检查拼图是否完成 let isSucc: boolean = true; for (let i = 0; i < this.puzzlePieces.length; i++) { console.info('====item', this.puzzlePieces[i].originalIndex, i); if (this.puzzlePieces[i].originalIndex !== i) { isSucc = false; break; } }
// 如果拼图完成,弹出提示对话框 if (isSucc) { promptAction.showDialog({ message: '拼图完成!', }); } } }); } }) // End of ForEach } // End of Grid .backgroundColor("#fafafa"); // 设置网格背景色 } } // End of Column .width('100%'); // 设置列宽度为100% }}
复制代码


用户头像

zhongcx

关注

还未添加个人签名 2024-09-27 加入

还未添加个人简介

评论

发布
暂无评论
【HarmonyOS】鸿蒙九宫格拼图游戏_zhongcx_InfoQ写作社区