【木棉花】#夏日挑战赛# 鸿蒙小游戏项目——数独Sudoku(4) 原创 精华
前言
在上期的分享中,笔者阐述了数字填入功能的开发流程。而在本期的分享中,笔者将分享一个非常有趣的内容。
上期的内容回顾——>>https://ost.51cto.com/posts/14551
正文
在数字填入的功能实现之后,我们下一步要做的就是写入判断游戏成功的相关逻辑代码。
关于数独游戏成功的判定,笔者思考过两种办法,一种是写递归算法来判断用户填入的答案是否满足游戏的胜利规则,另一种则是预先准备数独游戏的正确答案,然后将读者输入的答案与正确答案进行校对。这两种方法都有一点难度,而笔者尝试的方法是后者。
在第二期的分享中,笔者定义了一个二维数组grid_c0,作为数独游戏的一道题目。本期我们就以这道题目为例,来探索数独游戏成功的判定方法。
首先,我们给出grid_c0对应的答案的二维数组grid_v0,grid_v0所对应的矩阵如下:
4 3 5 6 1 2
1 5 2 4 6 3
6 2 3 1 4 5
5 4 1 2 3 6
2 6 4 3 5 1
3 1 6 5 2 4
当用户在网格区域的某个白色方格填入数字时,比如,在第二行第一列填入数字5时,我们可以在标有数字“5”的圆形Button组件的点击监听器中增加一个指令:grid_c0[j1][k1]=5(其中,j1=2,k1=1);
那么grid_c0对应的矩阵就会由原来的:
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
变成:(第二行第一列变成了5)
0 1 6 5 0 3
5 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
类似这样,我们可以在Button组件的点击监听器上增加指令,使得玩家每填入一次数字,grid_v0对应的矩阵都会发生变化;之后,我们再加入一个游戏判断的函数,用于判断grid_v0与grid_c0是否相等,若相等则游戏胜利。
不过我们现在面临一个问题——点击网格区域的某个白色Button组件的时候,我们需要获取这个白色Button组件在for循环中对应的x和y的值(以确定j1和k1),这样我们才能知道此Button组件是位于第几行第几列的,我们才能精准地传输指令。
在本期的内容中,笔者将具体阐述得到网格区域中每个Button组件所在的行和列的方法
首先,我们先定义两个整型数据j1,k1:
package com.example.project.slice;
import ...
public class GameAbilitySlice extends AbilitySlice {
...
int j1;
int k1;
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
..
}
}
接着,我们找到之前写入的二重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);
button.setText(string0);
button.setTextColor(Color.WHITE);
button.setTextSize(75);
button.setComponentSize(160, 160);
button.setContentPosition(65+160* x, 230+160*y);
if (number==0) {
button.setText("");
button.setBackground(element0);
button.setTextColor(Color.BLACK);
button.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
button_temp = button;
}
});
button.setComponentStateChangedListener(new Component.ComponentStateChangedListener() {
@Override
public void onComponentStateChanged(Component component, int i) {
if (ComponentState.isStateMatched(ComponentState.COMPONENT_STATE_FOCUSED,i)){
button.setBackground(element1);
}else{
button.setBackground(element0);
}
}
});
}else{
button.setBackground(element3);
button.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
button_temp=button_empty;
}
});
}
layout1.addComponent(button);
}
}
我们对代码进行如下修改:
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);
button.setText(string0);
button.setTextColor(Color.WHITE);
button.setTextSize(75);
button.setComponentSize(160, 160);
button.setContentPosition(65+160* x, 230+160*y);
//定义一个专门用于储存x和y的Text组件
Text text=new Text(this);
if (number==0) {
button.setText("");
button.setBackground(element0);
button.setTextColor(Color.BLACK);
//将x与y以字符串信息的方式储存
string1=String.valueOf(x);
string2=String.valueOf(y);
text.setText(string1+string2);
button.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
button_temp = button;
//定义两个整形数据j和k
int j=1;
int k=1;
string3=text.getText();
//翻译Text组件带有的信息
if(string3.equals("00")){j=0;k=0;}
if(string3.equals("10")){j=1;k=0;}
if(string3.equals("20")){j=2;k=0;}
if(string3.equals("30")){j=3;k=0;}
if(string3.equals("40")){j=4;k=0;}
if(string3.equals("50")){j=5;k=0;}
if(string3.equals("01")){j=0;k=1;}
if(string3.equals("11")){j=1;k=1;}
if(string3.equals("21")){j=2;k=1;}
if(string3.equals("31")){j=3;k=1;}
if(string3.equals("41")){j=4;k=1;}
if(string3.equals("51")){j=5;k=1;}
if(string3.equals("02")){j=0;k=2;}
if(string3.equals("12")){j=1;k=2;}
if(string3.equals("22")){j=2;k=2;}
if(string3.equals("32")){j=3;k=2;}
if(string3.equals("42")){j=4;k=2;}
if(string3.equals("52")){j=5;k=2;}
if(string3.equals("03")){j=0;k=3;}
if(string3.equals("13")){j=1;k=3;}
if(string3.equals("23")){j=2;k=3;}
if(string3.equals("33")){j=3;k=3;}
if(string3.equals("43")){j=4;k=3;}
if(string3.equals("53")){j=5;k=3;}
if(string3.equals("04")){j=0;k=4;}
if(string3.equals("14")){j=1;k=4;}
if(string3.equals("24")){j=2;k=4;}
if(string3.equals("34")){j=3;k=4;}
if(string3.equals("44")){j=4;k=4;}
if(string3.equals("54")){j=5;k=4;}
if(string3.equals("05")){j=0;k=5;}
if(string3.equals("15")){j=1;k=5;}
if(string3.equals("25")){j=2;k=5;}
if(string3.equals("35")){j=3;k=5;}
if(string3.equals("45")){j=4;k=5;}
if(string3.equals("55")){j=5;k=5;}
j1=j;
k1=k;
}
});
button.setComponentStateChangedListener(new Component.ComponentStateChangedListener() {
@Override
public void onComponentStateChanged(Component component, int i) {
if (ComponentState.isStateMatched(ComponentState.COMPONENT_STATE_FOCUSED,i)){
button.setBackground(element1);
}else{
button.setBackground(element0);
}
}
});
}else{
button.setBackground(element3);
button.setClickedListener(new Component.ClickedListener() {
@Override
public void onClick(Component component) {
button_temp=button_empty;
}
});
}
layout1.addComponent(button);
}
}
在这次的修改中,我们先是在for循环内创建了Text组件。我们知道,之前的二重for循环能创建36个Button组件,而在本次的修改后,二重for循环每创建一个Button组件的同时都会附属性地创建一个Text组件,也是一共会创建36个Text组件。
为什么说这个Text组件能存储x和y的信息呢?事实上,这个通过代码布局所创建的Text组件并不会在UI界面中展示出来,因为我们并没有定义Text组件的与视觉相关的必要属性(如组件大小,字体大小),但这个Text组件既然被创建了出来,它仍是会占用内存的。在上面加入的代码中,我们先是将每个Text组件在for循环中对应的x和y转换成字符串后,用于定义Text组件的显示文本内容,然后在白色Button组件的监听器中,通过getText.()函数将Text组件的文本信息提取出来,最后再写36个if来判断和输出这些文本信息,得到Text组件在for循环中x和y的信息(即j1和k1)。
由于每个Text组件都“附属于”一个网格区域中的Button组件,所以获得Text组件在for循环中的x和y的信息相当于获得Button组件在for循环中的x和y的信息,由此,我们在点击网格区域中的任一白色Button组件时,我们能获得它的行和列的信息(即j1和k1),进而可以通过grid_c0[j1][k1]=t(1<=t<=6,t为整数)的指令修改grid_c0。
上述的代码思路,实质上是一个将整形数据转化为字符串数据存储在Text组件中后,再将Text组件中携带的字符串数据重新转化为整形数据的过程。
结尾
本期的内容就先分享到这里,更多关于数独小游戏项目精彩的内容我将在下期继续为大家揭晓。
本期的内容大家可能会比较难get到笔者想表达的点
mark
感受到了规则制定的不易。