木棉花#夏日挑战赛# 鸿蒙小游戏项目——数独Sudoku

Posted 开源基础软件社区官方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了木棉花#夏日挑战赛# 鸿蒙小游戏项目——数独Sudoku相关的知识,希望对你有一定的参考价值。

​「本文正在参加星光计划3.0--夏日挑战赛」​

前言

    在上期内容的分享中,笔者介绍了如何搭建基础的页面框架(为之后的开发做准备),以及应用图像和标签的修改、应用的全屏化。而在本期,笔者就在上期的基础上继续展开数独小游戏项目的搭建。

    上期的内容回顾——>>​​https://ost.51cto.com/posts/14383​

【木棉花】#夏日挑战赛#

正文

  本期,笔者将介绍如何利用代码布局创建网格区域的UI。

  首先,笔者所说的网格区域指的是下图被圈出的部分:


【木棉花】#夏日挑战赛#

     事实上,因为网格区域用于承载数独的题目,它同时也是玩家主要面向的部分,所以网格区域的逻辑就是这个项目最核心的功能。网格区域中有两种颜色的网格,其中,蓝色网格内的数字是应用为用户提供的提示数字,白色网格则需要用户根据数独的规则合理填入数字,两种格子的数量加起来共计64个。而现在我们面临的问题是——我们如何将这个6x6的平面网格系统搭建起来呢?

    笔者的思路是,先设计网格区域的UI,再完善网格区域的交互逻辑。而本期将介绍的内容就是如何设计网格区域的UI。

    网格区域中共有36格子,那么这些格子需要用什么UI组件做呢?Button组件无疑可以尝试一下。那么我们接下来所要做的就是把Button组件设计成每一个格子,然后让他们按一定的顺序排起来,组成一个网格系统。由于格子的数量较多,所以我们不能用XML布局一个一个定义,这样不仅效率慢,而且占用内存。而如果我们选择使用Java代码布局的话,我们就可以利用for循环来渲染button组件,以此做到高效简洁。

    当然,我们还面临另一个问题——设计好的格子应该通过什么布局排起来呢?因为我们是通过for循环来生成格子的,在这样的前提下,只有坐标布局才能与for循环无缝融合。

   以下是通过代码布局设计网格区域的UI的具体步骤。

 

 

完善GameAbilitySlice

 由于数独小游戏项目的游戏界面是用GameAbilitySlice承载的,所以我们首先要完善之前新创建的GameAbilitySlice。打开GameAbilitySlice,将代码修改为如下:

package com.example.project.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;

public class GameAbilitySlice extends AbilitySlice

@Override
protected void onStart(Intent intent)
super.onStart(intent);




@Override
protected void onBackground()
super.onBackground();

 

这样以后,GameAbilitySlice就继承了AbilitySlice的类,并且它被写入了onStart和onBackground两个生命周期回调函数。

 

设计题目

在设计网格区域之前,我们需要先创建一个数独题目(这样之后每个格子的颜色和数字才能被确定),这个题目的信息需要用数据承载。

在这里,我们将利用数组的形式存储数独题目。定义一个6x6的数组——将代码修改为如下:

package com.example.project.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;



public class GameAbilitySlice extends AbilitySlice

//定义一个数组
int[][] grid_c0=new int[6][];



@Override
protected void onStart(Intent intent)
super.onStart(intent);

//为数组赋值
grid_c0[0]=new int[]0,0,0,0,1,0;
grid_c0[1]=new int[]1,0,2,4,0,0;
grid_c0[2]=new int[]6,2,3,0,0,5;
grid_c0[3]=new int[]5,0,0,2,3,6;
grid_c0[4]=new int[]0,6,4,3,5,0;
grid_c0[5]=new int[]3,1,0,5,0,4;





@Override
protected void onBackground()
super.onBackground();

可以看出,我们首先在GameAbilitySlice的内部定义了一个列数为6的数组grid_c0(即数组每行有六个数字),然后我们又在onStart函数内部为这个数组的每一列(第0列到第五列)赋值,这样grid_co就可以写成矩阵:

 

                                              0   1   6   5   0   3

                                              0   0   2   0   6   1

                                              0   2   3   0   4   0

                                              0   4   0   2   3   5

                                              1   0   0   3   5   0

                                              0   0   5   6   0   4

 

 

通过代码布局的方式创建GameAbilitySlice的UI界面

首先,在onStart内(”为数组赋值”的下方)加入下列代码:

PositionLayout layout1=new PositionLayout(getContext());
layout1.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
layout1.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);

这样做的目的是——在onStart的方法内创建一个PositionLayout的对象。并且,这个对象的高度和宽度继承了父组件(其父组件可以认为是手机屏幕)的尺寸。PositionLayout的中文名是坐标布局,它属于一种容器组件[容器组件是用来放置其它常用子组件(如按钮组件,文本组件)的]。我们这里之所以用坐标布局,而不是用其它布局,是因为坐标布局可以用坐标(x,y)来确定其子组件的位置。相较于方向布局和依赖布局,坐标布局更加直观和精确,这也是我们选用坐标布局的主要原因。

 

创建网格区域

首先,我们事先定义一些数据,以便在后面使用:

int x;
int y;
int number;
String string0;

接着,我们为Button组件创建两种背景元素:

ShapeElement element0=new ShapeElement();
element0.setRgbColor(new RgbColor(255,255,255)); //设置RGB颜色(白色)
element0.setStroke(5,new RgbColor(0,0,0)); //设置边框的厚度和颜色(黑色)

ShapeElement element3=new ShapeElement();
element3.setRgbColor(new RgbColor(0,125,225)); //设置RGB颜色(蓝色)
element3.setStroke(5,new RgbColor(0,0,0)); //设置边框的厚度和颜色(黑色)

于是,我们得到了element0和element3两种背景元素,他们分别可以把Button组件装饰成蓝色网格状和白色网格状。

 

之后,我们通过双重for循环来渲染Button组件,并在坐标布局的协助下,利用这些Button组件构成一个网格:

for (y=0;y<6;y++)
for (x=0;x < 6; x++)
Button button = new Button(this); //创建Button对象

number=grid_c0[x][y]; //按照两个for循环的序列对数组grid_c0取值(x代表grid_c0对应的行数,y代表grid_c0对应的列数)

string0=String.valueOf(number);
button.setText(string0); //将number由整形变量转化为字符串,然后把它设置为button显示的文字


button.setTextColor(Color.WHITE);
button.setTextSize(75);
button.setComponentSize(160, 160);
//定义按钮的尺寸,按钮内文字的大小和颜色


button.setContentPosition(65+160* x, 230+160*y);
//定义按钮的位置,设位置为T,那么T是关于x和y的函数



if (number==0) //判断number是否为0

button.setText("");
button.setBackground(element0);
button.setTextColor(Color.BLACK);
//如果是0,button将不显示任何文字,并且使用element0作为button的背景元素



else
button.setBackground(element3);
//如果不是0,button显示文字,并且使用element3作为button的背景元素



layout1.addComponent(button); //将button组件加入到坐标布局中






这段代码看起来稍微有点复杂,但只要理解好代码各层的逻辑关系,理解起来还是不费劲的。首先,我们设置了两个for循环,可以看出,以y为变量的for循环嵌套着以x为变量的for循环,这意味着,变量x每完成一次0到5循环,变量y的值才加1,于是这两个for循环会共同生成36个Button组件。

每生成一个Button组件时,系统都会根据这个组件在两个for循环中对应的x和y值,对grid_c0进行取值,以及确定这个Button组件的坐标。这样以后,网格区域每行每列的数字就能与grid_c0每行每列的数字对应起来(也就是跟数独题目对应起来)。

接着,我们还加入了一个判断条件,如果这个Button组件对grid_c0取到的数字为0,那么它将作为待用户填入数字的白色空白网格;如果这个Button组件对grid_c0取到的数字不是0(设其为t),那么它将作为用于提示的蓝色网格(这个网格将显示数字t)。

 

最后,我们再加上如下代码:

setUIContent(layout1);

这样以后,我们之前所创建的坐标布局对象layout1就被成功设置为GameAbilitySlice的UI框架了。

 

如果想查看设计的UI效果,我们可以打开MainAbility,把setMainRoute方法内的InitialAbilitySlice修改为GameAbilitySlice(这样就可以修改应用默认显示的页面)。当我们打开模拟机时,我们看到的第一个页面就是GameAbilitySlice了。

效果图如下:

【木棉花】#夏日挑战赛#

显然,图中网格区域中数字的分布与数组grid_c0的矩阵的数字排布一致,只不过,网格区域中的白色格子在矩阵中用数字0表示。

 

                                              0   1   6   5   0   3

                                              0   0   2   0   6   1

                                              0   2   3   0   4   0

                                              0   4   0   2   3   5

                                              1   0   0   3   5   0

                                              0   0   5   6   0   4

结尾

   本期的内容就先分享到这里,更多关于数独小游戏项目精彩的内容我将在下期继续为大家揭晓。


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

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​


以上是关于木棉花#夏日挑战赛# 鸿蒙小游戏项目——数独Sudoku的主要内容,如果未能解决你的问题,请参考以下文章

转木棉花鸿蒙小游戏项目——数独Sudoku(序言)

#夏日挑战赛# FFH从零开始的鸿蒙机器学习之旅-NLP情感分析

#夏日挑战赛#鸿蒙FA开发之JSUI与JavaUI相互跳转实例

#夏日挑战赛#FFHAI作诗之httpRequest实战

#夏日挑战赛# HarmonyOS - 实现带日期效果的待办事项

#夏日挑战赛#OHOS构建自定义服务实战