解决List的add方法错使前面的元素被覆盖成相同值
来源:互联网 发布:做淘宝直播如何赚钱 编辑:程序博客网 时间:2024/04/30 01:03
今天数据结构讲到栈和队列,无意中灵感突发,想到了给之前开发的2048小游戏加一个反悔的功能,并且可以反悔任意多步数(内存允许的情况下)。
反悔其实就类似于编辑类软件的撤销功能,不过这个撤销队列在数据操作上有自己的特征。
首先,这个队列大小是固定的,如下图,在这里它的长度是6,按照0~5的顺序进队,队满之后,若要再进队,则必须移除队首的元素(即0),我们可以看成是后来者挤掉最前者。
然后在取出元素的时候,和栈有点类似,是从队尾的元素开始取(因为撤销是返回最近的一次操作)。
明确思路后,我便开始写逻辑。
在GameView(继承自LinearLayout)中定义了一个卡片数组:
private int[][] cards_map = new int[Config.LINES][Config.LINES];
然后在滑动事件当中使用事先写好的set方法存储card_map对象进队:
private void swipeLeft() { // 循环获取卡片移动之前的状态 for (int x = 0; x < Config.LINES; ++x) { for (int y = 0; y < Config.LINES; ++y) { cards_map[x][y] = cardsMap[x][y].getNum(); } } cardsMapManager.setCards_map(cards_map);……}
当然,这个存储是Application级别的临时存储,退出应用后将消失。那么,我们就能在MainActivity当中的反悔按钮的监听里去调用事先写好的get方法:
backGame.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int temp_score = cardsMapManager.getScore(); if (temp_score != -1) { score = temp_score; tvScore.setText(score + ""); } int[][] temp_maps = cardsMapManager.getCards_map(); // 此处必须先定义临时变量来存储get到的数组,否则在if判断和resumeGame的参数里直接写get方法会造成get内部语句操作多次,这显然是不允许的 if (temp_maps != null) gameView.resumeGame(temp_maps); else { backGame.setEnabled(false); Toast.makeText(MainActivity.this, "反悔太多啦!", Toast.LENGTH_SHORT).show(); } } });
下面,我们就来看set和get方法的实现:在CardsMapManager(继承自Application)中,默认实例化list(这里是关键的必须的步骤),
private List<int[][]> cards_map_list = new ArrayList<>();
public int[][] getCards_map() { if (cards_map_list.size() == 0) return null; else { int last = cards_map_list.size() - 1; int[][] temp_maps = cards_map_list.get(last); cards_map_list.remove(last); return temp_maps; } }
public void setCards_map(int[][] cards_map) { if (cards_map_list.size() < Config.LIST_SIZE) cards_map_list.add(cards_map); else { for (int i = 0; i < cards_map_list.size() - 1; ++i) cards_map_list.set(i , cards_map_list.get(i + 1)); cards_map_list.set(cards_map_list.size() - 1, cards_map); } }
其实set和get的逻辑都是没有问题的,毕竟逻辑处理我还打了草稿。
但最后会发现一个百思不得其解的问题,那就是cards_map_list.add(cards_map)方法始终会覆盖之前add的数据,造成整个list的每一项元素都一样。
经过几番调试后,我发现了不是我逻辑的问题,而是所传对象cards_map实例化的问题,我们回过头去看最开始那两块代码,一个是在GameView里初始化定义的二维数组,一个是滑动事件里的循环赋值,关键就在这。
查阅到了一段资料:
很有可能是你加入的元素是某个bean,且这个bean被你在调用的类中定义成域成员,并实例化了。这时候你再循环改变bean里的内容add到list中,那么根据java的对象存的是地址的原理,你的list里全是那个实例化bean的地址,最后元素值就全都一样,并且取的是最后一次改变的值。
意思就是,我之前只在初始化那里定义了这个二维数组,在swipe内部方法里并没有进行新的定义,而是反复使用初始化定义,所以造成了静态值覆盖的错误,没有达到预期效果。
所以,解决办法就是在每一个swipe(left、right、up、down)里都实例化新的数组:
private void swipeLeft() { // 此处非常关键,如果不重新实例化会造成每次List的add方法覆盖前面全部元素 cards_map = new int[Config.LINES][Config.LINES]; for (int x = 0; x < Config.LINES; ++x) { for (int y = 0; y < Config.LINES; ++y) { cards_map[x][y] = cardsMap[x][y].getNum(); } } cardsMapManager.setCards_map(cards_map);……}
如此一来,什么都搞定了。
- 解决List的add方法错使前面的元素被覆盖成相同值
- ArrayList.add后,前面数据被覆盖的问题
- ArrayList.add(Object) 前面数据被覆盖的问题
- ArrayList.add后,前面数据被覆盖的问题
- 解决grub被覆盖的问题
- 解决页面展示被覆盖的情况
- javascript之调用被覆盖的方法
- 12.5.2 访问被覆盖的方法
- ArrayList中add后数据被覆盖的探索
- List的add()覆盖了前面的所有元素问题解决
- 解决ListView的listSelector被覆盖不起作用的问题
- 解决ListView的listSelector被覆盖不起作用的问题
- 解决vc最大化窗口时,任务栏被覆盖的问题
- 构造方法中不应调用可被覆盖的方法
- 解决list.add() 方法会覆盖前面的已经添加好的参数
- 元素是否被覆盖
- 构造器决不能调用可被覆盖的方法
- java ArrayList add()方法数据被覆盖问题
- Java线程池基本使用
- 使用Intent方式进行跨进程访问
- Qt5 UI信号、槽自动连接的控件重名大坑
- 表格汇总器(C#)
- Cocos2d-x 内存管理
- 解决List的add方法错使前面的元素被覆盖成相同值
- Mapreduce wordCount
- Moto XT1085 国行 解锁BL
- Unity Shader入门精要读书笔记第二篇
- 欢迎使用CSDN-markdown编辑器
- 通过FTP Server加载VxWorks映像
- 【bzoj1568】[JSOI2008]Blue Mary开公司 超哥线段树
- 如何使cmd窗口正确显示utf-8编码的文字
- Android的事件分发与消费机制