记录存储依赖于一个J2ME的专门的类:RecordStore,位于 javax.microedition.rms.*
我们现在关注一下RecordStore的本质,我们可以可以把它看作一个数据表,但是我们不能直接访问到制定列,必须先使用byte[] getRecord取得某行数据,然后对这个byte[]通过StreamReader来顺序地读到这一列。
它的方法有一大堆,但实际上我们用不着那么多,这里有个BaseRMS类,可以提供方便的借口,代码来自Jason Lam的<J2ME & Gaming>。
import javax.microedition.rms.*;
abstract public class BaseRMS {
private String rmsName;
private RecordStore recordStore;
BaseRMS(String rmsName){
this.rmsName = rmsName;//设置记录名称
}
public void open() throws Exception {
// 如果loadRecordStore失败则重新生成一个RecordStore
try {
recordStore = RecordStore.openRecordStore(this.rmsName,true);
if(recordStore.getNumRecords()>0){
loadData();
} else {
createDefaultData();
}
}catch(Exception e){
throw new Exception(this.rmsName + "::open::" + e);
}
}
public void close() throws Exception {
if(recordStore!=null){
try {
recordStore.closeRecordStore();
}catch(Exception e){
throw new Exception(this.rmsName + "::close::" + e);
}
}
}
public RecordStore getRecordStore(){
return this.recordStore; //返回整块记录
}
public String getRMSName(){
return this.rmsName;
}
abstract void loadData() throws Exception;
abstract void createDefaultData() throws Exception;
abstract void updateData() throws Exception;
}
下面的Score类由以上的BaseRMS派生
import java.io.*;
public class Score extends BaseRMS {
private String[] names = new String[3];// 仅保存前三条记录,所以只要一个3元素的数组即可
private int[] values = new int[3];
public Score(String rmsName){
super(rmsName);
initValues(); // 这个是初始数据
}
private void initValues(){
names[0] = "Magic.D";
names[1] = "Tangel";
names[2] = "Nick";
values[0] = 100;
values[1] = 50;
values[2] = 10;
}
public void loadScores() throws Exception {
try{
this.open();
if(this.getRecordStore()!=null)
this.close();
}catch(Exception e){
throw new Exception("Error loading Scores" + e);
}
}
public int[] getValues(){
return this.values;//得到分数的数组
}
public String[] getNames(){
return this.names;// 得到名字的数组
}
public void reset() throws Exception {//重新初始化数据集
this.open();
initValues();
updateData();
if(this.getRecordStore()!=null)
this.close();
}
public void updateScores(int score,String Name) throws Exception {
try {//数据量小,简单地使用冒泡排序来完成更新并重排记录
for(int i=0;i<names.length;i++){
if(score>=values[i]){
this.open();
for(int j=names.length-1;j>i;j--){
values[j] = values[j-1];
names[j] = names[j-1];
}
this.values[i] = score;
this.names[i] = Name;
updateData();
if(this.getRecordStore()!=null)
this.close();
break;
}
}
}catch(Exception e){
throw new Exception(this.getRMSName() + "::updateScores::" + e);
}
}
public boolean isHighScore(int score) throws Exception {
boolean isHighScore = false;// 遍历记录,判断新的分数是否是高分
try {
for(int i=0;i<names.length;i++){
if(score>=values[i])
isHighScore = true;
}
}catch(Exception e){
throw new Exception(this.getRMSName() + "::isHighScore::" + e);
}
return isHighScore;
}
protected void loadData() throws Exception {
try {
for(int i=0;i<names.length;i++){
byte[] record = this.getRecordStore().getRecord(i+1);
DataInputStream istream = new DataInputStream(new ByteArrayInputStream(record,0,record.length));// 注意DataInputStream的使用
values[i] = istream.readInt();
names[i] = istream.readUTF();
}
}catch(Exception e){
throw new Exception(this.getRMSName() + "::loadData::" + e);
}
}
protected void createDefaultData() throws Exception {
try{
for(int i=0;i<names.length;i++){
ByteArrayOutputStream bstream = new ByteArrayOutputStream(12);
DataOutputStream ostream = new DataOutputStream(bstream);
ostream.writeInt(values[i]);
ostream.writeUTF(names[i]);
ostream.flush();
ostream.close();
byte[] record = bstream.toByteArray();
this.getRecordStore().addRecord(record,0,record.length);
}
}catch(Exception e){
throw new Exception(this.getRMSName() + "::createDefaultData::" + e);
}
}
protected void updateData() throws Exception {
try{
for(int i=0;i<names.length;i++){
ByteArrayOutputStream bstream = new ByteArrayOutputStream(12);
DataOutputStream ostream = new DataOutputStream(bstream);
ostream.writeInt(values[i]);
ostream.writeUTF(names[i]);
ostream.flush();
ostream.close();
byte[] record = bstream.toByteArray();
this.getRecordStore().setRecord(i+1,record,0,record.length);
}
}catch(Exception e){
throw new Exception(this.getRMSName() + "::updateData::" + e);
}
}
}
有了这个类,怎么显示高分,怎么加入高分我想应该不用多言了,都是简单的问题啦,同时我们也可以联想到,游戏设置其实跟这个本质上是相同的,我们用BaseRMS派生出一个GameOption类,然后每次进入游戏前读入设置,就OK 。到此我把这个小游戏的各个方面都说了一遍,自我感觉还是比较乱的,我计划接下来再写文章分别仔细讨论一下J2ME的UI设计,图形设计。