【木棉花】#打卡不停更#HarmonyOS小游戏项目——数独Sudoku(6) 原创
前言
上期的分享中,我们成功添加了判断游戏是否成功的功能;在上期的基础上,本期笔者将在游戏内导入更多题目,并实现游戏处于关卡选择页面时进入不同关卡的页面跳转逻辑。
上期的内容回顾——>>https://ost.51cto.com/posts/17819
正文
利用xml布局创建UI
打开entry>src>main>resouce>base>graphic,并在graphic目录下新创建一个xml文件(可以通过复制粘贴graphic目录下的其他xml文件来实现),将其命名为select_text.xml,最后在文件内将代码修改为如下:
<?xml version="1.0" encoding="UTF-8" ?>
<state-container xmlns:ohos="http://schemas.huawei.com/res/ohos" >
<item ohos:state="component_state_pressed" ohos:element="#007CFD"/>
<item ohos:state="component_state_empty" ohos:element="white"/>
</state-container>
接着,在graphic目录下再次新创建一个xml文件,将其命名为select_text_exit.xml,并在文件内添加如下代码:
<?xml version="1.0" encoding="UTF-8" ?>
<state-container xmlns:ohos="http://schemas.huawei.com/res/ohos" >
<item ohos:state="component_state_pressed" ohos:element="red"/>
<item ohos:state="component_state_empty" ohos:element="white"/>
</state-container>
这样以后,我们就完成了两类组件背景元素的创建,而这两类组件背景元素所实现的UI效果是:当组件处于被点击的状态时,组件改变颜色;当组件未处于被点击的·状态时,组件保持初始的颜色。
之后,打开entry>src>main>resouce>base>layout,并在layout目录下新创建一个xml文件(可以通过复制粘贴layout目录下的其他xml文件来实现),将其命名为select.xml,
最后在文件内将代码修改为如下:
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<Text
ohos:id="$+id:btn1"
ohos:background_element="$graphic:select_text" //引用先前创建的背景元素
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="30vp"
ohos:text="第一关 入门"
ohos:text_alignment="horizontal_center"
ohos:bottom_margin="15vp"/>
<Text
ohos:id="$+id:btn2"
ohos:background_element="$graphic:select_text"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="30vp"
ohos:text="第二关 初级"
ohos:text_alignment="horizontal_center"
ohos:bottom_margin="15vp"
/>
<Text
ohos:id="$+id:btn3"
ohos:background_element="$graphic:select_text"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="30vp"
ohos:text="第三关 中级"
ohos:text_alignment="horizontal_center"
ohos:bottom_margin="15vp"
/>
<Text
ohos:id="$+id:btn4"
ohos:background_element="$graphic:select_text"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="30vp"
ohos:text="第四关 中级"
ohos:text_alignment="horizontal_center"
ohos:bottom_margin="15vp"
/>
<Text
ohos:id="$+id:btn5"
ohos:background_element="$graphic:select_text"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="30vp"
ohos:text="第五关 高级"
ohos:text_alignment="horizontal_center"
ohos:bottom_margin="15vp"
/>
<Text
ohos:id="$+id:Aa"
ohos:background_element="$graphic:select_text"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="30vp"
ohos:text_alignment="horizontal_center"
ohos:bottom_margin="15vp"
/>
<Text
ohos:id="$+id:btn6"
ohos:background_element="$graphic:select_text_exit"
ohos:height="match_content"
ohos:width="match_parent"
ohos:text_size="30vp"
ohos:text="退出"
ohos:text_alignment="horizontal_center"
ohos:top_margin="55vp"
/>
</DirectionalLayout>
这样以后,我们就完成了基本的组件布局,当然,此xml文件在后文是要与关卡选择界面相绑定的。此时可以打开previewer预览UI效果。
在SelectAbilitySlice内完善交互逻辑
打开先前创建的SelectAbilitySlice(目录路径:entry\src\main\java\com.example.project\slice\SelectAbilitySlice),将代码修改为如下:
package ...
import ......
public class SelectAbilitySlice extends AbilitySlice { //继承AbilitySlice类
private String level; //定义字符串level,
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_select);//绑定先前创建的layout类xml文件
}
@Override
protected void onActive() {
super.onActive();
//将select.xml文件中的6个text组件在AbilitySlice中声明
Text text1=(Text) findComponentById(ResourceTable.Id_btn1);
Text text2=(Text) findComponentById(ResourceTable.Id_btn2);
Text text3=(Text) findComponentById(ResourceTable.Id_btn3);
Text text4=(Text) findComponentById(ResourceTable.Id_btn4);
Text text5=(Text) findComponentById(ResourceTable.Id_btn5);
Text text6=(Text) findComponentById(ResourceTable.Id_btn6);
Intent intent_go=new Intent();//创建一个intent对象
text1.setClickedListener((Component component)->{
intent_go.setParam("level","0");
present(new GameAbilitySlice(),intent_go);
});
text2.setClickedListener((Component component)->{
intent_go.setParam("level","1");
present(new GameAbilitySlice(),intent_go);
});
text3.setClickedListener((Component component)->{
intent_go.setParam("level","2");
presen(new GameAbilitySlice(),intent_go);
});
text4.setClickedListener((Component component)->{
intent_go.setParam("level","3");
present(new GameAbilitySlice(),intent_go);
});
text5.setClickedListener((Component component)->{
intent_go.setParam("level","4");
present(new GameAbilitySlice(),intent_go);
});
text6.setClickedListener((Component component)->{
terminate();
});
}
@Override
protected void onResult(int request_code,Intent intent_back){
super.onResult(request_code,intent_back);
}
@Override
protected void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
protected void onBackground() {
super.onBackground();
}
}
在此次的代码添加中,笔者先是扩展了SelectAbilitySlice的框架,并将SelectAbilitySlice与select.xml绑定,这样以后SelectAbilitySlice就可以显示select.xml内设定的布局元素;接着,我们在onActive()函数内声明了已在select.xml设定的6个text组件,并为每个text组件都设定了点击监听器;最后,我们创建了一个intent对象,并在每个text对象的点击监听器内加入指令:将需要传递的数字信息以字符串的形式储存在inent中,并调用present()函数执行页面跳转(从SelectAbilitySlice跳转至新创建的GameAbilitySlice)。由于intent是两个AbilitySlice的信息传递媒介,故当页面导航至新生成的GameAbilitySlice时,GameAbilitySlice可以接收到来自SelectAbilitySlice的intent,而这个intent也是携带重要的数字信息的(点击不同的text组件,intent所携带的数字信息也不同)。关于intent的接收,笔者将在后文阐述。
有关页面跳转与intent的知识可以参考:https://ost.51cto.com/posts/8479
完成上述操作后,我们打开MainAbilitySlice,设置其页面导航路由,使得我们在主界面点击“开始游戏”后,系统界面可以从主界面跳转至关卡选择界面:
public class MainAbilitySlice extends AbilitySlice {
@Override
...
@Override
public void onActive() {
super.onActive();
//通过id号获取xml文件中的button组件
Button button1=(Button) findComponentById(ResourceTable.Id_Game);
button1.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
present(new SelectAbilitySlice(),new Intent());//点击此组件后,页面将从MainAbilitySlice跳转至SelectAbilitySlice
}
});
}
@Override
...
再打开MainAbility,将PageAbility默认展示界面改为InitialAbilitySlice:
......
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(InitialAbilitySlice.class.getName()); //将参数改为改为InitialAbilitySlice
}
}
完成以上操作后,我们可以打开模拟机查看效果:当界面跳转至游戏的主界面时,我们点击“开始游戏”,游戏则会跳转到关卡选择的画面。
点击
导入更多的数独题目
在GameAbilitySlice合适的位置加入如下八个数组(局部变量),其中,前四个数组用做数独题答案,后四个数组则将用于题目的初始化、与用户交互。
...
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
....
//答案
int[][] grid_v1=new int[6][];
grid_v1[0]=new int[]{5,4,3,1,2,6};
grid_v1[1]=new int[]{6,3,4,2,5,1};
grid_v1[2]=new int[]{2,1,6,5,3,4};
grid_v1[3]=new int[]{3,5,1,6,4,2};
grid_v1[4]=new int[]{4,6,2,3,1,5};
grid_v1[5]=new int[]{1,2,5,4,6,3};
int[][] grid_v2=new int[6][];
grid_v2[0]=new int[]{5,6,1,2,3,4};
grid_v2[1]=new int[]{1,3,5,4,2,6};
grid_v2[2]=new int[]{2,4,6,3,5,1};
grid_v2[3]=new int[]{6,5,2,1,4,3};
grid_v2[4]=new int[]{3,1,4,5,6,2};
grid_v2[5]=new int[]{4,2,3,6,1,5};
int[][] grid_v3=new int[6][];
grid_v3[0]=new int[]{2,1,3,6,4,5};
grid_v3[1]=new int[]{5,4,1,2,3,6};
grid_v3[2]=new int[]{6,3,5,4,2,1};
grid_v3[3]=new int[]{1,6,4,3,5,2};
grid_v3[4]=new int[]{4,2,6,5,1,3};
grid_v3[5]=new int[]{3,5,2,1,6,4};
int[][] grid_v4=new int[6][];
grid_v4[0]=new int[]{5,2,3,4,1,6};
grid_v4[1]=new int[]{6,4,2,1,5,3};
grid_v4[2]=new int[]{3,1,5,6,2,4};
grid_v4[3]=new int[]{1,3,4,2,6,5};
grid_v4[4]=new int[]{2,5,6,3,4,1};
grid_v4[5]=new int[]{4,6,1,5,3,2};
//题目
int[][] grid_c1=new int[6][];
grid_c1[0]=new int[]{5,0,3,0,2,0};
grid_c1[1]=new int[]{0,0,4,2,0,1};
grid_c1[2]=new int[]{2,1,0,0,3,0};
grid_c1[3]=new int[]{0,5,0,0,4,2};
grid_c1[4]=new int[]{4,0,2,3,0,0};
grid_c1[5]=new int[]{0,2,0,4,0,3};
int[][] grid_c2=new int[6][];
grid_c2[0]=new int[]{0,0,1,2,0,0};
grid_c2[1]=new int[]{0,0,0,0,0,0};
grid_c2[2]=new int[]{0,0,0,3,0,1};
grid_c2[3]=new int[]{0,5,2,0,0,3};
grid_c2[4]=new int[]{0,1,4,5,0,2};
grid_c2[5]=new int[]{4,0,0,0,0,0};
int[][] grid_c3=new int[6][];
grid_c3[0]=new int[]{2,0,3,0,4,5};
grid_c3[1]=new int[]{0,0,0,0,0,0};
grid_c3[2]=new int[]{0,0,0,0,2,1};
grid_c3[3]=new int[]{1,6,0,0,0,0};
grid_c3[4]=new int[]{0,0,0,0,0,0};
grid_c3[5]=new int[]{3,5,0,1,0,4};
int[][] grid_c4=new int[6][];
grid_c4[0]=new int[]{5,0,0,0,1,6};
grid_c4[1]=new int[]{0,0,2,0,0,0};
grid_c4[2]=new int[]{0,1,0,0,0,0};
grid_c4[3]=new int[]{0,0,0,0,6,0};
grid_c4[4]=new int[]{0,0,0,3,0,0};
grid_c4[5]=new int[]{4,6,0,0,0,2};
...
之后,定义一个新的二维数组grids_initial(可以是局部变量也可以是局部变量):
int[][] grids_initial=new int[6][];
先找到之前用于创建网格区域的二重for循环:
for (y=0;y<6;y++){
for (x=0;x < 6; x++) {
Button button = new Button(this);
button.setTouchFocusable(true);
number=grid_c0[x][y];
string0=String.valueOf(number);
....
然后进行如下修改(即将数组grid_c0改为数组grids_initial):
for (y=0;y<6;y++){
for (x=0;x < 6; x++) {
Button button = new Button(this);
button.setTouchFocusable(true);
number=grids_initial[x][y];//将数组grid_c0改为数组grids_initial
string0=String.valueOf(number);
...
这样以后,grids_initial就作为唯一用于生成游戏题目的数组变量了。
最后,删除之前在onStart()函数内添加的以下赋值代码:
grids_input=grid_c0;
grids_win=grid_v0;
获取intent
终于来到最后一个环节了。在前文的内容中,我们已经实现了一个功能:系统从SelectAbilitySlice导航至GameAbilitySlice时,GameAbilitySlice可以接收到包含数字信息的intent。
那么如何获取intent中的信息呢?如下列代码所示,我们通过getStringParam方法接收从SelectAbilitySlice传入的intent,并提取其携带的字符串信息(其所对应的键是"level"),再将此字符串转化为整形数据,最后存储在一个新声明的整型变量L中。因为intent中存储的字符串代表用户想要进入的关卡,所以在得到L以后,我们通过switch来判断用户点击的是第几关,并将对应关卡的题目与答案分别赋给三个数组变量:grids_win,grids_input与grids_initial。
......
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
grid_c0[0]=new int[]{0,0,0,0,1,0};
.......
//获取intent
int L=Integer.parseInt(intent.getStringParam("level"));
//判断
switch (L){
case 0: grids_win=grid_v0;grids_input=grid_c0;grids_initial=grid_c0;break;
case 1: grids_win=grid_v1;grids_input=grid_c1;grids_initial=grid_c1;break;
case 2: grids_win=grid_v2;grids_input=grid_c2;grids_initial=grid_c2;break;
case 3: grids_win=grid_v3;grids_input=grid_c3;grids_initial=grid_c3;break;
case 4: grids_win=grid_v4;grids_input=grid_c4;grids_initial=grid_c4;break;
}
这样以后,当用户进入不同关卡时,GameAbilitySlice的题目会根据grids_initial初始化,判断游戏成功与否的Gamesuccess()函数也会获取对应的信息与成功条件,我们也就实现了游戏处于关卡选择页面时进入不同关卡的页面跳转逻辑与功能。
此时我们可以打开模拟器查看交互效果:
点击“第二关”:
进入第二关:
结语
本期的内容就先分享到这里,更多关于数独小游戏项目精彩的内容我将在下期继续为大家揭晓。
不错不错,越来越好了