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
  
  个人看法
  目前的技术,入门,达到中级水平,能够干活和赚钱,还是比较容易的。
  达到一定水平之后,想要继续高深,就要看个人对技术的理解了。
  至于重构、代码规范、游戏设计,每个人都有自己的理解。
  结合实际情况,再做具体考量。

时间: 2024-10-05 10:09:43

Android群英传-拼图游戏puzzle-代码设计和实现的相关文章

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

一.缘由  经常写文章,混了一些C币.最近在深入学习Android应用开发,就从商城里买了一本<Android群英传>.这本书的内容,不是纯粹的入门那种,分几个章节,重点讲解Activity.动画等.最后一章是2个小游戏的实例,其中1个是拼图游戏.  认真研究了下作者的代码,有不敢苟同的地方,特意吐槽几句. 二.游戏相关资料  游戏名称:拼图.移动拼图.滑动拼图.Pullze  在搜索过程中,搜到了"华容道"和"数字推盘游戏".    数字推盘游戏(n-

Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验

Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 这一章很多,但是很有趣,也是这书的最后一章知识点了,我现在还在考虑要不要写这个拼图和2048的案例,在此之前,我们先来玩玩Android5.X的新特性吧!

Android群英传笔记——摘要,概述,新的出发点,温故而知新,能够为师矣!

Android群英传笔记--摘要.概述,新的出发点,温故而知新.能够为师矣! 当工作的越久,就越感到力不从心了,基础和理解才是最重要的,所以买了两本书,医生的<Android群英传>和主席的<Android开发艺术探索>.主要是再全面点的把自己所学的知识消化,这样也就不枉自己天天熬夜学习了,如今群英传快看完了.准备又一次再看一遍,同一时候把笔记以博客的形式记录下来,这样或许更加的深刻,然后再消磨一下主席的那本书,这本书有视频解说,更加好,所以估计以后应该非常少再写其它的博客,只是工

对不起!我来晚了!——《Android群英传》出版祭

对不起!我来晚了!--<Android群英传>出版祭 历时将近一年,我的第一本书终于就要出版了,虽然经历种种曲折,历经磨难,最终还是赶在八月份的尾巴上,修成正果. 首先,要向大家道歉,本来预计是在6月份上市的书,一拖再拖,直到现在才得以出版,让不少朋友一等再等,这里,向这些朋友的耐心,狠狠的点个赞. 写书之前 其实,当官杨主编第一次找我写书的时候,其实我是,是想拒绝的,我跟女朋友讲,我拒绝,因为,其实我还只是一个非常普通的开发者--但女朋友对我讲,写书,不一定是要有多么响的名声,用心去写,把自

Android群英传笔记——第四章:ListView使用技巧

Android群英传笔记--第四章:ListView使用技巧 近期也是比較迷茫.可是有一点点还是要坚持的,就是学习了.近期离职了,今天也是继续温习第四章ListView,也拖了事实上也挺久的了,listview可谓是老牌大将了,非常多的应用场景都要使用它,他也是我们用得最多的控件之中的一个了,尽管如今出来了一个RecyclerView,可是ListView的地位一时半会儿还是撼动不了的.这就促使我们更加应该去把他掌握了 一.Listview经常使用优化技巧 我们一步步来把ListView学习好

事件拦截机制分析(Android群英传)

内容是博主照着书敲出来的,博主码字挺辛苦的,转载请注明出处,后序内容陆续会码出. 当Android系统捕获到用户的各种输入事件后,如何准确地传递给真正需要这个事件的控件呢?Android给我们提供了一整套完善的事件传递.处理机制,来帮助开发者完成准确的事件分配与处理. 要了解触摸事件的拦截机制,首先要了解什么是触摸事件?顾名思义,触摸事件就是捕获触摸屏幕后产生的事件.当点击一个按钮时,通常就会产生两个或者三个事件--按钮按下,这是事件一:如果不小心滑动一点,这就是事件二:当手抬起,这是事件三.A

Android群英传笔记——第八章:Activity与Activity调用栈分析

Android群英传笔记--第八章:Activity与Activity调用栈分析 开篇,我们陈述一下Activity,Activity是整个应用用户交互的核心组件,了解Activity的工作模式,生命周期和管理方式,是了解Android的基础,本节主讲 Activity的生命周期与工作模式 Activity调用栈管理 一.Activity Activity作为四大组建出现平率最高的组件,我们在哪里都能看到他,就让我们一起先来了解一下他的生命周期 1.起源 Activity是用户交互的第一接口,他

《Android群英传》勘误

<Android群英传>勘误 我的新书<Android群英传>刚刚上市不久,希望大家多多支持.本篇为本市的勘误,由于时间仓促,书中难免会存在一些错误,特在此列出这些勘误,也希望广大读者发现错误后,及时在本文评论中贴出来,我将收录到下次的修订中,感谢大家的支持和包容~~ 前言-资源与勘误 --都会上传到Github代码分享平台供大家 frok,下载-- -----> --都会上传到Github代码分享平台供大家 fork,下载-- 本书特色 本书各个章节之间并没有严格的 递近

Android群英传笔记系列一view的介绍

学习完第一行代码后,继续学习Android群英传,希望能坚持下去,好好学习完这本书,并及时做好相关笔记,巩固相关知识: 一. View的介绍: 1`.我们先来看下view树结构: 2.树结构内容: a.viewparent是整棵树的核心,它统一调度和分配所有的交互管理事件. b.控件分为viewgroup和view两种控件,viewgroup作为父控件可以包含多个vie       w控件. c.我们知道在使用控件前都要通过findViewById的方法来实例化控件,那么在树结构中,实际上表现为