一步一步写自表达代码——消小球(5)
接上节我们发现的遗留问题。
先来解决GridBagLayout的问题。
MainFrame.build方法修改如下:
1 public void build() { 2 this.setLayout(null); 3 this.setSize(480, 480); 4 balls = new JButton[12][12]; 5 6 for (int y = 0; y < 12; y++) { 7 for (int x = 0; x < 12; x++) { 8 JButton ball = new JButton(""); 9 ball.setSize(40, 40); 10 this.add(ball); 11 ball.setLocation(x * 40, y * 40); 12 ball.addActionListener(new BallActionListener(x, y)); 13 balls[y][x] = ball; 14 } 15 } 16 }
然后,增加统计分数功能,更新BallActionListener
1 public void actionPerformed(ActionEvent e) { 2 Game game = Game.getInstance(); 3 if (game.isSelectedBall(x, y)) { 4 game.destroySelectedBalls(); 5 game.fallDown(); 6 game.alignRight(); 7 game.score.current += game.score.selected; 8 game.score.selected = 0; 9 if (game.score.highest < game.score.current) { 10 game.score.highest = game.score.current; 11 } 12 } else { 13 game.startSelect(x, y); 14 game.score.selected = game.countSelectedScore(); 15 } 16 EventDispatcher.send(Event.UPDATE_BALLS); 17 EventDispatcher.send(Event.UPDATE_SCORES); 18 }
下面是其中的countSelectedScore()的具体实现:
1 public int countSelectedScore() { 2 int selected = 0; 3 int score = 0; 4 for (int y = 0; y < 12; y++) { 5 for (int x = 0; x < 12; x++) { 6 if (grid.balls[y][x].selected) { 7 selected++; 8 score += selected; 9 } 10 } 11 } 12 return score; 13 }
然后增加后悔功能。
增加按钮以及相应的Listener。
然后在Grid类中增加backup,用来存放数据。
1 public Ball[][] backup = new Ball[12][12];
然后修改BallActionListener,当消除小球时,保存数据。
1 public void actionPerformed(ActionEvent e) { 2 Game game = Game.getInstance(); 3 if (game.isSelectedBall(x, y)) { 4 game.backup(); 5 game.destroySelectedBalls(); 6 game.fallDown(); 7 game.alignRight(); 8 game.score.current += game.score.selected; 9 game.score.selected = 0; 10 if (game.score.highest < game.score.current) { 11 game.score.highest = game.score.current; 12 } 13 } else { 14 game.startSelect(x, y); 15 game.score.selected = game.countSelectedScore(); 16 } 17 EventDispatcher.send(Event.UPDATE_BALLS); 18 EventDispatcher.send(Event.UPDATE_SCORES); 19 }
当点击后悔按钮时,恢复数据。
1 package org.stephen.bubblebreaker.listener; 2 3 import java.awt.event.ActionEvent; 4 import java.awt.event.ActionListener; 5 6 import org.stephen.bubblebreaker.control.EventDispatcher; 7 import org.stephen.bubblebreaker.model.Event; 8 import org.stephen.bubblebreaker.model.Game; 9 10 public class UndoActionListener implements ActionListener { 11 12 @Override 13 public void actionPerformed(ActionEvent arg0) { 14 Game.getInstance().rollback(); 15 EventDispatcher.send(Event.UPDATE_BALLS); 16 EventDispatcher.send(Event.UPDATE_SCORES); 17 } 18 19 }
备份时应该备份界面和分数两者。
1 public void backup() { 2 for (int x = 0; x < 12; x++) { 3 for (int y = 0; y < 12; y++) { 4 grid.backup[y][x].color = grid.balls[y][x].color; 5 grid.backup[y][x].destroyed = grid.balls[y][x].destroyed; 6 grid.backup[y][x].marked = grid.balls[y][x].marked; 7 grid.backup[y][x].selected = grid.balls[y][x].selected; 8 } 9 } 10 backupScore.current = score.current; 11 backupScore.selected = score.selected; 12 backupScore.highest = score.highest; 13 backupScore.playCount = score.playCount; 14 backupScore.average = score.average; 15 } 16 17 public void rollback() { 18 for (int x = 0; x < 12; x++) { 19 for (int y = 0; y < 12; y++) { 20 grid.balls[y][x].color = grid.backup[y][x].color; 21 grid.balls[y][x].destroyed = grid.backup[y][x].destroyed; 22 grid.balls[y][x].marked = grid.backup[y][x].marked; 23 grid.balls[y][x].selected = grid.backup[y][x].selected; 24 } 25 } 26 27 }
为实现上述功能,还需要一些相应的初始化操作。
Grid类:
1 public Grid() { 2 3 for (int y = 0; y < 12; y++) { 4 for (int x = 0; x < 12; x++) { 5 balls[y][x] = new Ball(); 6 backup[y][x] = new Ball(); 7 } 8 } 9 }
Game类:
1 Score backupScore; 2 backupScore = new Score();
好的,又增加了两个功能。
然后实现一下清空功能
1 package org.stephen.bubblebreaker.listener; 2 3 import java.awt.event.ActionEvent; 4 import java.awt.event.ActionListener; 5 6 import org.stephen.bubblebreaker.control.EventDispatcher; 7 import org.stephen.bubblebreaker.model.Event; 8 import org.stephen.bubblebreaker.model.Game; 9 import org.stephen.bubblebreaker.model.Score; 10 11 public class ClearActionListener implements ActionListener { 12 13 @Override 14 public void actionPerformed(ActionEvent e) { 15 // TODO show a dialog if possible. 16 Score score = Game.getInstance().score; 17 score.current = 0; 18 score.selected = 0; 19 score.highest = 0; 20 score.average = 0; 21 score.playCount = 0; 22 23 EventDispatcher.send(Event.UPDATE_SCORES); 24 } 25 }
和退出功能:
1 package org.stephen.bubblebreaker.listener; 2 3 import java.awt.event.ActionEvent; 4 import java.awt.event.ActionListener; 5 6 public class ExitActionListener implements ActionListener { 7 8 @Override 9 public void actionPerformed(ActionEvent e) { 10 System.exit(0); 11 } 12 13 }
在结尾的地方,我们继续优化一下代码:
1. 选中时应该考虑destroy标志。
2. 去掉Ball类中的无用变量x, y, state以及State定义。
-----------------------------------------------------------------
现为独立咨询师。为软件企业或者其他企业的软件采购部门提供咨询,帮助改进软件开发流程,员工技术能力提升,以帮助企业在质量成本交货期三方面得到改善。