在上几篇博文中,介绍了
Swing贪吃蛇游戏(一):基本功能实现 >>>
[url]http://mouselearnjava.iteye.com/blog/1913290[/url]
Swing贪吃蛇游戏(二):增加随机产生障碍物功能 >>>
[url]http://mouselearnjava.iteye.com/blog/1913886[/url]
Swing贪吃蛇游戏(三):增加游戏进度存储和加载功能 >>>
[url]http://mouselearnjava.iteye.com/blog/1914225[/url]
本文在这些既有功能之上,添加游戏得分排行榜功能。[b]得分排行榜上列出Top 10的记录信息,包括玩家名称,得分和名次。[/b]
为了完成这个功能,我们需要做的主要改动有如下几点:
首先:创建与记录相关的类。
其次:完成游戏结束后对记录文件更新的操作。
最后:完成点击Record相关的MenuItem,读取记录信息,并用ScrollPane展示出来。
[b]1. 创建与记录相关的类[/b]
package my.games.snake.model;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
/**
* @author Eric
* @desc 贪吃蛇游戏的排行榜
*/
public class SnakeGameRecords implements Serializable {
private static final long serialVersionUID = 4513299590910220441L;
private static final int TOP_TEN = 10;
private Record[] records = null;
private int numberInRecord = 0; // 排行榜中已经拥有的记录个数
public SnakeGameRecords() {
records = new Record[TOP_TEN];
}
@SuppressWarnings("unchecked")
public void sortRecords() {
Collections.sort(Arrays.asList(getAvailableRecords()), new RecordComparator());
}
private Record[] getAvailableRecords(){
Record[] availableRecords = new Record[numberInRecord];
for(int i=0;i availableRecords[i] = new Record(records[i].getPlayer(),records[i].getScore());
}
return availableRecords;
}
/**
*
* @return
*/
public Record getLastAvailableRecord() {
return isEmpty() ? null : records[numberInRecord - 1];
}
/**
*
* @param record
*/
public void addRecordToTopTen(Record record) {
if (isEmpty()) {
records[0] = record;
numberInRecord++;
return;
}
if (isFull()) {
if (records[TOP_TEN - 1].getScore() < record.getScore()) {
records[TOP_TEN - 1] = record;
sortRecords();
return;
}
}
records[numberInRecord] = record;
numberInRecord++;
sortRecords();
}
/**
*
* @return
*/
public boolean isEmpty() {
return 0 == numberInRecord;
}
/**
*
* @return
*/
public boolean isFull() {
return TOP_TEN == numberInRecord;
}
/**
* @return the numberInRecord
*/
public int getNumberInRecord() {
return numberInRecord;
}
/**
* @param numberInRecord
* the numberInRecord to set
*/
public void setNumberInRecord(int numberInRecord) {
this.numberInRecord = numberInRecord;
}
/**
* @return the records
*/
public Record[] getRecords() {
return records;
}
/**
* @param records
* the records to set
*/
public void setRecords(Record[] records) {
this.records = records;
}
private class RecordComparator implements Comparator {
public int compare(Object o1, Object o2) {
Record r1 = (Record) o1;
Record r2 = (Record) o2;
return (0 == compareScore(r1, r2)) ? compareName(r1, r2)
: compareScore(r1, r2);
}
private int compareScore(Record r1, Record r2) {
return r1.getScore() - r2.getScore();
}
private int compareName(Record r1, Record r2) {
return r1.getPlayer().compareTo(r2.getPlayer());
}
}
}
package my.games.snake.model.record;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import my.games.snake.model.SnakeGameRecords;
/**
*
* @author Eric
* @vesion 1.0
* @desc Read Record
*/
public class ReadRecord {
public SnakeGameRecords readRecordsFromFile(File recordFile) {
SnakeGameRecords records = new SnakeGameRecords();
FileInputStream fileInput = null;
ObjectInputStream objectInput = null;
if (!recordFile.exists()) {
return records;
}
try {
fileInput = new FileInputStream(recordFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
objectInput = new ObjectInputStream(fileInput);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Object o = null;
try {
o = objectInput.readObject();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
objectInput.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fileInput.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
records = (SnakeGameRecords) o;
records.sortRecords();
return records;
}
}
package my.games.snake.model.record;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import my.games.snake.model.SnakeGameRecords;
/**
* @author Eric
* @vesion 1.0
* @desc Write records
*/
public class WriteRecord {
public void writeRecordToFile(SnakeGameRecords records, File recordFile) {
FileOutputStream fileOutput = null;
try {
fileOutput = new FileOutputStream(recordFile);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ObjectOutputStream objectOutput = null;
try {
objectOutput = new ObjectOutputStream(fileOutput);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
objectOutput.writeObject(records);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
objectOutput.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
fileOutput.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
[b]2. 完成游戏结束后对记录文件更新的操作。[/b]
[b]3. 完成点击Record相关的MenuItem,读取记录信息,并用ScrollPane展示出来。[/b]
public class SnakeGameFrame extends JFrame {
private JMenuItem recordMI = new JMenuItem("Record");
public SnakeGameFrame() {
setMenu.add(recordMI);
recordMI.addActionListener(new RecordAction());
}
private class RecordAction implements ActionListener {
@SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent event) {
File file = new File("file.dat");
SnakeGameRecords records = new ReadRecord()
.readRecordsFromFile(file);
records.sortRecords();
JScrollPane panel = new RecordScrollPane().getReadScrollPane(records,
file);
JDialog recordDialog = new JDialog(SnakeGameFrame.this, "贪吃蛇游戏");
recordDialog.setBounds(300, 300, 300, 219);
Container container = recordDialog.getContentPane();
container.add(panel);
recordDialog.show();
}
}
}
package my.games.snake.ui;
import java.io.File;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import my.games.snake.model.Record;
import my.games.snake.model.SnakeGameRecords;
public class RecordScrollPane{
private static final long serialVersionUID = -3552642981292000951L;
public JScrollPane getReadScrollPane(SnakeGameRecords records,
File recordFile) {
Object[][] data = new Object[records.getNumberInRecord()][3];
for (int i = 0; i < records.getNumberInRecord(); i++) {
Record record = records.getRecords()[i];
data[i][0] = String.valueOf(i + 1);
data[i][1] = record.getPlayer();
data[i][2] = String.valueOf(record.getScore());
}
Object[] columnNames = new Object[3];
columnNames[0] = "ID";
columnNames[1] = "Name";
columnNames[2] = "Score";
JTable table = new JTable(data, columnNames);
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
JScrollPane pane = new JScrollPane(table);
return pane;
}
}
//游戏结束时,如果分数大于0,那么将分数写入到排行榜中去
public class SnakeGamePanel extends JPanel {
private void writeScore() {
if (score == 0) {
return;
}
File file = new File("file.dat");
SnakeGameRecords records = new ReadRecord().readRecordsFromFile(file);
if (records == null
|| records.isEmpty()
|| !records.isFull()
|| (records.getLastAvailableRecord().getScore() < score && records
.isFull())) {
String playerName = JOptionPane
.showInputDialog("Please input your name");
if (playerName == null || playerName.length() == 0
|| playerName.trim().equals("")) {
playerName = "无名英雄";
}
Record record = new Record(playerName, score);
records.addRecordToTopTen(record);
new WriteRecord().writeRecordToFile(records, file);
}
}
}
一个演示的示例如下:
游戏结束时,输入Frank的玩家名字。
[img]http://dl2.iteye.com/upload/attachment/0087/5102/0034b235-7358-35de-b362-e1a37e5225c0.jpg[/img]
查看得分排行榜:
[img]http://dl2.iteye.com/upload/attachment/0087/5106/2dd54c9d-f22e-3021-a440-228cfe2fb3cf.jpg[/img]
[img]http://dl2.iteye.com/upload/attachment/0087/5104/16cc9469-7e59-3485-b0ad-dee712e7eaaa.jpg[/img]
至此,一个拥有进度存储和加载功能,得分排行榜以及随机产生障碍物的Swing贪吃蛇游戏就完成了。
代码还没有优化过,详细代码请参考附件MySnakeGame.7z