最强大脑之《数字华容道》游戏Android端的具体实现

简介: 其实我的实现方式很是简单,自定义一个View,确定View大小后,绘制八个格子,确定八个格子的左上右下,随机给八个格子绘制数据,比如第八个格子绘制的是“1”,那么,随着手势的移动当第八个格子也就是“1”的左上右下和第一个格子的左上右下相等时,那么这个格子的位置是正确的,同理,其它格子也是如此实现,当所有的格子都找到位置后,一一比较都是相等的,那么我们就可以判断,移动成功,那么就可以进入下一关了。

游戏效果:


image.gif


前提摘要:


前两天粘贴出来了地址,不知道大家下载了没有,如果玩的话,是不是发现了几个潜在的问题,如果按完开始键后,不停的点击上一关或者下一关就会出现应用闪退的情况,这种情况是toast的问题,目前已经修复,当然了还有,滑着滑着,有的格子就不见了的问题,这种问题,虽然很少见,但是确实出现过,它是因为滑动的距离过长,本来是走一格,一不小心多走了一格,这就尴尬了,我觉得最大的问题就是滑着不是很灵敏,有时滑不动,这样那样潜在的问题是很多了,毕竟这个简单的游戏,仅仅用了十几个小时开发出来的,问题是在所难免的,大家有兴趣的可以去优化。


灵感源于:


来新公司有一段时间了,由于处于没有需求的状态,只好不停的去学习,去研究一些自己感兴趣的技术,之前没有去开源的东西,自己也正在逐步的整理,逐步的开源,前几天,新的一季最强大脑已经开播了,模式似乎发生了改变,不过具有智慧的游戏还是依旧未变,第一集的数字华容道便是我的灵感,打乱的格子推来推去,紧张的时间下,透露着分秒必争,那么我能不能做一个呢,于是,就开始尝试了起来。


代码存在问题:


毋庸置疑,代码是很烂的,很多都是重复性的代码,自己写的,看的都想吐,我也准备做一个抽取,当然了,大家也可以去优化,也许网上也有很多的实现方式,毕竟思维不一样,实现也不一样也许别人的更加简单,更高级,这个是不能否定的,自己水平有限,也只能这样了。


具体实现:


其实我的实现方式很是简单,自定义一个View,确定View大小后,绘制八个格子,确定八个格子的左上右下,随机给八个格子绘制数据,比如第八个格子绘制的是“1”,那么,随着手势的移动当第八个格子也就是“1”的左上右下和第一个格子的左上右下相等时,那么这个格子的位置是正确的,同理,其它格子也是如此实现,当所有的格子都找到位置后,一一比较都是相等的,那么我们就可以判断,移动成功,那么就可以进入下一关了,如下图。


image.gif


主要代码(这里只贴出主要实现的代码,全部代码请下载源码,源码里都有注释):


/*** 记录每个格子移动的左上右下* rect0:空白格子,rect1:第一个格子 ……* x_0:左* x_1:右* y_0:上* y_1:下* x_t:绘制文字的x坐标* y_t:绘制文字的y坐标* */privateintrect0_x_0,rect0_x_1,rect0_y_0,rect0_y_1;//空隙位置privateintrect1_x_0,rect1_x_1,rect1_y_0,rect1_y_1,rect1_x_t,rect1_y_t;
privateintrect2_x_0,rect2_x_1,rect2_y_0,rect2_y_1,rect2_x_t,rect2_y_t;
privateintrect3_x_0,rect3_x_1,rect3_y_0,rect3_y_1,rect3_x_t,rect3_y_t;
privateintrect4_x_0,rect4_x_1,rect4_y_0,rect4_y_1,rect4_x_t,rect4_y_t;
privateintrect5_x_0,rect5_x_1,rect5_y_0,rect5_y_1,rect5_x_t,rect5_y_t;
privateintrect6_x_0,rect6_x_1,rect6_y_0,rect6_y_1,rect6_x_t,rect6_y_t;
privateintrect7_x_0,rect7_x_1,rect7_y_0,rect7_y_1,rect7_x_t,rect7_y_t;
privateintrect8_x_0,rect8_x_1,rect8_y_0,rect8_y_1,rect8_x_t,rect8_y_t;
获取View的宽高,及每个格子的宽高:mWidth=getMeasuredWidth();
mHeight=getMeasuredHeight();
floatX_6=mWidth/6;
floatY_6=mHeight/6;
floatX=mWidth/3;
floatY=mHeight/3;
初始化八个格子和空白格子的位置,这里的padding等于10dp,是边框距离左上右下的距离/*** 第一个格子的位置* */privatevoidcreateView_1() {
rect1_x_0=padding;
rect1_x_1=floatX+padding;
rect1_y_0=padding;
rect1_y_1=floatY+padding;
rect1_x_t=(floatX+padding)/2;
rect1_y_t=(floatY+padding)/2;
}
/*** 第二个格子的位置* */privatevoidcreateView_2() {
rect2_x_0=padding+floatX;
rect2_x_1=floatX*2+padding;
rect2_y_0=padding;
rect2_y_1=floatY+padding;
rect2_x_t=(floatX*2+padding)-floatX_6;
rect2_y_t=(floatY+padding)/2;
}
/*** 第三个格子的位置* */privatevoidcreateView_3() {
rect3_x_0=padding+floatX*2;
rect3_x_1=mWidth-padding;
rect3_y_0=padding;
rect3_y_1=floatY+padding;
rect3_x_t=(mWidth-padding)-floatX_6;
rect3_y_t=(floatY+padding)/2;
}
/*** 第四个格子的位置* */privatevoidcreateView_4() {
rect4_x_0=padding;
rect4_x_1=floatX+padding;
rect4_y_0=padding+floatY;
rect4_y_1=floatY*2+padding;
rect4_x_t=(floatX+padding)/2;
rect4_y_t=(floatY*2+padding)-floatY_6;
}
/*** 第五个格子的位置* */privatevoidcreateView_5() {
rect5_x_0=padding+floatX;
rect5_x_1=floatX*2+padding;
rect5_y_0=padding+floatY;
rect5_y_1=floatY*2+padding;
rect5_x_t=(floatX*2+padding)-floatX_6;
rect5_y_t=(floatY*2+padding)-floatY_6;
}
/*** 第六个格子的位置* */privatevoidcreateView_6(){
rect6_x_0=padding+floatX*2;
rect6_x_1=mWidth-padding;
rect6_y_0=padding+floatY;
rect6_y_1=floatY*2+padding;
rect6_x_t=(mWidth-padding)-floatX_6;
rect6_y_t=(floatY*2+padding)-floatY_6;
}
/*** 第七个格子的位置* */privatevoidcreateView_7(){
rect7_x_0=padding;
rect7_x_1=floatX+padding;
rect7_y_0=padding+floatY*2;
rect7_y_1=mHeight-padding;
rect7_x_t=(floatX+padding)/2;
rect7_y_t=(mHeight-padding)-floatY_6;
}
/*** 第八个格子的位置* */privatevoidcreateView_8() {
rect8_x_0=padding+floatX;
rect8_x_1=floatX*2+padding;
rect8_y_0=padding+floatY*2;
rect8_y_1=mHeight-padding;
rect8_x_t=(floatX*2+padding)-floatX_6;
rect8_y_t=(mHeight-padding)-floatY_6;
}
/*** 每次移动格子,记录空白格子的位置* */privatevoidcreateView_9(intnum1,intnum2,intnum3,intnum4) {
Log.i("createView_9",num1+"==="+num2+"==="+num3+"==="+num4);
rect0_x_0=num1;
rect0_x_1=num2;
rect0_y_0=num3;
rect0_y_1=num4;
}


onTouchEvent事件:当手指抬起的时候去移动格子,根据手指抬起的XY坐标和空白格子进行比较,如果条件符合,那么就可以执行下一步,否则不让移动,目的解决乱移动现象,具体移动多少,才可以移动格子,这里我设置的是手指必须移动的距离,必须得大于一格半,MainActivity.isStart是我设置的一个开始暂停按钮。


具体是否移动了哪一格:需要根据按下的XY进行判断,这里我只列出了第一个格,其它格子判断和第一格一样,都是一些重复性的代码。


caseMotionEvent.ACTION_UP:
upX= (int) event.getX();
upY= (int) event.getY();
//如果不是大于空白格子,那么就不移动booleanisScroll=upX>rect0_x_0&&upX<rect0_x_1&&upY>rect0_y_0&&upY<rect0_y_1;
if(!isScroll){
returntrue;
    }
//如果移动的距离大于一格半,那么就不移动,必须在一格半之内if(Math.abs(upX-downX)>floatX+floatX/2||Math.abs(upY-downY)>floatY/2+floatY){
returntrue;
    }
if(!MainActivity.isStart){
listener.toast();
returntrue;
    }
if(downX>rect1_x_0&&downX<rect1_x_1&&downY>rect1_y_0&&downY<rect1_y_1) {//移动了1号Log.i("Scroll2048","111111");
if(Math.abs(upY-downY)>floatY/2&&Math.abs(upX-downX)<floatX/2){
//纵向移动if(upY>downY&&upY>floatY+padding&&upY<floatY*2+padding) {
//第一行往下resert_down_1_1();
            }elseif(upY>downY&&upY>floatY*2+padding&&upY<mHeight-padding){
//第二行往下resert_down_1_2();
            }elseif(upY<downY&&upY>floatY+padding&&upY<floatY*2+padding){
//第三行往上resert_up_1_1();
            }elseif(upY<downY&&upY>padding&&upY<floatY+padding){
//第二行往上resert_up_1_2();
            }
        }elseif(Math.abs(upX-downX)>floatX/2&&Math.abs(upY-downY)<floatY/2){
//横向移动if(upX>downX&&upX>floatX+padding&&upX<floatX*2+padding){
//第一纵行往右滑动resert_left_1_1();
            }elseif(upX>downX&&upX>floatX*2+padding&&upX<mWidth-padding){
//第二纵行往右滑动resert_left_1_2();
            }elseif(upX<downX&&upX<mWidth-padding&&upX>floatX+padding){
//第三纵行往左滑动resert_right_1_1();
            }elseif(upX<downX&&upX<floatX+padding&&upX>padding){
//第二纵行往左滑动resert_right_1_2();
            }
        }
    }


以下是移动后,改变第一格的左上右下,以及空白格子的位置重新确定,你不知道用户会移动到哪一格,所以啊九种情况都需要去考虑。


//第1格第1行向下移动privatevoidresert_down_1_1(){
if(upX>padding&&upX<floatX+padding){//第4格createView_9(padding,floatX+padding,padding,floatY+padding);
view_1_4();
    }elseif(upX>floatX+padding&&upX<floatX*2+padding){//第5格createView_9(padding+floatX,floatX*2+padding,padding,floatY+padding);
view_1_5();
    }elseif(upX>floatX*2+padding&&upX<mWidth-padding){//第6格createView_9(padding+floatX*2,mWidth-padding,padding,floatY+padding);
view_1_6();
    }
}
//第1格第2行向下移动privatevoidresert_down_1_2() {
if(upX>padding&&upX<floatX+padding){//第7格createView_9(padding,floatX+padding,padding+floatY,floatY*2+padding);
view_1_7();
    }elseif(upX>floatX+padding&&upX<floatX*2+padding){//第8格createView_9(padding+floatX,floatX*2+padding,padding+floatY,floatY*2+padding);
view_1_8();
    }elseif(upX>floatX*2+padding&&upX<mWidth-padding){//第9格createView_9(floatX*2+padding,mWidth-padding,padding+floatY,floatY*2+padding);
view_1_9();
    }
}
//第1格第3行向上移动privatevoidresert_up_1_1() {
if(upX>padding&&upX<floatX+padding){//第2格createView_9(padding,floatX+padding,padding+floatY*2,mHeight-padding);
view_1_4();
    }elseif(upX>floatX+padding&&upX<floatX*2+padding){//第3格createView_9(floatX+padding,floatX*2+padding,padding+floatY*2,mHeight-padding);
view_1_5();
    }elseif(upX>floatX*2+padding&&upX<mWidth-padding){//第5格createView_9(floatX*2+padding,mWidth-padding,padding+floatY*2,mHeight-padding);
view_1_6();
    }
}
//第1格第2行向上移动privatevoidresert_up_1_2() {
if(upX>padding&&upX<floatX+padding){//第1格createView_9(padding,floatX+padding,padding+floatY,floatY*2+padding);
view_1_1();
    }elseif(upX>floatX+padding&&upX<floatX*2+padding){//第2格createView_9(floatX+padding,floatX*2+padding,padding+floatY,floatY*2+padding);
view_1_2();
    }elseif(upX>floatX*2+padding&&upX<mWidth-padding){//第3格createView_9(floatX*2+padding,mWidth-padding,padding+floatY,floatY*2+padding);
view_1_3();
    }
}
//第1格第1竖行向右边移动privatevoidresert_left_1_1() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding,floatX+padding,padding,floatY+padding);
view_1_2();
    }elseif(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding,floatX+padding,padding+floatY,floatY*2+padding);
view_1_5();
    }elseif(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding,floatX+padding,floatY*2+padding,mHeight-padding);
view_1_8();
    }
}
//第1格第2竖行向右边移动privatevoidresert_left_1_2() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding+floatX,floatX*2+padding,padding,floatY+padding);
view_1_3();
    }elseif(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding+floatX,floatX*2+padding,padding+floatY,floatY*2+padding);
view_1_6();
    }elseif(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding+floatX,floatX*2+padding,padding+floatY*2,mHeight-padding);
view_1_9();
    }
}
//第1格第2竖行向左边移动privatevoidresert_right_1_2() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding+floatX,floatX*2+padding,padding,floatY+padding);
view_1_1();
    }elseif(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding+floatX,floatX*2+padding,floatY+padding,floatY*2+padding);
view_1_4();
    }elseif(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding+floatX,floatX*2+padding,floatY*2+padding,mHeight-padding);
view_1_7();
    }
}
//第1格第3竖行向左边移动privatevoidresert_right_1_1() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding+floatX*2,mWidth-padding,padding,floatY+padding);
view_1_2();
    }elseif(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding+floatX*2,mWidth-padding,floatY+padding,floatY*2+padding);
view_1_5();
    }elseif(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding+floatX*2,mWidth-padding,floatY*2+padding,mHeight-padding);
view_1_8();
    }
}
//第1格移动到第1格privatevoidview_1_1(){
rect1_x_0=padding;
rect1_x_1=floatX+padding;
rect1_y_0=padding;
rect1_y_1=floatY+padding;
rect1_x_t=(floatX+padding)/2;
rect1_y_t=(floatY+padding)/2;
}
//第1格移动到第2格privatevoidview_1_2(){
rect1_x_0=padding+floatX;
rect1_x_1=floatX*2+padding;
rect1_y_0=padding;
rect1_y_1=floatY+padding;
rect1_x_t=(floatX*2+padding)-floatX_6;
rect1_y_t=(floatY+padding)/2;
}
//第1格移动到第3格privatevoidview_1_3(){
rect1_x_0=padding+floatX*2;
rect1_x_1=mWidth-padding;
rect1_y_0=padding;
rect1_y_1=floatY+padding;
rect1_x_t=(mWidth-padding)-floatX_6;
rect1_y_t=(floatY+padding)/2;
}
//第1格移动到第4格privatevoidview_1_4(){
rect1_x_0=padding;
rect1_x_1=floatX+padding;
rect1_y_0=padding+floatY;
rect1_y_1=floatY*2+padding;
rect1_x_t=(floatX+padding)/2;
rect1_y_t=(floatY*2+padding)-floatY_6;
}
//第1格移动到第5格privatevoidview_1_5(){
rect1_x_0=padding+floatX;
rect1_x_1=floatX*2+padding;
rect1_y_0=padding+floatY;
rect1_y_1=floatY*2+padding;
rect1_x_t=(floatX*2+padding)-floatX_6;
rect1_y_t=(floatY*2+padding)-floatY_6;
}
//第1格移动到第6格privatevoidview_1_6(){
rect1_x_0=padding+floatX*2;
rect1_x_1=mWidth-padding;
rect1_y_0=padding+floatY;
rect1_y_1=floatY*2+padding;
rect1_x_t=(mWidth-padding)-floatX_6;
rect1_y_t=(floatY*2+padding)-floatY_6;
}
//第1格移动到第7格privatevoidview_1_7(){
rect1_x_0=padding;
rect1_x_1=floatX+padding;
rect1_y_0=padding+floatY*2;
rect1_y_1=mHeight-padding;
rect1_x_t=(floatX+padding)/2;
rect1_y_t=(mHeight-padding)-floatY_6;
}
//第1格移动到第8格privatevoidview_1_8(){
rect1_x_0=padding+floatX;
rect1_x_1=floatX*2+padding;
rect1_y_0=padding+floatY*2;
rect1_y_1=mHeight-padding;
rect1_x_t=(floatX*2+padding)-floatX_6;
rect1_y_t=(mHeight-padding)-floatY_6;
}
//第1格移动到第9格privatevoidview_1_9(){
rect1_x_0=padding+floatX*2;
rect1_x_1=mWidth-padding;
rect1_y_0=padding+floatY*2;
rect1_y_1=mHeight-padding;
rect1_x_t=(mWidth-padding)-floatX_6;
rect1_y_t=(mHeight-padding)-floatY_6;
}


如何判断移动成功了:


在上面的图中,我也有说过,就是比较移动后的格子的左上右下和初始化的格子的左上右下,比如,我们随机给的顺为:"8","6","3","1","5","7","2","4",那么我们比较如下,成功后进行回调:


/*** 获取初始化格子的左上右下* */privateintnumber_1_left=padding,number_1_right=floatX+padding,
number_1_top=padding,number_1_bottom=floatY+padding;
privateintnumber_2_left=padding+floatX,number_2_right=floatX*2+padding,
number_2_top=padding,number_2_bottom=floatY+padding;
privateintnumber_3_left=padding+floatX*2,number_3_right=mWidth-padding,
number_3_top=padding,number_3_bottom=floatY+padding;
privateintnumber_4_left=padding,number_4_right=floatX+padding,
number_4_top=floatY+padding,number_4_bottom=floatY*2+padding;
privateintnumber_5_left=padding+floatX,number_5_right=floatX*2+padding,
number_5_top=floatY+padding,number_5_bottom=floatY*2+padding;
privateintnumber_6_left=padding+floatX*2,number_6_right=mWidth-padding,
number_6_top=floatY+padding,number_6_bottom=floatY*2+padding;
privateintnumber_7_left=padding,number_7_right=floatX+padding,
number_7_top=floatY*2+padding,number_7_bottom=mHeight-padding;
privateintnumber_8_left=padding+floatX,number_8_right=floatX*2+padding,
number_8_top=floatY*2+padding,number_8_bottom=mHeight-padding;
if(rect1.top==number_8_top&&rect1.bottom==number_8_bottom&&rect1.left==number_8_left&&rect1.right==number_8_right&&rect2.top==number_6_top&&rect2.bottom==number_6_bottom&&rect2.left==number_6_left&&rect2.right==number_6_right&&rect3.top==number_3_top&&rect3.bottom==number_3_bottom&&rect3.left==number_3_left&&rect3.right==number_3_right&&rect4.top==number_1_top&&rect4.bottom==number_1_bottom&&rect4.left==number_1_left&&rect4.right==number_1_right&&rect5.top==number_5_top&&rect5.bottom==number_5_bottom&&rect5.left==number_5_left&&rect5.right==number_5_right&&rect6.top==number_7_top&&rect6.bottom==number_7_bottom&&rect6.left==number_7_left&&rect6.right==number_7_right&&rect7.top==number_2_top&&rect7.bottom==number_2_bottom&&rect7.left==number_2_left&&rect7.right==number_2_right&&rect8.top==number_4_top&&rect8.bottom==number_4_bottom&&rect8.left==number_4_left&&rect8.right==number_4_right){
listener.success(numberType);
}


其实就是这样一一去比较,我的思路是这样,可能还是有更加简便的思路,我暂时还没有想起来,具体实现就是这样,代码比较繁琐,有更好的实现方式,可以留言探讨,不吝赐教。


开源地址:https://github.com/AbnerMing888/NumberHrd

相关文章
|
数据库连接 Android开发
安卓android期末项目之纸牌游戏之三
安卓android期末项目之纸牌游戏之三
86 0
|
存储 Android开发 数据库管理
Android安卓项目猜纸牌游戏之二 实体类
Android安卓项目猜纸牌游戏之二 实体类
43 0
|
Android开发
flutter中实现仿Android端的onResume和onPause方法
flutter中实现仿Android端的onResume和onPause方法
|
6月前
|
算法 Java 定位技术
分享104个益智休闲安卓游戏源码,总有一款适合你
分享104个益智休闲安卓游戏源码,总有一款适合你
392 1
|
6月前
|
监控 Devops Java
大型IM工程重构实践:企业微信Android端的重构之路
本文将探讨我们在大型IM工程实践中采用的一些行之有效的重构方法和实例,以及如何让一个大型软件系统持续保持活力。
156 0
|
6月前
|
编解码 移动开发 人工智能
android游戏源码
android游戏源码
188 0
|
Android开发 Windows
Mac 好用的 Android 模拟器整理(玩游戏、装应用、支持咸鱼、拼多多...)
Mac 好用的 Android 模拟器整理(玩游戏、装应用、支持咸鱼、拼多多...)
17450 47
|
11月前
|
机器学习/深度学习 人工智能 安全
2023 Google 开发者大会:无障碍游戏体验升级、安卓开发人员生产力爆棚
2023 Google 开发者大会:无障碍游戏体验升级、安卓开发人员生产力爆棚
|
XML Android开发 数据格式
Android项目猜纸牌游戏之一 界面设计和资源文件的设计
Android项目猜纸牌游戏之一 界面设计和资源文件的设计
78 0
|
开发工具 Android开发 Python
【Android 逆向】逆向修改游戏应用 ( APK 解析工具 | 解包 -> 分析 -> 重打包 -> 签名 流程 )
【Android 逆向】逆向修改游戏应用 ( APK 解析工具 | 解包 -> 分析 -> 重打包 -> 签名 流程 )
751 0
【Android 逆向】逆向修改游戏应用 ( APK 解析工具 | 解包 -> 分析 -> 重打包 -> 签名 流程 )