本篇的内容是,在前一篇的基础上添�了撤销的功能。撤销事实上就是将当前的用户界面恢复到这次滑动值前的样子。我实现撤销的主要原理是,将每次滑动后界面上的格子和相应的数字记录下来,当然还有分数,把这些数据写入一个栈中,然后点击撤销操作的时候,将栈顶pop掉,读取下一个栈中的对象,并依据对象中存储的数据又一次绘制界面。

以下是我用于存储每次界面情况的类,在这个类中保存了界面中基本的三个数据,空白格、数字格和当前的分数。

package com.example.t2048;

import java.util.ArrayList;
import java.util.List; public class History { //相应主activity中的空格列表
private List<Integer> spaceList;
//相应主activity中的数字列表
private NumberList numberList;
//相应主activity中的当前分数
private int score = 0; /**
* 构造方法
* @param sl 空格列表
* @param nl 数字列表
* @param s 当前分数
*/
History(List<Integer> sl, NumberList nl, int s) {
spaceList = new ArrayList<Integer>(sl);
numberList = new NumberList(new ArrayList<Integer>(nl.getStuffList()), new ArrayList<Integer>(nl.getNumberList()));
this.score = s;
} public List<Integer> getSpaceList(){
return this.spaceList;
} public NumberList getNumberList() {
return this.numberList;
} public int getScore() {
return this.score;
} /**
* 打印日志
*/
public void printLog(){
System.out.println(this.spaceList.toString());
this.numberList.printLog();
System.out.println("score: "+this.score);
}
}

然后,我在主Activity中声明了一个stack用于保存每次的History

	//保存历史记录,用于撤销操作
Stack<History> historyStack = new Stack<History>();

在每次完毕初始化以及每次有效的滑动之后,将当前界面的History压入stack中

	History history = new History(spaceList, numberList, score);
historyStack.push(history);

运行撤销的操作,我写了例如以下方法,代码还是非常easy的:

	/**
* 撤销操作,获取操作记录栈中最后的记录,并重绘界面
*/
public void goBack(){
//至少应有一次有效滑动后才干撤销
if(historyStack.size()>=2){
//将当前的界面记录在栈中弹出
historyStack.pop();
//取栈中第二个对象即为本次操作之前的界面的记录
History history = historyStack.peek(); numberList = history.getNumberList();
spaceList = history.getSpaceList();
score = history.getScore(); //调取方法,重绘界面
drawViews(spaceList, numberList, score);
}
} /**
* 依据參数重绘界面
* @param spaceList 空白格列表
* @param numberList 数字格列表
* @param score 当前分数
*/
public void drawViews(List<Integer> spaceList, NumberList numberList, int score){
scoreText.setText(score+"");
gridLayout.removeAllViews();
for(int i=0; i<16; i++){
View view = View.inflate(this, R.layout.item, null);
ImageView image = (ImageView) view.findViewById(R.id.image); if(numberList.contains(i))
image.setBackgroundResource(icons[numberList.getNumberByIndex(i)]);
else
image.setBackgroundResource(icons[0]);
gridLayout.addView(view);
}
}

完毕以上代码后,将goback方法绑定到撤销button的onclicklistener中,就完毕的撤销功能的实现。

本篇的原理基本就是这种,这样实如今代码上感觉比較好理解,可是在效率上有非常大的问题,比方在用户的操作记录了非常多之后,内存的占用率会比較高(没有实际检測过有多少),耗电肯定也会添加�不少,我想这也是为什么有的版本号的2048仅仅提供几步撤销功能的原因之中的一个吧。假设大家有什么更好的实现方法,欢迎留言或者私信,多交流促进共同进步哈。

最后,附上截至眼下,全部的源代码,如有问题希望大家批评指正

下载地址:http://download.csdn.net/detail/johnsonwce/7290697

从零開始开发Android版2048 (五) 撤销的实现的更多相关文章

  1. 从零開始开发Android版2048 (一)初始化界面

    自学Android一个月多了,一直在工作之余零零散散地看一些东西.感觉经常使用的东西都有些了解了,可是一開始写代码总会出各种奇葩的问题.感觉还是代码写得太少.这样继续杂乱地学习下去进度也太慢了,并且学 ...

  2. 从零開始开发Android版2048 (二)获取手势信息

    今天是尝试開始Android版2048小游戏的第二天.在今天,我主要学习了怎样获取用户在屏幕滑动的手势,以及对布局进行了一些小小的完好. 获取用户操作的手势(比方向左滑.向右滑等)主要用到了Gestu ...

  3. 从零開始开发Android版2048 (四) 分数、重置、结束

    这一篇的内容主要是在上一篇的基础上,增加分数计算(包含当前分数和最高分数).游戏结束的推断以及游戏界面的重置这三个部分的功能. 一.分数的计算和保存          首先,2048这个游戏的分数包含 ...

  4. 从零開始开发Android版2048 (三)逻辑推断

    近期工作比較忙,所以更新的慢了一点,今天的主要内容是关于Android版2048的逻辑推断,经过本篇的解说,基本上完毕了这个游戏的主体部分. 首先还是看一下,我在实现2048时用到的一些存储的数据结构 ...

  5. Bmob移动后端云服务平台--Android从零開始--(二)android高速入门

    Bmob移动后端云服务平台--Android从零開始--(二)android高速入门 上一篇博文我们简介何为Bmob移动后端服务平台,以及其相关功能和优势. 本文将利用Bmob高速实现简单样例,进一步 ...

  6. 从零開始学android&lt;TabHost标签组件.二十九.&gt;

    TabHost主要特点是能够在一个窗体中显示多组标签栏的内容,在Android系统之中每一个标签栏就称为一个Tab.而包括这多个标签栏的容器就将其称为TabHost.TabHost类的继承结构例如以下 ...

  7. 第13章、布局Layouts之RelativeLayout相对布局(从零開始学Android)

    RelativeLayout相对布局 RelativeLayout是一种相对布局,控件的位置是依照相对位置来计算的,后一个控件在什么位置依赖于前一个控件的基本位置,是布局最经常使用,也是最灵活的一种布 ...

  8. 从零開始学android&lt;SeekBar滑动组件.二十二.&gt;

    拖动条能够由用户自己进行手工的调节,比如:当用户须要调整播放器音量或者是电影的播放进度时都会使用到拖动条,SeekBar类的定义结构例如以下所看到的: java.lang.Object    ↳ an ...

  9. 从零開始学android&lt;数据存储(1)SharedPreferences属性文件.三十五.&gt;

    在android中有五种保存数据的方法.各自是: Shared Preferences Store private primitive data in key-value pairs. 相应属性的键值 ...

随机推荐

  1. java设计模式——单例(Singleton)模式

    在某些场景,你需要找到一个承担职责的对象,并且这个对象是他所属类的唯一实例.此时可以使用单例模式. 单例模式的意图是为了确保一个类有且仅有一个实例,并为他提供一个全局的访问点.创建一个担当独一无二角色 ...

  2. jQuery选择器种类整理

    选择器概念 jQuery选择器是通过标签.属性或者内容对HTML内容进行选择,选择器运行对HTML元素组或者单个元素进行操作. jQuery选择器使用$符号,等同于jquery,例如: $(“li”) ...

  3. 【Windows核心编程】Windows常见数据类型

    一,常见数据类型 WORD:               16位无符号整形数据 DWORD:             32位无符号整型数据(DWORD32) DWORD64:         64位无 ...

  4. Python面向对象OOP

    一 OOP     与C++和Java一样,Python同样具有OOP设计. 过程式:从前到后,一条一条,机器能接受的顺序性方式:方式大概为"首先你应该做什么,第二应该做什么,高级点的做点假 ...

  5. 关于wtl的一个实验

    代码如下: #include <iostream> using namespace std; template<typename T> class Base { public: ...

  6. Apache虚拟站点配置

    简单虚拟站点配置: <VirtualHost 127.0.0.2:80> DocumentRoot E:/wamp/www/yue ServerName 127.0.0.2:80</ ...

  7. BZOJ 1487 无归岛

    Description Neverland是个神奇的地方,它由一些岛屿环形排列组成,每个岛上都生活着之中与众不同的物种.但是这些物种都有一个共同的生活习性:对于同一个岛上的任意两个生物,他们有且仅有一 ...

  8. Unity3d 合作开发项目

    Unity3d  合作开发项目    交流群:63438968  本人:灰太龙 项目的合作开发是至关重要的,第一个问题就是自适应分辨率的问题! 综合考虑了一下,我们采用了IGUI插件,这个插件有以下几 ...

  9. 跨进程发送消息数据(发送WM_COPYDATA消息,够简单的)

    1 //1.发送窗体 2 procedure TForm2.Button1Click(Sender: TObject); 3 var 4 h: HWND; 5 Size: Integer; 6 Cop ...

  10. c# 哈希表集合;函数

    * 哈希表集合 1.先进去的后出来,最后进去的先出来 2.利用枚举类型打印出集合中的Key值和Value值 ** 函数 1.函数:能够独立完成某项功能的模块. 函数四要素:输入.输出.函数体.函数名 ...