J2ME手机编程心得(四)

   上一个贪吃蛇的游戏是可以玩了,但是有个问题是,就算我玩的分数再高也没有记录,这样玩起来不是就没有挑战性了嘛?所以还需要为游戏加上一个记录分数和排名的模块,这样玩起来会有意思的多了。这就涉及到J2ME中的持久化的内容了,网上的这方面的资料都有很多,基本的原理就不多说了,直接说说在这个游戏中用到的技术。

    首先需要将用户的姓名和分数保存,这就需要一个格式,在这里定义为"用户分数#用户姓名"这样的格式。用户姓名是在记录分数的界面用户输入的,而用户的分数则是从GameScreen类中直接获取的。那如何获取GameScreen的实例呢?可以有多种方法,可以在构造RecordScreen的时候就将实例放到构造函数的参数中,也可以在Midlet的主类SnakeGame中获取GameScreen的实例。我偏向于第二种做法,因为这样看起来结构比较清晰,因为所有的屏幕都是属于这个Midlet的,将所有的屏幕(Screen)都做为主类的成员,再为每个设置get方法就可以在任何时候很方便的获取任意一个屏幕的实例。还有个问题是如何随时获取主Midlet类的实例呢?在JBuilder里面生成的代码中有个静态的变量instance,所以在任何地方都可以用SnakeGame.instance来获取这个类的实例。不过我的习惯是将instance设置成private类型,再写一个getInstance()的静态方法返回instance。这样,如果我想获取GameScreen的实例,就可以在任何地方直接用SnakeGame.getIntance().getGameScreen()获取了。

    数据可以获取了,现在就是保存了,保存很简单了,打开一个RecordStore,然后用addRecord方法添加记录就是了,这里的记录表现形式只能是byte数组类型的。代码如下:

    int score = gameScreen.getScore();//获取的分数
    String name = playerName.getString();//获取姓名
    String record = score + "#" + name;//组成字符串
    try {
      RecordStore rs = RecordStore.openRecordStore("SnakeGame", true);//打开,如果没有就新建
      rs.addRecord(record.getBytes(), 0, record.length());//保存
      rs.closeRecordStore();//关闭
    }
    catch (RecordStoreException ex) {
      ex.printStackTrace();
    }

    这样简单就把数据保存进去了。

    保存完了应该读取了,而且这个是要按排名先后来排序的,一般来说,遍历整个记录集可以使用RecordEnumeration,我们可以用RecordStore的enumerateRecords来进行遍历,enumerateRecords有三个参数,在这里只需要关心第二个参数就可以了,第二个参数是需要提供一个排序的类,这个类要实现RecordComparator接口,RecordComparator接口里面有compare(byte[] a byte[] b)函数,我们只要按照我们的意图实现这个方法就可以了。我们需要的是比较#前面的数字的大小,因此也比较简单,具体类的代码如下:

class MyExpenseComparator
    implements RecordComparator {
  public int compare(byte[] a, byte[] b) {
    String strA = new String(a);
    String strB = new String(b);
    int indexA = strA.indexOf("#");
    String scoreA = strA.substring(0, indexA);

    int indexB = strB.indexOf("#");
    String scoreB = strB.substring(0, indexB);

    if (Integer.parseInt(scoreA) > Integer.parseInt(scoreB)) {
      return this.PRECEDES;
    }
    if (Integer.parseInt(scoreA) < Integer.parseInt(scoreB)) {
      return this.FOLLOWS;
    }
    return this.EQUIVALENT;
  }
}

有了这个排序的类,其他的就好办了,遍历记录然后一条一条显示就可以了,考虑到如果记录多了会很长,因此遍历的时候只取出前10名的记录,后面的全部都删除掉。遍历以及显示记录的代码如下:


  private void listRecord() {
    String[] names;
    try {
      RecordStore rs = RecordStore.openRecordStore("SnakeGame", false);
      int count = 0;
      RecordEnumeration e = rs.enumerateRecords(null, new MyExpenseComparator(), false);
      while (e.hasNextElement()) {
        int rid = e.nextRecordId();
        String str = new String(rs.getRecord(rid));
        int index = str.indexOf("#");
        String score = str.substring(0, index);
        String name = str.substring(index + 1);
        if (count++ >= 10)
          rs.deleteRecord(rid);
        else
          append("No" + count + "." + "姓名:" + name + "  得分:" + score + "\r\n");
      }
      rs.closeRecordStore();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

    显示和记录都完成了,呵呵,再集成到我们的游戏里面去吧,整个RecordScreen的代码如下:

package snakegame;

import javax.microedition.lcdui.*;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.*;
import java.util.Hashtable;

public class RecordScreen
    extends Form implements CommandListener {
  private Command cancel;
  private Command save;
  private TextField playerName = new TextField("您的大名", "Noname", 10, TextField.ANY);
  private GameScreen gameScreen;
  public RecordScreen() {
    super("记录成绩");
    this.gameScreen = SnakeGame.getInstance().getGameScreen();
    cancel = new Command("取消", Command.EXIT, 1);
    save = new Command("保存成绩", Command.OK, 2);
    this.append(playerName);
    addCommand(cancel);
    addCommand(save);
    setCommandListener(this);
    listRecord();   
  }

  private void saveRecord() {
    int score = gameScreen.getScore();
    String name = playerName.getString();
    String record = score + "#" + name;
    try {
      RecordStore rs = RecordStore.openRecordStore("SnakeGame", true);
      int id = rs.addRecord(record.getBytes(), 0, record.length());
      rs.closeRecordStore();
    }
    catch (RecordStoreException ex) {
      ex.printStackTrace();
    }
    listRecord();
  }

  private void listRecord() {
    String[] names;
    try {
      RecordStore rs = RecordStore.openRecordStore("SnakeGame", false);
      int count = 0;
      RecordEnumeration e = rs.enumerateRecords(null, new MyExpenseComparator(), false);
      while (e.hasNextElement()) {
        int rid = e.nextRecordId();
        String str = new String(rs.getRecord(rid));
        int index = str.indexOf("#");
        String score = str.substring(0, index);
        String name = str.substring(index + 1);
        if (count++ >= 10)
          rs.deleteRecord(rid);
        else
          append("No" + count + "." + "姓名:" + name + "  得分:" + score + "\r\n");
      }
      rs.closeRecordStore();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
 
  public void commandAction(Command command, Displayable displayable) {
    if (command == save) {
      saveRecord();
      SnakeGame.getInstance().gameScreen();
    }
    if (command == cancel) {
      SnakeGame.getInstance().gameScreen();
    }
  }

}

class MyExpenseComparator
    implements RecordComparator {
  public int compare(byte[] a, byte[] b) {
    String strA = new String(a);
    String strB = new String(b);
    int indexA = strA.indexOf("#");
    String scoreA = strA.substring(0, indexA);

    int indexB = strB.indexOf("#");
    String scoreB = strB.substring(0, indexB);

    if (Integer.parseInt(scoreA) > Integer.parseInt(scoreB)) {
      return this.PRECEDES;
    }
    if (Integer.parseInt(scoreA) < Integer.parseInt(scoreB)) {
      return this.FOLLOWS;
    }
    return this.EQUIVALENT;
  }
}

OK,这个功能就实现了!

不过在测试中发现,如果输入的姓名有中文,可能显示的就会有点问题,上面的图片第二条记录,本来填写的是“无名”,结果显示的时候只显示出了“无”字。这个问题有人知道的话请告诉我解决的办法,多谢了!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值