zoukankan      html  css  js  c++  java
  • Android群英传-拼图游戏puzzle-代码设计和实现

      上个周末,3个小时总体上读完了《Android群英传》,本周主要在研究代码层次的设计和实现。
      编译安装在手机上,玩了几把,结合代码,一周时间才掌握了整体的思路。
      大部分时间,其实花在了“重构”上。
      重构的过程,就是学习和思考的过程。
      
      本文,算是一篇学习总结,总体介绍下这款小游戏的实现思路。
      后面抽空,再改造下这个游戏不合理的设计方式,即格子是N*N+1,而不是N*N个。
      
      写到快吐了:在写过的几百篇文章里,其中有很多案例了,写得次数越多,越发现很多流程和思路是一致的。
      因此,很有必要把一些通用的知识总结下。写清楚了,再介绍就清楚多了。
      文章的名字初步定为“可视化界面GUI应用开发总结:Android、iOS、Web、Swing、Windows开发等”,预计2015年12月7日之前发表。
      
      代码讲解
      
      1.包结构

        cn.fansunion.puzzle
      --activity
        GlobalConst.java 几个全局常量
    MainActivity.java 游戏的入口Activity
    PuzzleActivity.java 拼图游戏过程的Activity
      --adapter
        MainGridViewAdapter.java 游戏入口界面的Gridview的适配器,可以理解成GridView的数据提供者
    PuzzleGridViewAdapter.java拼图界面的GridView的适配器
      --bean
        GridItem.java 表格中的1个元素
      --util
         GameUtil.java 封装了游戏规则
     ImageUtil.java 图片处理工具
     ScreenUtil.java 屏幕工具
     
      2.基础类讲解
        GameUtil.java

    isMoveable:判断图片是否可以移动,或者称为“能否和空格进行交换”,根据GridView中的position,判断是否和空格是“相邻”的就可以了。
    swapItems:交换2个GridItem的位置,在判断可以移动之后
    isSuccess:判断当前拼图是否完成
    getPuzzleGenerator:生成随机的Item,就是把N*N个数字的位置,打乱
    canSolve:判断随机生成的Item是否有解,即能否通过移动交换图片,还原“原图”。
    (这个地方的设计,也比较坑。我目前认为,可以换种方式生成初始拼图,即随机交换空格和周边的图片N次。因为“交换是可逆的”,所以总是有解)

    ImageUtil.java:把1个图片,切成N*N个;放大图片。
    ScreenUtil.java:获得屏幕的大小、密度。

    GridItem.java:游戏拼图的核心Model,表格中的1项,id、图片资源id、图片资源,方便绘图和游戏规则实现。
    MainGridViewAdapter.java和PuzzleGridViewAdapter.java:继承android.widget.BaseAdapter,重载若干方法。

    GlobalConst.java:一些常量,太简单了吧。

      3.游戏的流程
        游戏入口MainActivity.java

    核心流程:
     a.设置主体界面
       setContentView(R.layout.xpuzzle_main);
     b.初始化其它界面,按钮等
            initViews();
     c.数据适配器
            gridView.setAdapter(new MainGridViewAdapter(
                    MainActivity.this, bitmapList));
     d.按钮、界面等绑定事件
       gridView.setOnItemClickListener
          e.事件响应
     
        重要事件
        a.选择游戏难度,保存到Type字段中。给用户一个“弹出对话框”选择。
           
     selectedTypeTextView.setOnClickListener(
                    new OnClickListener() {
    
    
                        @Override
                        public void onClick(View v) {
                            // 弹出popup window
                            popupShow(v);
                        }
                    });
        }


        b.游戏自带若干图片和使用系统图片。
     用表格展示的,Item点击监听,最后1个图片,表示选择“本地图库或者相机拍摄”,其它图片就直接选择了。
           
     gridView.setOnItemClickListener(new OnItemClickListener() {
    
    
                @Override
                public void onItemClick(AdapterView<?> arg0, View view,
                                        int position, long arg3) {
                    if (position == photoResourceIdArray.length - 1) {
                        // 选择本地图库 相机
                        showDialogCustom();
                    } else {
                        // 选择默认图片
                        Intent intent = new Intent(
                                MainActivity.this,
                                PuzzleMain.class);
                        intent.putExtra(GlobalConst.SELECT_PHOTO_ID, photoResourceIdArray[position]);
                        intent.putExtra(GlobalConst.TYPE, type);
                        startActivity(intent);
                    }
                }
            });


    本地图库和相机拍照,是2套类似的逻辑。用户选择之后,调用图库相机回调方法,保存用户选择的图片。
           然后就进入到“拼图游戏主界面”了。
      
    拼图游戏主界面PuzzleActivity.java
    核心流程:
    a.设置主体布局
      setContentView(R.layout.xpuzzle_puzzle_detail_main);
    b.获得用户选择的图片,并切图
      getIntent().getExtras().getInt(GlobalConst.SELECT_PHOTO_ID);
    c. 初始化其它Views
            initViews();
    d. 调用GameUtil生成游戏初始数据,并启动定时器。(写到这里突然发现,又不合理了,定时器,应该在程序全部初始化完成之后,再开启。)
      generateGame();
    e.事件绑定。
       // 返回按钮点击事件
            backButton.setOnClickListener(this);
            // 显示原图按钮点击事件
            imageButton.setOnClickListener(this);
            // 重置按钮点击事件
            restartButton.setOnClickListener(this);

      // GridView点击事件(最重要的其实是这个),图片可否移动,在能够移动的情况下,需要“交换图片、”“更新绘图”、“更新步数”。
      //在成功的情况下,后续处理(停止计时等)
         
      gridView.setOnItemClickListener(new OnItemClickListener() {
    
    
                @Override
                public void onItemClick(AdapterView<?> arg0, View view,
                                        int position, long arg3) {
                    // 判断是否可移动
                    if (GameUtil.isMoveable(position)) {
                        // 交换点击Item与空格的位置
                        GameUtil.swapItems(
                                GameUtil.gridItemList.get(position),
                                GameUtil.blankGridItem);
                        // 重新获取图片
                        recreateData();
                        // 通知GridView更改UI
                        puzzleGridViewAdapter.notifyDataSetChanged();
                        // 更新步数
                        stepCount++;
                        stepCountTextView.setText("" + stepCount);
                        // 判断是否成功
                        if (GameUtil.isSuccess()) {
                            // 将最后一张图显示完整
                            recreateData();
                            bitmapItemList.remove(TYPE * TYPE - 1);
                            bitmapItemList.add(lastBitmap);
                            // 通知GridView更改UI
                            puzzleGridViewAdapter.notifyDataSetChanged();
                            Toast.makeText(PuzzleMain.this, "拼图成功!",
                                    Toast.LENGTH_LONG).show();
                            gridView.setEnabled(false);
                            timer.cancel();
                            timerTask.cancel();
                        }
                    }
                }
            });


      4.资源
        布局、菜单、字符串,结合Java代码,很容易读懂。


      代码地址:
      https://git.oschina.net/fansunion/puzzle
      
      个人看法
      目前的技术,入门,达到中级水平,能够干活和赚钱,还是比较容易的。
      达到一定水平之后,想要继续高深,就要看个人对技术的理解了。
      至于重构、代码规范、游戏设计,每个人都有自己的理解。
      结合实际情况,再做具体考量。
  • 相关阅读:
    关于同步解释
    dll 问题 (转)
    SQL SERVER 触发器中如何调用外部程序
    SQL SERVER所有表、字段名、主键、类型、长度、小数位数等信息
    variant 和 Stream 的互換
    Variant的相关函数
    使用 wxPython 创建“目录树”(5)
    wxPython 绘图演示——模拟雷达信号图(2)
    wxpython 实现简易画板(1)
    使用 wx.tools.img2py (4)
  • 原文地址:https://www.cnblogs.com/qitian1/p/6462540.html
Copyright © 2011-2022 走看看