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

下一步,我们来实现消除。

消除分两步,第一步消除选中的小球,第二步,降落。

先说消除,

在BallActionListener中进行分支处理即可。

1     public void actionPerformed(ActionEvent e) {
2         Game game = Game.getInstance();
3         if (game.isSelectedBall(x, y)) {
4             game.destroySelectedBalls();
5         } else {
6             game.startSelect(x, y);
7         }
8         EventDispatcher.send(Event.UPDATE_BALLS);
9     }

然后实现上述两个新增的方法:

isSelectedBall(int, int)和destroySelectedBalls()

 1     public boolean isSelectedBall(int x, int y) {
 2         return grid.balls[y][x].selected && marked.size() > 1;
 3     }
 4 
 5     public void destroySelectedBalls() {
 6         Set<Integer> set = marked.keySet();
 7         Iterator<Integer> iterator = set.iterator();
 8         while (iterator.hasNext()) {
 9             Integer key = iterator.next();
10             grid.balls[key / 12][key % 12].destroyed = true;
11         }
12         marked.clear();
13     }

然后更新显示部分,对于destroyed的小球做特殊处理。

对MainFrame.render()进行修改:

 1     public void render() {
 2         Ball[][] balls = Game.getInstance().grid.balls;
 3         for (int y = 0; y < 12; y++) {
 4             for (int x = 0; x < 12; x++) {
 5                 if (balls[y][x].destroyed) {
 6                     this.balls[y][x].setBorder(null);
 7                     this.balls[y][x].setIcon(null);
 8                     continue;
 9                 }
10                 if (balls[y][x].selected) {
11                     this.balls[y][x].setBorder(BorderFactory
12                             .createLineBorder(Color.CYAN));
13                 } else {
14                     this.balls[y][x].setBorder(null);
15                 }
16                 this.balls[y][x].setIcon(balls[y][x].color.getImageIcon());
17                 this.balls[y][x].invalidate();
18             }
19         }
20     }

至此,消除动作已经完成。

然后,开始进行降落处理。

降落的时候要将所有消除掉的空白格子向上浮起,直到所有的有颜色的都降落下来为止。

那么算法就应该是,按照先列后行的顺序,从右下向左上遍历,遇到空白单元格就向上浮起,直到当前单元格不再是空白单元格为止。另外要防止无限循环。相应代码如下:

 1     public void fallDown() {
 2         for (int x = 11; x >= 0; x--) {
 3             for (int y = 11; y >= 0; y--) {
 4                 while (swapLine(x, y))
 5                     ;
 6             }
 7         }
 8     }
 9 
10     private boolean swapLine(int x, int y) {
11         boolean frozen = false;
12         if (grid.balls[y][x].destroyed) {
13             for (int i = y; i > 0; i--) {
14                 frozen |= bubbleUp(x, i);
15             }
16         }
17         return frozen;
18     }
19 
20     private boolean bubbleUp(int x, int y) {
21         Ball temp = grid.balls[y][x];
22         grid.balls[y][x] = grid.balls[y - 1][x];
23         grid.balls[y - 1][x] = temp;
24         return !grid.balls[y][x].destroyed;
25     }

然后就是垂直某列如果为空白的时候应该向右并拢,同样,也要注意防止死循环。

 1 public void alignRight() {
 2         int emptyColumnIndex = -1;
 3         while (true) {
 4             emptyColumnIndex = getEmptyColumnIndex();
 5             if (emptyColumnIndex == -1) {
 6                 break;
 7             }
 8             moveColumnRight(emptyColumnIndex);
 9         }
10     }
11 
12     private int getEmptyColumnIndex() {
13         for (int x = 1; x < 11; x++) {
14             if (isEmptyColumn(x) && !isEmptyColumn(x - 1)) {
15                 System.out.println("empty@" + x);
16                 return x;
17             }
18         }
19         return -1;
20     }
21 
22     private void moveColumnRight(int x) {
23         for (int i = x; i > 0; i--) {
24             for (int y = 0; y < 12; y++) {
25                 grid.balls[y][i] = grid.balls[y][i - 1];
26             }
27         }
28         for (int y = 0; y < 12; y++) {
29             grid.balls[y][0].destroyed = true;
30         }
31     }
32 
33     private boolean isEmptyColumn(int x) {
34         for (int y = 0; y < 12; y++) {
35             if (!grid.balls[y][x].destroyed) {
36                 return false;
37             }
38         }
39         return true;
40     }

 

 

至此,消除同色小球的处理已经完成。


但是,我们发现,还有如下问题:

1. GridBagLayout导致了小球消除以后分散显示。

2. 没有后悔功能。

3. 有些算法的确效率很低。

4. 没有用到control下面的类。

我们将在以后的章节中逐步阐述。

posted @ 2012-11-27 16:45  史蒂芬.王  阅读(205)  评论(0编辑  收藏  举报