news 2026/5/12 18:15:47

Flutter for OpenHarmony 实战_魔方应用3D数据结构与旋转算法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flutter for OpenHarmony 实战_魔方应用3D数据结构与旋转算法

Flutter for OpenHarmony 实战:魔方应用3D数据结构与旋转算法

文章目录

  • Flutter for OpenHarmony 实战:魔方应用3D数据结构与旋转算法
    • 前言
    • 一、魔方数据结构
      • 1.1 三维数组设计
      • 1.2 面的索引
      • 1.3 颜色映射
    • 二、面旋转算法
      • 2.1 顺时针旋转
      • 2.2 逆时针旋转
      • 2.3 旋转矩阵原理
    • 三、边缘联动系统
      • 3.1 前面旋转联动
      • 3.2 上面旋转联动
      • 3.3 边缘映射表
    • 四、CustomPainter绘制
      • 4.1 展开图布局
      • 4.2 单面绘制
      • 4.3 边框绘制
    • 五、交互控制
      • 5.1 面选择
      • 5.2 旋转按钮
      • 5.3 手势旋转
    • 六、状态管理
      • 6.1 移动计数
      • 6.2 历史记录
    • 总结

欢迎加入开源鸿蒙跨平台社区: 开源鸿蒙跨平台开发者社区

前言

魔方应用的核心在于如何用二维数据结构模拟三维魔方,以及如何实现正确的旋转算法。本文将详细介绍魔方的三维数组表示、面旋转算法、边缘联动机制、CustomPainter绘制技术以及状态管理系统。

一、魔方数据结构

1.1 三维数组设计

lateList<List<List<int>>>cube;voidinitCube(){cube=List.generate(6,(face){returnList.generate(3,(row){returnList.generate(3,(col){returnface;// 每个面初始为相同的颜色});});});}

使用6×3×3的三维数组表示魔方。第一维表示6个面(前、后、左、右、上、下),后两维表示每个面的3×3网格。

1.2 面的索引

// 0: 前面 (Front)// 1: 后面 (Back)// 2: 左面 (Left)// 3: 右面 (Right)// 4: 上面 (Up)// 5: 下面 (Down)

使用整数0-5表示不同的面,便于颜色映射和旋转计算。

1.3 颜色映射

ColorgetFaceColor(int face){switch(face){case0:returnColors.green;// 前面-绿色case1:returnColors.blue;// 后面-蓝色case2:returnColors.orange;// 左面-橙色case3:returnColors.red;// 右面-红色case4:returnColors.white;// 上面-白色case5:returnColors.yellow;// 下面-黄色default:returnColors.grey;}}

标准魔方配色方案。

二、面旋转算法

2.1 顺时针旋转

voidrotateFaceClockwise(int faceIndex){List<List<int>>face=cube[faceIndex];List<List<int>>newFace=List.generate(3,(i)=>List.generate(3,(j)=>0));for(int i=0;i<3;i++){for(int j=0;j<3;j++){newFace[j][2-i]=face[i][j];}}cube[faceIndex]=newFace;_rotateAdjacentEdges(faceIndex,true);}

使用旋转矩阵公式:newFace[j][2-i] = face[i][j],实现90度顺时针旋转。

2.2 逆时针旋转

voidrotateFaceCounterClockwise(int faceIndex){List<List<int>>face=cube[faceIndex];List<List<int>>newFace=List.generate(3,(i)=>List.generate(3,(j)=>0));for(int i=0;i<3;i++){for(int j=0;j<3;j++){newFace[2-j][i]=face[i][j];}}cube[faceIndex]=newFace;_rotateAdjacentEdges(faceIndex,false);}

逆时针旋转公式:newFace[2-j][i] = face[i][j]。

2.3 旋转矩阵原理

顺时针旋转90度: (0,0) -> (0,2) (0,1) -> (1,2) (0,2) -> (2,2) (1,0) -> (0,1) (1,1) -> (1,1) (1,2) -> (2,1) (2,0) -> (0,0) (2,1) -> (1,0) (2,2) -> (2,0) 公式:new[j][2-i] = old[i][j]

三、边缘联动系统

3.1 前面旋转联动

void_rotateFrontEdges(bool clockwise){if(clockwise){// 上面的下行 -> 右面的左列// 右面的左列 -> 下面的上行// 下面的上行 -> 左面的右列// 左面的右列 -> 上面的下行List<int>temp=[cube[4][2][0],cube[4][2][1],cube[4][2][2]];for(int i=0;i<3;i++){cube[4][2][i]=cube[2][2-i][2];cube[2][2-i][2]=cube[5][0][2-i];cube[5][0][2-i]=cube[3][i][0];cube[3][i][0]=temp[i];}}}

旋转前面时,需要同时旋转上、右、下、左四个面与前面相邻的边缘。

3.2 上面旋转联动

void_rotateUpEdges(bool clockwise){if(clockwise){List<int>temp=[cube[0][0][0],cube[0][0][1],cube[0][0][2]];for(int i=0;i<3;i++){cube[0][0][i]=cube[3][0][i];cube[3][0][i]=cube[1][0][i];cube[1][0][i]=cube[2][0][i];cube[2][0][i]=temp[i];}}}

旋转上面时,前、右、后、左四个面的顶行需要同步旋转。

3.3 边缘映射表

每个面的旋转都影响相邻面的特定行或列,需要精确的映射关系。

四、CustomPainter绘制

4.1 展开图布局

voidpaint(Canvascanvas,Sizesize){finalcellSize=50.0;// 绘制前面_drawFace(canvas,0,Offset(150,150),cellSize);// 绘制上面_drawFace(canvas,4,Offset(150,50),cellSize);// 绘制下面_drawFace(canvas,5,Offset(150,250),cellSize);// 绘制左面_drawFace(canvas,2,Offset(50,150),cellSize);// 绘制右面_drawFace(canvas,3,Offset(250,150),cellSize);// 绘制后面_drawFace(canvas,1,Offset(350,150),cellSize);}

使用十字形展开图布局,前面为中心,其他面围绕排列。

4.2 单面绘制

void_drawFace(Canvascanvas,int faceIndex,Offsetoffset,double cellSize){for(int row=0;row<3;row++){for(int col=0;col<3;col++){finalrect=Rect.fromLTWH(offset.dx+col*cellSize,offset.dy+row*cellSize,cellSize-2,cellSize-2,);finalpaint=Paint()..color=getFaceColor(cube[faceIndex][row][col])..style=PaintingStyle.fill;canvas.drawRect(rect,paint);}}}

绘制单个面的3×3网格,每个小方格根据颜色值填充。

4.3 边框绘制

finalborderPaint=Paint()..color=Colors.black..strokeWidth=2..style=PaintingStyle.stroke;canvas.drawRect(rect,borderPaint);

每个小方格绘制黑色边框,增强视觉分离。

五、交互控制

5.1 面选择

int?selectedFace;void_handleTap(TapDownDetailsdetails){finallocalPosition=details.localPosition;for(int face=0;face<6;face++){if(_isPointInFace(localPosition,face)){setState((){selectedFace=face;});return;}}}

点击选择要旋转的面。

5.2 旋转按钮

Row(children:[ElevatedButton(onPressed:selectedFace!=null?()=>rotateFaceClockwise(selectedFace!):null,child:constText('顺时针'),),ElevatedButton(onPressed:selectedFace!=null?()=>rotateFaceCounterClockwise(selectedFace!):null,child:constText('逆时针'),),],)

提供顺时针和逆时针旋转按钮。

5.3 手势旋转

double?previousAngle;void_handlePanStart(DragStartDetailsdetails){if(selectedFace==null)return;finaldx=details.localPosition.dx-getFaceCenter(selectedFace!).dx;finaldy=details.localPosition.dy-getFaceCenter(selectedFace!).dy;previousAngle=atan2(dy,dx);}void_handlePanUpdate(DragUpdateDetailsdetails){if(selectedFace==null||previousAngle==null)return;finaldx=details.localPosition.dx-getFaceCenter(selectedFace!).dx;finaldy=details.localPosition.dy-getFaceCenter(selectedFace!).dy;finalcurrentAngle=atan2(dy,dx);if((currentAngle-previousAngle!).abs()>pi/4){rotateFaceClockwise(selectedFace!);previousAngle=currentAngle;}}

支持手势滑动旋转,每45度触发一次旋转。

六、状态管理

6.1 移动计数

int moveCount=0;voidrotateFaceClockwise(int faceIndex){// ...旋转逻辑setState((){moveCount++;});}

记录旋转次数,用于评估解法效率。

6.2 历史记录

List<String>moveHistory=[];voidaddMove(int face,bool clockwise){moveHistory.add('$face${clockwise?"CW":"CCW"}');}

记录每次旋转,支持撤销功能。

总结

本文详细介绍了魔方应用的3D数据结构和旋转算法。从三维数组设计到面旋转算法,从边缘联动到CustomPainter绘制,每个技术点都直接影响应用的功能性和用户体验。通过这些技术的综合应用,实现了功能完整且交互流畅的魔方应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 23:24:55

反传统笔记APP,摒弃纯文本/图片记录,支持语音+场景自动补充,用户说明天下午三点开会,自动补充会议地点,参会人员,(从通讯录提取),还能生成思维导图。

1. 实际应用场景与痛点场景传统笔记 APP 只能记录纯文本或图片&#xff0c;用户在记录会议信息时&#xff0c;需要手动输入&#xff1a;- 会议地点- 参会人员- 相关背景资料这导致&#xff1a;- 记录效率低- 容易遗漏关键信息- 无法自动关联已有数据&#xff08;如通讯录、日历…

作者头像 李华
网站建设 2026/4/28 13:53:10

深圳汇芯生物全自动外泌体提取系统界面设计

01项目背景深圳汇芯生物医疗科技有限公司&#xff08;以下简称汇芯生物&#xff09;是由外泌体领域知名科学家和产业专家共同创立的国家高新技术企业&#xff0c;致力于推动外泌体在癌症早期诊断和治疗领域的研究及应用&#xff0c;开发全球领先的生物医疗技术&#xff0c;满足…

作者头像 李华
网站建设 2026/5/8 16:57:47

Light Image Resizer v7.5.1 批量压缩加水印工具

Light Image Resizer v7.5.1 是一款免激活的专业批量图片处理工具&#xff0c;集批量调整大小、格式转换、加水印、优化压缩等多功能于一体&#xff0c;操作便捷且参数灵活&#xff0c;完美适配个人日常与职场办公的图片批量处理需求&#xff0c;助力高效完成图片优化任务。一、…

作者头像 李华
网站建设 2026/5/11 22:12:33

Java程序员如何逆袭进大厂?

前几天&#xff0c;跟个老朋友吃饭&#xff0c;他最近想跳槽去大厂&#xff0c;觉得压力很大&#xff0c;问我能不能分享些所谓的经验套路。每次有这类请求&#xff0c;都觉得有些有趣&#xff0c;不知道你发现没有大家身边真的有很多人不知道怎么面试&#xff0c;也不知道怎么…

作者头像 李华
网站建设 2026/5/10 17:16:40

(含关键技术人员解析)从“千问崩了”到“系统重生”:一场30亿级高并发实战背后的全链路技术复盘

从“千问崩了”到“系统重生”&#xff1a;一场30亿级高并发实战背后的全链路技术复盘 适合读者&#xff1a;后端开发、SRE工程师、AI平台建设者、技术管理者、计算机专业学生 关键词&#xff1a;通义千问、高并发、大模型推理、系统稳定性、限流降级、Kubernetes、GPU调度、CS…

作者头像 李华
网站建设 2026/5/11 13:52:20

【C++与Linux基础】文件篇 -语言特性上的文件操作

【C与Linux基础】文件篇 - 语言特性上的文件操作 在 C 中进行文件操作&#xff0c;主要依赖两种方式&#xff1a; C 标准库&#xff08;<fstream>&#xff09;—— 现代 C 推荐方式&#xff0c;跨平台&#xff0c;面向对象风格C 风格文件操作&#xff08;<cstdio>…

作者头像 李华