一步一步写自表达代码——消小球(3)
2012-11-27 15:38
148 查看
然后,我们实现点击小球的动作。
点击小球的时候,分为两步,第一步:选中;第二步,清除。
本章先研究选中。
首先,我们需要了解点击的小球的位置,但是,之前的设计并没有传入相关的参数。
所以我们先来重构BallActionListener
这样,通过x,y就可以知道选中的位置,并且通过选中的位置,选中临近的同色小球(Game.getInstance().startSelect(int, int))。然后更新显示。
选中的处理,由于我们需要从选中点开始向四周扩散不断的寻找相邻的同色小球。所以,我们建立一个Map用来存放那些同色的小球,并用一个boolean型表示该小球是否被遍历过。
选中处理结束的标志就是这个Map里所有的数据值都是true。
那么选中的算法就可以描述为:
然后实现上述需要的3个方法:
clearMarkState
markHomoNeighbor
getNextUnselectedKey
上述代码书写过程中会产生marked,selected变量。
注:上述代码还可以采用递归调用来实现,代码更加简练。
然后就是显示处理,在原有的MainFrame.render处理中增加下列处理。
这样就可以处理选中操作了,效果如下图所示。
点击小球的时候,分为两步,第一步:选中;第二步,清除。
本章先研究选中。
首先,我们需要了解点击的小球的位置,但是,之前的设计并没有传入相关的参数。
所以我们先来重构BallActionListener
package org.stephen.bubblebreaker.listener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import org.stephen.bubblebreaker.control.EventDispatcher; import org.stephen.bubblebreaker.model.Event; import org.stephen.bubblebreaker.model.Game; public class BallActionListener implements ActionListener { int x; int y; public BallActionListener(int x, int y) { this.x = x; this.y = y; } @Override public void actionPerformed(ActionEvent e) { Game.getInstance().startSelect(x, y); EventDispatcher.send(Event.UPDATE_BALLS); } }
这样,通过x,y就可以知道选中的位置,并且通过选中的位置,选中临近的同色小球(Game.getInstance().startSelect(int, int))。然后更新显示。
选中的处理,由于我们需要从选中点开始向四周扩散不断的寻找相邻的同色小球。所以,我们建立一个Map用来存放那些同色的小球,并用一个boolean型表示该小球是否被遍历过。
Map<Integer, Boolean> marked = new HashMap<Integer, Boolean>();
选中处理结束的标志就是这个Map里所有的数据值都是true。
那么选中的算法就可以描述为:
public void startSelect(int x, int y) { clearMarkState(); marked.put(y * 12 + x, false); Integer key = y * 12 + x; while (key != null) { markHomoNeighbor(key % 12, key / 12); key = getNextUnselectedKey(); } }
然后实现上述需要的3个方法:
clearMarkState
public void clearMarkState() { marked.clear(); for (Ball[] row : grid.balls) { for (Ball ball : row) { ball.marked = false; ball.selected = false; } } }
markHomoNeighbor
public void markHomoNeighbor(int x, int y) { Ball[][] balls = grid.balls; balls[y][x].marked = true; balls[y][x].selected = true; marked.put(y * 12 + x, true); if (x > 0 && balls[y][x - 1].color.equals(balls[y][x].color)) { balls[y][x - 1].marked = true; if (!marked.containsKey(y * 12 + x - 1)) { marked.put(y * 12 + x - 1, false); } } if (x < 11 && balls[y][x + 1].color.equals(balls[y][x].color)) { balls[y][x + 1].marked = true; if (!marked.containsKey(y * 12 + x + 1)) { marked.put(y * 12 + x + 1, false); } } if (y > 0 && balls[y - 1][x].color.equals(balls[y][x].color)) { balls[y - 1][x].marked = true; if (!marked.containsKey((y - 1) * 12 + x)) { marked.put((y - 1) * 12 + x, false); } } if (y < 11 && balls[y + 1][x].color.equals(balls[y][x].color)) { balls[y + 1][x].marked = true; if (!marked.containsKey((y + 1) * 12 + x)) { marked.put((y + 1) * 12 + x, false); } } }
getNextUnselectedKey
private Integer getNextUnselectedKey() { Set<Integer> set = marked.keySet(); Iterator<Integer> iterator = set.iterator(); while (iterator.hasNext()) { Integer key = iterator.next(); if (marked.get(key) == false) { return key; } } return null; }
上述代码书写过程中会产生marked,selected变量。
注:上述代码还可以采用递归调用来实现,代码更加简练。
然后就是显示处理,在原有的MainFrame.render处理中增加下列处理。
if (balls[y][x].selected) { this.balls[y][x].setBorder(BorderFactory .createLineBorder(Color.CYAN)); } else { this.balls[y][x].setBorder(null); }
这样就可以处理选中操作了,效果如下图所示。
相关文章推荐
- 一步一步写自表达代码——消小球(6)
- 一步一步写自表达代码——消小球(4)
- 一步一步写自表达代码——消小球(1)
- 一步一步写自表达代码——消小球(5)
- 一步一步写自表达代码——消小球(2)
- Linux网络编程一步一步学-epoll同时处理海量连接的代码
- 【Visual C++】游戏开发笔记二十九 一步一步教你用优雅的Direct3D11代码画一个三角形
- Linux网络编程一步一步学-epoll同时处理海量连接的代码
- 一步一步开始Web Service (有代码和图) (上)
- 爬虫代码,正则表达,下载图片
- 一步一步学Silverlight 2系列(22):在Silverlight中如何用JavaScript调用.NET代码
- 基于WPF的一个小球碰撞代码
- 如何一步一步写出MVP架构的代码
- 一步一步jQuery流程设计器插件goflow(附代码) - 1 - 构建设计器UI界面
- 十种更好的表达“你的代码写的很烂”的方法
- 一步一步教你用优雅的Direct3D11代码画一个三角形
- 一步一步从原理跟我学邮件收取及发送 10.四句代码说清base64
- 一步一步重写 CodeIgniter 框架 (12) —— 代码再重构,回归 CI
- 数据结构学习笔记2——栈用栈计算后缀(postfix)表达的完整代码
- 一步一步学习sharepoint2010 workflow 系列第三部分:自定义SharePoint代码工作流 第8章 自定义Visual Studio工作流(Custom Visual Studio workflows)