您的位置:首页 > 编程语言

一步一步写自表达代码——消小球(3)

2012-11-27 15:38 148 查看
然后,我们实现点击小球的动作。

点击小球的时候,分为两步,第一步:选中;第二步,清除。

本章先研究选中。

首先,我们需要了解点击的小球的位置,但是,之前的设计并没有传入相关的参数。

所以我们先来重构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);
}


这样就可以处理选中操作了,效果如下图所示。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: