• Android群英传-拼图游戏puzzle-6点吐槽


    一、缘由
      经常写文章,混了一些C币。最近在深入学习Android应用开发,就从商城里买了一本《Android群英传》。
    这本书的内容,不是纯粹的入门那种,分几个章节,重点讲解Activity、动画等。
    最后一章是2个小游戏的实例,其中1个是拼图游戏。
      认真研究了下作者的代码,有不敢苟同的地方,特意吐槽几句。


    二、游戏相关资料
      游戏名称:拼图、移动拼图、滑动拼图、Pullze
      在搜索过程中,搜到了“华容道”和“数字推盘游戏”。
      
      数字推盘游戏(n-puzzle)是一种智力游戏,常见的类型有十五数字推盘游戏和八数字推盘游戏等。也有以图画代替数字的推盘游戏。可能Noyes Palmer Chapman在1874年发明十五数字推盘,但Sam Loyd则在1891年也宣称为其发明。
    八数字推盘(又名重排九宫)则可能由Henry Ernest Dudeney发明,并且Martin Gardner在科学人寻求更快的解答。也有人认为重排九宫是传统中国游戏,来自洛书,并且为华容道的祖先。


      游戏规则:游戏者要移动板上的方块,让所有的方块顺着数字的次序排列。
      
      在看了“数字推盘游戏”的介绍之后,我发现“拼图游戏”的本质就是“数字推盘游戏”。

      我们设计的图片推盘游戏,背后的表示就是“数字”,“按顺序排放”。

      

      
    三、6点吐槽
    1.游戏的核心设计,非常坑。

    问了下作者,他是根据自己的理解,设计的这个游戏。
    我严重怀疑,他没有玩过“实物版”的“移动拼图游戏”,反正我是玩过了。
    因此,我特意严重吐槽下他的游戏设计。


    游戏设计不给力,导致技术设计和实现,很让人着急啊。
    没有太大问题的话,我打算改造下,实现标准的“移动拼图游戏”,然后分享出来。


     他的游戏界面

        N*N个格子,其中1个是“空”的,实际上只是“图片”没有展示,并不是严格意义上的“空格子”。


     
     实物版的游戏界面
        N*N+1个格子,有个格子专门是“空”的,用来交换,腾位置的。


    2.变量命名方式非主流。
      private View mPopupView;
      竟然用类似“匈牙利命名法”这种。
      Java和Android开发,不都是“驼峰式命名”么?
      popupView就可以了。
      
      另外,popupView也符合“约定优于配置”,Android自动提示也更舒服。
      
    3.函数命名不准确。
          public static DisplayMetrics getScreenSize(Context context) {
            DisplayMetrics metrics = new DisplayMetrics();
            WindowManager windowManager = (WindowManager) context.getSystemService(
                    Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();
            display.getMetrics(metrics);
            return metrics;
        }


      返回的是DisplayMetrics,它包含的可不只是“屏幕的大小”。
      因此,要么自定义1个实体类,包装屏幕大小。
      要么,就用getDisplayMetrics更好。
      
      
      相比之下,类似代码的另外一个方法“获得设备密度”就更准确一点了,返回的是float,而不是DisplayMetrics。
       
      /**
         * 获取屏幕density(密度)
         *
         * @param context context
         * @return density 屏幕density
         */
        public static float getDeviceDensity(Context context) {
            DisplayMetrics metrics = new DisplayMetrics();
            WindowManager windowManager = (WindowManager) context.getSystemService(
                    Context.WINDOW_SERVICE);
            windowManager.getDefaultDisplay().getMetrics(metrics);
            return metrics.density;
        }



    这个就更准确一下。


    ImageUtil有个方法
    public void createInitBitmaps(int type, Bitmap photoSelected,Context context);
     
    从函数的名字,我们很可能想到,返回的是1个对象,但结果是void。直接取名initBitmaps更好,初始化对象。
    另外,ImageUtil是工具类,而“Bitmap photoSelected”这种命名方式,体现了业务场景,但实际上纯粹的工具方法,连“业务工具方法”都不算,
    为啥要这么命名呢?
    函数的命名和作用,和业务无关,就更容易通用,在其它项目中使用,才能起到“工具函数”的作用。
     
    4.代码重复
      还是上面的代码,getDeviceDensity的代码前3行和getScreenSize函数的前4行是一样的。
      而且,从“windowManager.getDefaultDisplay().getMetrics(metrics);”这里可以看出,第2个函数还不是“复制-粘贴”修改的。
      
      这里,我有个疑问,获得DisplayMetrics对象,为什么是传入一个新的对象,而不是getMetrics在内部new一个新对象,然后返回呢?
      
      重构之后的代码:
     
       /**
         * 获取屏幕相关参数
         *
         * @param context context
         * @return DisplayMetrics 屏幕宽高
         */
        public static DisplayMetrics getDisplayMetrics(Context context) {
            DisplayMetrics metrics = new DisplayMetrics();
            WindowManager windowManager = (WindowManager) context.getSystemService(
                    Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();
            display.getMetrics(metrics);
            return metrics;
        }
    
    
        /**
         * 获取屏幕density(密度)
         *
         * @param context context
         * @return density 屏幕density
         */
        public static float getDeviceDensity(Context context) {
            DisplayMetrics metrics =getDisplayMetrics(context);
            return metrics.density;
        }


      
    5.变量作用域太大。
    public class ImageUtil {
        public GridItem gridItem;
    }
    定义了1个public字段,实际上这个字段只是“某个函数”的一个局部变量,也没有被其它类访问。
    因此,不应该定义单独的字段,也不应该是public的。


    另外,ImageUtil是个工具类,既然没有必要定义实例字段,直接把方法定义成static更好。
    而不是 new ImageUtil().method();


    6.相同的字符串,没有提取成常量。
    	// 选择默认图片
    	Intent intent = new Intent(
    			MainActivity.this,
    			PuzzleMain.class);
    	intent.putExtra("picSelectedID", mResPicId[position]);
    	intent.putExtra("mType", mType);
    	startActivity(intent);


    至少有2个地方,使用了"picSelectedID"。用常量表示,容易维护。


    更多地方,就不吐槽了~


    四、代码
      a.我自己初步重构的-
      https://git.oschina.net/fansunion/puzzle
      
      b.Android群英传-原版拼图游戏  
      https://github.com/xuyisheng/AndroidHeroes/tree/master/13.实例提高/XPuzzle
      
      c.更改游戏设计,增加1个格子,大幅度改版的,暂时还在研究中~后续公开~
      
    五、写在最后
      不少人读过博主的“拼图游戏系列文章”,也有部分人读过博主的“Android群英传”这本书。
      虽说深入学习Android不久,作为一名有多年编程经验的人来说,我还是吐槽一些比较好。
      不好就是不好,理由都摆在那里。
      Android群英传的作者,还需要加点油~
      相关人士,看着办~(*^__^*) 
      
      参考资料
      
      数字推盘游戏
      http://baike.baidu.com/link?url=qO5ShCCBQavlEn35RepADpAAl_OZ8CuNjYul6QK_v23hB2XtnFXfSoaHvO043ruLY8hzWedi8lLiH1EaOA_P0K
      
      书籍《Android群英传》,作者博客:http://blog.csdn.net/eclipsexys
      
      作者的拼图专栏:http://blog.csdn.net/column/details/android-puzzle.html
  • 相关阅读:
    动态设置字体大小需要注意的点
    getDimension与getDimensionPixelOffset与getDimensionPixelSize的区别
    统计图钻取的明细报表在非模态窗口中显示
    局部区块多个报表 TAB 页切换及局部区块的参数查询
    分栏报表制作攻略
    多值关联过滤
    鼠标悬停出现提示信息怎么做
    复杂报表设计之动态报表
    Logo(图片)作为报表水印的解决方法
    分组填报表的制作
  • 原文地址:https://www.cnblogs.com/qitian1/p/6462541.html
Copyright © 2020-2023  润新知