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

项目地址:https://github.com/ming723/NumberHrd


游戏效果:



前提摘要:


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


灵感源于:


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


 代码存在问题:


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


 具体实现:


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




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




/**
* 记录每个格子移动的左上右下
* rect0:空白格子,rect1:第一个格子 ……
* x_0:左
* x_1:右
* y_0:上
* y_1:下
* x_t:绘制文字的x坐标
* y_t:绘制文字的y坐标
* */
private int rect0_x_0,rect0_x_1,rect0_y_0,rect0_y_1;//空隙位置
private int rect1_x_0,rect1_x_1,rect1_y_0,rect1_y_1,rect1_x_t,rect1_y_t;
private int rect2_x_0,rect2_x_1,rect2_y_0,rect2_y_1,rect2_x_t,rect2_y_t;
private int rect3_x_0,rect3_x_1,rect3_y_0,rect3_y_1,rect3_x_t,rect3_y_t;
private int rect4_x_0,rect4_x_1,rect4_y_0,rect4_y_1,rect4_x_t,rect4_y_t;
private int rect5_x_0,rect5_x_1,rect5_y_0,rect5_y_1,rect5_x_t,rect5_y_t;
private int rect6_x_0,rect6_x_1,rect6_y_0,rect6_y_1,rect6_x_t,rect6_y_t;
private int rect7_x_0,rect7_x_1,rect7_y_0,rect7_y_1,rect7_x_t,rect7_y_t;
private int rect8_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,是边框距离左上右下的距离



/**
* 第一个格子的位置
* */
private void createView_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;
}
/**
* 第二个格子的位置
* */
private void createView_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;
}
/**
* 第三个格子的位置
* */
private void createView_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;
}
/**
* 第四个格子的位置
* */
private void createView_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;
}
/**
* 第五个格子的位置
* */
private void createView_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;
}
/**
* 第六个格子的位置
* */
private void createView_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;
}
/**
* 第七个格子的位置
* */
private void createView_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;
}
/**
* 第八个格子的位置
* */
private void createView_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;
}

/**
* 每次移动格子,记录空白格子的位置
* */
private void createView_9(int num1,int num2,int num3,int num4) {
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进行判断,这里我只列出了第一个格,其它格子判断和第一格一样,都是一些重复性的代码。


case MotionEvent.ACTION_UP:
upX= (int) event.getX();
   upY= (int) event.getY();
   //如果不是大于空白格子,那么就不移动
   boolean isScroll=upX>rect0_x_0&&upX<rect0_x_1&&upY>rect0_y_0&&upY<rect0_y_1;
   if(!isScroll){
return true;
   }
//如果移动的距离大于一格半,那么就不移动,必须在一格半之内
   if(Math.abs(upX-downX)>floatX+floatX/2||Math.abs(upY-downY)>floatY/2+floatY){
return true;
   }
if(!MainActivity.isStart){
listener.toast();
       return true;
   }

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();
           }else if(upY>downY&&upY>floatY*2+padding&&upY<mHeight-padding){
//第二行往下
               resert_down_1_2();
           }else if(upY<downY&&upY>floatY+padding&&upY<floatY*2+padding){
//第三行往上
               resert_up_1_1();
           }else if(upY<downY&&upY>padding&&upY<floatY+padding){
//第二行往上
               resert_up_1_2();
           }
}else if(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();
           }else if(upX>downX&&upX>floatX*2+padding&&upX<mWidth-padding){
//第二纵行往右滑动
               resert_left_1_2();
           }else if(upX<downX&&upX<mWidth-padding&&upX>floatX+padding){
//第三纵行往左滑动
               resert_right_1_1();
           }else if(upX<downX&&upX<floatX+padding&&upX>padding){
//第二纵行往左滑动
               resert_right_1_2();
           }
}

}


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



//第1格第1行向下移动
private void resert_down_1_1(){
if(upX>padding&&upX<floatX+padding){//第4格
       createView_9(padding,floatX+padding,padding,floatY+padding);
       view_1_4();
   }else if(upX>floatX+padding&&upX<floatX*2+padding){//第5格
       createView_9(padding+floatX,floatX*2+padding,padding,floatY+padding);
       view_1_5();
   }else if(upX>floatX*2+padding&&upX<mWidth-padding){//第6格
       createView_9(padding+floatX*2,mWidth-padding,padding,floatY+padding);
       view_1_6();
   }
}


//第1格第2行向下移动
private void resert_down_1_2() {
if(upX>padding&&upX<floatX+padding){//第7格
       createView_9(padding,floatX+padding,padding+floatY,floatY*2+padding);
       view_1_7();
   }else if(upX>floatX+padding&&upX<floatX*2+padding){//第8格
       createView_9(padding+floatX,floatX*2+padding,padding+floatY,floatY*2+padding);
       view_1_8();
   }else if(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行向上移动
private void resert_up_1_1() {
if(upX>padding&&upX<floatX+padding){//第2格
       createView_9(padding,floatX+padding,padding+floatY*2,mHeight-padding);
       view_1_4();
   }else if(upX>floatX+padding&&upX<floatX*2+padding){//第3格
       createView_9(floatX+padding,floatX*2+padding,padding+floatY*2,mHeight-padding);
       view_1_5();
   }else if(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行向上移动
private void resert_up_1_2() {
if(upX>padding&&upX<floatX+padding){//第1格
       createView_9(padding,floatX+padding,padding+floatY,floatY*2+padding);
       view_1_1();
   }else if(upX>floatX+padding&&upX<floatX*2+padding){//第2格
       createView_9(floatX+padding,floatX*2+padding,padding+floatY,floatY*2+padding);
       view_1_2();
   }else if(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竖行向右边移动
private void resert_left_1_1() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding,floatX+padding,padding,floatY+padding);
       view_1_2();
   }else if(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding,floatX+padding,padding+floatY,floatY*2+padding);
       view_1_5();
   }else if(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding,floatX+padding,floatY*2+padding,mHeight-padding);
       view_1_8();
   }
}
//第1格第2竖行向右边移动
private void resert_left_1_2() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding+floatX,floatX*2+padding,padding,floatY+padding);
       view_1_3();
   }else if(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding+floatX,floatX*2+padding,padding+floatY,floatY*2+padding);
       view_1_6();
   }else if(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding+floatX,floatX*2+padding,padding+floatY*2,mHeight-padding);
       view_1_9();
   }
}
//第1格第2竖行向左边移动
private void resert_right_1_2() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding+floatX,floatX*2+padding,padding,floatY+padding);
       view_1_1();
   }else if(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding+floatX,floatX*2+padding,floatY+padding,floatY*2+padding);
       view_1_4();
   }else if(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding+floatX,floatX*2+padding,floatY*2+padding,mHeight-padding);
       view_1_7();
   }
}
//第1格第3竖行向左边移动
private void resert_right_1_1() {
if(upY>padding&&upY<floatY+padding){
createView_9(padding+floatX*2,mWidth-padding,padding,floatY+padding);
       view_1_2();
   }else if(upY>floatY+padding&&upY<floatY*2+padding){
createView_9(padding+floatX*2,mWidth-padding,floatY+padding,floatY*2+padding);
       view_1_5();
   }else if(upY>floatY*2+padding&&upY<mHeight-padding){
createView_9(padding+floatX*2,mWidth-padding,floatY*2+padding,mHeight-padding);
       view_1_8();
   }

}




//第1格移动到第1格
private void view_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格
private void view_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格
private void view_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格
private void view_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格
private void view_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格
private void view_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格
private void view_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格
private void view_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格
private void view_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",那么我们比较如下,成功后进行回调:


/**
* 获取初始化格子的左上右下
* */
private  int number_1_left=padding,number_1_right=floatX+padding,
       number_1_top=padding,number_1_bottom=floatY+padding;
private  int number_2_left=padding+floatX,number_2_right=floatX*2+padding,
       number_2_top=padding,number_2_bottom=floatY+padding;
private  int number_3_left=padding+floatX*2,number_3_right=mWidth-padding,
       number_3_top=padding,number_3_bottom=floatY+padding;
private  int number_4_left=padding,number_4_right=floatX+padding,
       number_4_top=floatY+padding,number_4_bottom=floatY*2+padding;
private  int number_5_left=padding+floatX,number_5_right=floatX*2+padding,
       number_5_top=floatY+padding,number_5_bottom=floatY*2+padding;
private  int number_6_left=padding+floatX*2,number_6_right=mWidth-padding,
       number_6_top=floatY+padding,number_6_bottom=floatY*2+padding;
private  int number_7_left=padding,number_7_right=floatX+padding,
       number_7_top=floatY*2+padding,number_7_bottom=mHeight-padding;
private  int number_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);
}


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

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员一鸣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值