本篇文章教大家如何在鸿蒙上实现“数字华容道”小游戏。

①打开引用首先为数字华容道的初始界面,点击开始游戏即会切换到数字华容道的游戏界面。

②进入数字华容道的游戏界面显示 3*3 的方阵,方阵中分布有随意打乱的 1 至 8 的数字和一个空白方格,方阵下方显示一个“重新开始”的按钮和一个“返回”按钮。
点击“重新开始”按钮即会重新生成随意打乱的 1 至 8 的数字和一个空白方格的方阵,点击“返回”按钮即会切换到数字华容道的初始界面,最下方有四个指示不同方向箭头的按钮,点击任一按钮或向上、下、左、右任一方向滑动,空白方格周围对应位置的方格便会随之向对应的方向移动一格。
③经过若干次滑动或点击后,当所有的数字按顺序排列后,则会弹出游戏成功的界面,再滑动或点击也不会有任何变化。
创建项目
DevEco Studio 下载安装成功后,打开 DevEco Studio,点击左上角的 File,点击 New,再选择 New Project,选择 Phone 选项,选择默认的模板,然后选择保存路径。
将文件命名为 MyPhoneApplication(文件名不能出现中文或者特殊字符,否则将无法成功创建项目文件),最后点击 Finish。
实现初始界面布局
首先,我们要先实现数字华容道的初始界面,点击开始游戏即会切换到另一页面。

①先在 entry>src>main>config.json 文件中最下方"launchType": “standard"的后面添加以下代码。
并且将上方的“label”:“MyPhoneApplication”修改成"label”: “数字华容道”,这样就实现去掉应用上方的标题栏和将应用名称改为数字华容道了。
config.json 最下面部分代码:
"orientation":"unspecified", "name":"com.example.myphoneapplication.MainAbility", "icon":"$media:icon", "description":"$string:mainability_description", "label":"数字华容道", "type":"page", "launchType":"standard", "metaData":{ "customizeData":[ { "name":"hwc-theme", "value":"androidhwext:style/Theme.Emui.Light.NoTitleBar", "extra":"" } ] }②先将我们事先准备好的图片复制粘贴到 entry>src>main>resources>base>media 文件夹中,并且命名为 game,点击 OK。

在 entry>src>main>resources>base>layout>ability_main.xml 中添加布局。 先将事先存在的 Text 组件删去,添加 Image 图片组件,引入我们刚才复制粘贴的图片,再添加一个 Button 按钮组件,加入唯一标识符 id 并配置好其他相应的属性。
③在 entry>src>main>java>com.example.myphoneapplication>slice 中右键选择 New>Java Class 增加一个空白的类以用来后面编写数字。 华容道的游戏界面,并且命名为 SecondAbilitySlice 在这里插入图片描述。
将
entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice
中的代码修改成如下:
packagecom.example.myphoneapplication.slice;
importcom.example.myphoneapplication.ResourceTable;
importohos.aafwk.ability.AbilitySlice;
importohos.aafwk.content.Intent;
publicclassSecondAbilitySliceextendsAbilitySlice{
publicvoidonStart(Intentintent){
super.onStart(intent);
}
@Override
publicvoidonActive(){
super.onActive();
}
@Override
publicvoidonForeground(Intentintent){
super.onForeground(intent);
}
}
④在下面代码中的 onStart 函数中添加一个按钮指向我们(2)中添加的按钮。
entry>src>main>java>com.example.myphoneapplication>slice>MainAbilitySlice按钮添加一个响应点击事件的函数,用 parsent 函数跳转到 SecondAbilitySlice。
packagecom.example.myphoneapplication.slice;
importcom.example.myphoneapplication.ResourceTable;
importohos.aafwk.content.Intent;
importohos.agp.components.Button;
importohos.agp.components.Component;
publicclassMainAbilitySliceextendsohos.aafwk.ability.AbilitySlice{
@Override
publicvoidonStart(Intentintent){
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
Buttonbutton=(Button)findComponentById(ResourceTable.Id_button_game);
button.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
present(newSecondAbilitySlice(),newIntent());
}
});
}
@Override
publicvoidonActive(){
super.onActive();
}
@Override
publicvoidonForeground(Intentintent){
super.onForeground(intent);
}
}
实现数字的随机打乱
然后我们要在数字华容道的游戏界面生成随意打乱的 1 至 15 的数字和一个空白方格的方阵。
在这里编写代码:
entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice先定义个一个位置布局 layout 和一个二维数组 grids,创建函数 initializeinitialize() 分别对其初始化,在 onStart 函数中调用函数 initializeinitialize()。
privatefloatstarX,starY,distanceX,distanceY;
privateDirectionalLayoutlayout;
privateint[][]grids;
publicvoidonStart(Intentintent){
super.onStart(intent);
initialize();
}
publicvoidinitialize(){
layout=newDirectionalLayout(this);
grids=newint[][]{{1,2,3,4},{5,6,7,8,},{9,10,11,12},{13,14,15,0}};
}
然后定义函数 drawGrids(int[][] grids) 用于绘制 4*4 方阵和其二维数组对应的数字。
publicvoiddrawGrids(int[][]grids){
layout.setLayoutConfig((newComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,ComponentContainer.LayoutConfig.MATCH_PARENT)));
Component.DrawTasktask=newComponent.DrawTask(){
publicvoidonDraw(Componentcomponent,Canvascanvas){
PaintmPaint=newPaint();
mPaint.setColor(Color.GRAY);
RectFloatrect=newRectFloat(2,230,1078,1306);
canvas.drawRect(rect,mPaint);
for(introw=0;row< 4; row++){
for(int column = 0; column < 4; column++){
mPaint.setColor(Color.CYAN);
RectFloat rectFloat=new RectFloat(22+column*262,250+row*262,272+column*262,500+row*262);
canvas.drawRect(rectFloat,mPaint);
mPaint.setColor(Color.YELLOW);
mPaint.setTextSize(125);
if(grids[row][column]!=0){
if(grids[row][column]<10){
canvas.drawText(mPaint, String.valueOf(grids[row][column]),105+column*262,425+row*262);
}
else{
canvas.drawText(mPaint, String.valueOf(grids[row][column]),65+column*262,425+row*262);
}
}
}
}
}
};
layout.addDrawTask(task);
setUIContent(layout);
}
再定义函数 changeGrids(int[][] grids,int direction),每次接收一个方向,2 表示上移,-1 表示左移,1 表示右移,-2 表示下移,找出空白方格所在位置对应的二维数组下标,对应的方格和空白方格对应的二维数组的数值对调。
publicvoidchangeGrids(int[][]grids,intdirection){ introw_0=3; intcolumn_0=3; inttemp; for(introw=0;row< 4; row++) { for (int column = 0; column < 4; column++) { if(grids[row][column] == 0){ row_0 = row; column_0 = column; } } } if(direction == -1 && (column_0 + 1) <= 3){ temp = grids[row_0][column_0 + 1]; grids[row_0][column_0 + 1] = grids[row_0][column_0]; grids[row_0][column_0] = temp; }else if (direction == 1 && (column_0 - 1) >=0){ temp=grids[row_0][column_0-1]; grids[row_0][column_0-1]=grids[row_0][column_0]; grids[row_0][column_0]=temp; }elseif(direction==2&&(row_0+1)<= 3) { temp = grids[row_0 + 1][column_0]; grids[row_0 + 1][column_0] = grids[row_0][column_0]; grids[row_0][column_0] = temp; } else if (direction == -2 && (row_0 - 1) >=0){ temp=grids[row_0-1][column_0]; grids[row_0-1][column_0]=grids[row_0][column_0]; grids[row_0][column_0]=temp; } }
定义函数 createGrids(int[][] grids) 用于随机生成一个表示方向的数字,循环调用函数 changeGrids(grids,direction) 用于随机打乱二维数组对应的数字。
publicvoidcreateGrids(int[][]grids){
int[]array={-1,-2,1,2};
for(inti=0;i< 100; i++){
int random = (int)Math.floor(Math.random()*4);
int direction = array[random];
changeGrids(grids,direction);
}
}
最后在initialize()函数中调用createGrids(grids)函数和drawGrids(grids)函数
public void initialize(){
layout = new DirectionalLayout(this);
grids = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8,}, {9, 10, 11, 12}, {13, 14, 15, 0}};
createGrids(grids);
drawGrids(grids);
}
实现滑动或点击调换数字
添加“重新开始”和“返回”按钮,在每个方块下面添加不同方向箭头的按钮,点击方块并向上、下、左、右任一方向滑动,空白方格周围对应位置的方格便会随之向对应的方向移动一格。

在这里编写代码:
entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice
先定义一个函数 drawButton() 用于绘制所有的按钮,四个指示不同方向箭头的按钮分别添加四个响应点击事件的函数。
分别调用对应的 changeGrids(grids,direction) 函数实现空白方格周围对应位置的方格便会随之向对应的方向移动一格,并调用 drawGrids(grids) 函数用于绘制新的方阵。
publicvoiddrawButton(){
Buttonbutton=newButton(this);
button.setText("重新开始");
button.setTextSize(100);
button.setTextAlignment(TextAlignment.CENTER);
button.setTextColor(Color.WHITE);
button.setMarginTop(1400);
button.setMarginLeft(80);
button.setPadding(20,20,20,20);
ShapeElementbackground=newShapeElement();
background.setRgbColor(newRgbColor(174,158,143));
background.setCornerRadius(100);
button.setBackground(background);
layout.addComponent(button);
Buttonbutton0=newButton(this);
button0.setText("返回");
button0.setTextSize(100);
button0.setTextAlignment(TextAlignment.CENTER);
button0.setTextColor(Color.WHITE);
button0.setMarginTop(-170);
button0.setMarginLeft(680);
button0.setPadding(20,20,20,20);
button0.setBackground(background);
layout.addComponent(button0);
ShapeElementbackground0=newShapeElement();
background0.setRgbColor(newRgbColor(174,158,143));
background0.setCornerRadius(100);
Buttonbutton1=newButton(this);
button1.setText("↑");
button1.setTextAlignment(TextAlignment.CENTER);
button1.setTextColor(Color.WHITE);
button1.setTextSize(100);
button1.setMarginLeft(500);
button1.setMarginTop(70);
button1.setPadding(10,0,10,0);
button1.setBackground(background0);
button1.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
changeGrids(grids,2);
}
});
layout.addComponent(button1);
Buttonbutton2=newButton(this);
button2.setText("←");
button2.setTextAlignment(TextAlignment.CENTER);
button2.setTextColor(Color.WHITE);
button2.setTextSize(100);
button2.setMarginTop(10);
button2.setMarginLeft(400);
button2.setPadding(10,0,10,0);
button2.setBackground(background0);
button2.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
changeGrids(grids,-1);
}
});
layout.addComponent(button2);
Buttonbutton3=newButton(this);
button3.setText("→");
button3.setTextAlignment(TextAlignment.CENTER);
button3.setTextColor(Color.WHITE);
button3.setTextSize(100);
button3.setMarginLeft(600);
button3.setMarginTop(-130);
button3.setPadding(10,0,10,0);
button3.setBackground(background0);
button3.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
changeGrids(grids,1);
}
});
layout.addComponent(button3);
Buttonbutton4=newButton(this);
button4.setText("↓");
button4.setTextAlignment(TextAlignment.CENTER);
button4.setTextColor(Color.WHITE);
button4.setTextSize(100);
button4.setMarginLeft(500);
button4.setMarginTop(10);
button4.setPadding(10,0,10,0);
button4.setBackground(background0);
button4.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
changeGrids(grids,-2);
}
});
layout.addComponent(button4);
drawGrids(grids);
}
然后添加一个函数 slideGrids() 为布局 layout 添加一个滑动事件,并获取滑动开始与结束的坐标,并计算出大致的滑动方向。
分别调用对应的 changeGrids(grids,direction) 函数实现空白方格周围对应位置的方格便会随之向对应的方向移动一格,并调用 drawGrids(grids) 函数用于绘制新的方阵,并在开头添加相应的变量。
privatefloatstarX,starY,distanceX,distanceY;
publicvoidslideGrids(){
layout.setTouchEventListener(newComponent.TouchEventListener(){
@Override
publicbooleanonTouchEvent(Componentcomponent,TouchEventtouchEvent){
MmiPointpoint=touchEvent.getPointerScreenPosition(0);
switch(touchEvent.getAction()){
caseTouchEvent.PRIMARY_POINT_DOWN:
starX=point.getX();
starY=point.getY();
break;
caseTouchEvent.PRIMARY_POINT_UP:
distanceX=point.getX()-starX;
distanceY=point.getY()-starY;
break;
}
if(gameover()==false){
if(Math.abs(distanceX)>Math.abs(distanceY)){
if(distanceX>200){
changeGrids(grids,1);
}elseif(distanceX< -200) {
changeGrids(grids,-1);
}
} else if (Math.abs(distanceX) < Math.abs(distanceY)){
if (distanceY >200){
changeGrids(grids,-2);
}elseif(distanceY< -200) {
changeGrids(grids,2);
}
}
}
drawGrids(grids);
return false;
}
});
}
最后在 initialize() 函数中调用 slideGrids() 函数和 drawButton() 函数。
publicvoidinitialize(){
layout=newDirectionalLayout(this);
grids=newint[][]{{1,2,3,4},{5,6,7,8,},{9,10,11,12},{13,14,15,0}};
createGrids(grids);
slideGrids();
drawButton();
drawGrids(grids);
}
实现游戏成功界面
点击“重新开始”按钮即会重新生成随意打乱的 1 至 15 的数字和一个空白方格的方阵,点击“返回”按钮即会切换到数字华容道的初始界面。 经过若干次滑动或点击后,当所有的数字按顺序排列后,则会弹出游戏成功的界面,再滑动或点击也不会有任何变化。 
在这里编写代码:
entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice首先定义一个函数 drawText() 用于绘制游戏成功字样。
publicvoiddrawText(){
Texttext=newText(this);
text.setText("游戏成功");
text.setTextSize(100);
text.setTextColor(Color.BLUE);
text.setTextAlignment(TextAlignment.CENTER);
text.setMarginsTopAndBottom(-2000,0);
text.setMarginsLeftAndRight(350,0);
layout.addComponent(text);
setUIContent(layout);
}
然后定义一个函数 gameover() 用于判断二维数组的数字是否按顺序排列,当二维数组的数字按顺序排列时返回 true,否则返回 false。
publicbooleangameover(){
int[][]gameoverGrids={{1,2,3,4},{5,6,7,8,},{9,10,11,12},{13,14,15,0}};
for(introw=0;row< 4; row++) {
for (int column = 0; column < 4; column++) {
if (grids[row][column] != gameoverGrids[row][column]) {
return false;
}
}
}
return true;
}
再在 drawButton() 函数中重新开始按钮中添加一个响应点击事件的函数,用于调用函数 initialize() 实现重新生成随意打乱的 1 至 15 的数字和一个空白方格的方阵,返回按钮中添加一个响应点击事件的函数。 用 parsen 函数返回数字华容道的初始界面,四个指示不同方向箭头的按钮的响应点击事件的函数中增加一个判断。 当函数 gameover() 返回为 false 时才调用各自的 changeGrids(grids,direction) 函数。
最后增加一个判断,当函数 gameover() 返回为 true 时调用函数 drawText()。
publicvoiddrawButton(){//部分代码没有贴出,可自行下载源代码查看
button.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
initialize();
}
});
button0.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
present(newSecondAbilitySlice(),newIntent());
}
});
button1.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
if(gameover()==false){
changeGrids(grids,2);
}
}
});
button2.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
if(gameover()==false){
changeGrids(grids,-1);
}
}
});
button3.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
if(gameover()==false){
changeGrids(grids,1);
}
}
});
button4.setClickedListener(newComponent.ClickedListener(){
@Override
publicvoidonClick(Componentcomponent){
if(gameover()==false){
changeGrids(grids,-2);
}
}
});
if(gameover()){
drawText();
}
}
在函数 slideGrids() 函数中增加一个判断,当函数 gameover() 返回为 false 时才调用 changeGrids(grids,direction) 函数,最后增加一个判断,当函数 gameover() 返回为 true 时调用函数 drawText()。
publicvoidslideGrids(){//部分代码没有贴出,可自行下载源代码查看
if(gameover()==false){
//{...}
}
if(gameover()){
drawText();
}
}
审核编辑:汤梓红
-
游戏
+关注
关注
2文章
787浏览量
27246 -
函数
+关注
关注
3文章
4406浏览量
66839 -
鸿蒙
+关注
关注
60文章
2858浏览量
45355
原文标题:鸿蒙上实现“数字华容道”小游戏
文章出处:【微信号:gh_834c4b3d87fe,微信公众号:OpenHarmony技术社区】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录

鸿蒙上实现“数字华容道”小游戏
评论