用Eclipse开发J2ME手机游戏入门讲座(续)

时间:2020-12-27 03:22:11

    我在天极网看到一篇关于用Eclipse开发J2ME的文章,觉得非常不错,所以拿来和大家一起分享。

    引自: http://www.yesky.com/SoftChannel/72348977504190464/20050411/1934159.shtml

第四讲 创建经典的HelloWorld程序

  引言

  前面几篇文章已经介绍了Eclipse及其工作环境的安装、配置过程,并完成各项相关准备工作。因此从本文开始将讲述如何使用前面配置好的Eclipse开发环境来创建J2ME项目,开始真正的J2ME开发之旅。由于这是创建的第一个J2ME程序,按照程序开发的惯例,这头把交椅自然又是非"Hello World"莫属了。HelloWorld虽然功能简单,但是麻雀虽小,五脏俱全,通过这个小程序的开发,完全能够达到让读者熟悉J2ME程序开发一般流程的目的。

  创建J2ME项目

  与其他语言应用程序的开发类似,在开发一个J2ME程序时也要首先新建一个项目(工程)所有后续的编码、调试和运行都是在这个工程中进行。在启动Eclipse后,点击"文件"菜单下"新建"菜单弹出的"项目"菜单项。将弹出如下所示的新建项目向导对话框:

用Eclipse开发J2ME手机游戏入门讲座(续)

  首先需要指定创建的是什么项目,展开J2ME项目,选中J2ME Midlet Suite子项后进入下一步。该向导页(如下所示)用来设置项目名称和项目存放路径。一般取缺省路径即可,项目名称自然是经典的"HelloWorld"了。设置完毕后继续下一步的设置。

用Eclipse开发J2ME手机游戏入门讲座(续)

用Eclipse开发J2ME手机游戏入门讲座(续)

用Eclipse开发J2ME手机游戏入门讲座(续)

  此向导页需要对应用程序所支持的MIDP版本进行指定。如果考虑兼容性的话可以选择J2ME Wireless Toolkit 2.1 MIDP 1.0 platform。当然也可以选择MIDP 2.0,但是目前支持MIDP 2.0的手机毕竟还是少数。点击下一步对Java构建设置进行定义,通常取默认值就可以了。点击完成按钮后EclipseMe将会自动设置好项目的编辑及运行环境。可以在导航器视图中点击HelloWorld.jad项,在右侧编辑视图中将可以查看EclipseMe生成的项目结构:

用Eclipse开发J2ME手机游戏入门讲座(续)

        创建J2ME应用程序

         用Eclipse开发J2ME手机游戏入门讲座(续)

  刚才创建的是MIDlet Suite,一般也称作MIDlet应用程序套件,可以包含一个或多个MIDlet,只是在发布时是以MIDlet Suite为单位进行。实质性的工作都是在MIDlet中完成的。因此,需要继续添加MIDlet到项目。在导航器上点击鼠标右键,从弹出菜单中选择"新建"、"其他"菜单项启动上图所示对话框,选择J2ME下的J2ME Midlet子项后进入下一步:

           用Eclipse开发J2ME手机游戏入门讲座(续)

  这里需要指定包(也可以取缺省值)和名称,点击完成后EclipseMe将自动生成框架代码。可以添加必要的功能代码(阴影部分)到其中,以达到"Hello World"字符显示的目的。   

package demo;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class HelloWorldMIDlet extends MIDlet {
 private TextBox textbox;
 public HelloWorldMIDlet() {
  super();
  textbox = new TextBox("测试程序", "Hello World!", 20, 0);
 }
 protected void startApp() throws MIDletStateChangeException {
  Display.getDisplay(this).setCurrent(textbox);
 }
 protected void pauseApp() {
 }
 protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
 }
}


  在添加上述功能代码后会发现在前面有错误图标出现,这是由于没有导入相应的包所致。这有点类似于C++语言中缺少所引用的头文件。与C++需要手工添加对头文件的引用不同,在Eclipse中可以点击"源代码"菜单下的"组织导入"菜单项,EclipseMe将自动添加需要的包到工程:

import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.TextBox;


  运行HelloWorld

用Eclipse开发J2ME手机游戏入门讲座(续)

用Eclipse开发J2ME手机游戏入门讲座(续)

用Eclipse开发J2ME手机游戏入门讲座(续)


  代码已经编写完毕。点击"运行"菜单下的"运行……"菜单项以弹出如上图所示配置界面。在左侧配置窗口中鼠标右键点击"Wireless Toolkit Emulator"并选择弹出菜单的"新建"菜单项,在右侧将显示如下所示的运行配置属性页,一般可选缺省设置。也可以在"Emulation"选项卡中对默认设备进行指定。通常用"DefaultClolorPhone"项即可,其模拟的是在彩屏手机上的运行效果。由于目前支持Java的手机一般配置都不是很低,绝大多数也都是彩屏配置,因此"DefaultClolorPhone"选项应该是比较大众的。当然,如何用户需要,也可以设置"DefaultGrayPhone"等其他项目以模拟在单色或其他配置的手机上的运行效果。

  最后,点击运行按钮执行我们刚才创建的第一个J2ME程序,将弹出如下所示的一个彩屏手机图案的窗口。这便是手机模拟器,可以在其上模拟手机的全部按键,功能与真机相同。观察其屏幕,显示的正是刚才编写的J2ME程序所显示的"Hello World"字样。虽然仅仅是几个字符的显示,但却标志着我们已经开始进入J2ME世界。在下一篇文章,将对J2ME程序的真机发布过程进行讲述,完成一个真正手机应用程序的制作和发布。

用Eclipse开发J2ME手机游戏入门讲座(续)


第五讲 J2ME应用程序的仿真机发布

  引言

  在上一篇文章介绍了HelloWorld程序的开发过程,虽然这是一个经典的程序但并不具备任何实质性的功能而且只是在模拟器中仿真运行。经过这么长时间的学习,本文中要向读者在这段时间的学习有所交代,最起码应当让读者能够开发出一个具备简单功能的能够在真机运行的J2ME手机应用程序,也好以此向周围的同学、同事炫耀一番。相信赢得些许羡慕的目光应该不是什么难事。好了,闲话暂且不提,先简单介绍一下本文将要介绍的知识点。

  本文将通过一个简单的J2ME程序"整蛊专家"的开发向读者介绍信息框的显示、命令按钮的添加、通过文本框与用户的交互、对命令按钮的响应以及对所开发应用程序的打包发布等主要内容。最终展现给读者的将是一个能够在真机运行的J2ME手机程序。

  程序的设计

  首先,按照上一篇文章介绍的知识创建J2ME项目Test并添加MIDlet到其中。现在就在EclipseMe生成的框架代码基础上将下面阴影显示的功能代码添加到相应位置:

package demo;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
public class Test extends MIDlet implements CommandListener {
 private TextBox textbox; // Textbox 显示一条消息
 private Display disp; // 引用MIDlet的Display 对象
 private Command cmdExit; // 设定按钮用于退出MIDlet
 private Command cmdOK; // 确定按钮
 private Alert alt; // 信息提示对象
 public Test() {
  super();
  disp = Display.getDisplay(this); // 获得当前MIDlet的Display对象
  cmdExit = new Command("退出", Command.SCREEN, 1); // 新建两个控制按钮
  cmdOK = new Command("阅读", Command.OK, 1);
  textbox = new TextBox("请输入待阅项目序号:", "", 40, 0); // 新建文本框
  textbox.addCommand(cmdExit); // 添加控制按钮
  textbox.addCommand(cmdOK);
  textbox.setCommandListener(this); // 开始侦听命令
 }
 protected void startApp() throws MIDletStateChangeException {
  alt = new Alert("整蛊专家 V1.0");// 开始运行时显示版权信息,新建信息框对象
  // 设置显示字符串
  alt.setString("==== 整蛊专家 V1.0 ====郎锐2004年作版权所有(C) 2004-2005");
  alt.setType(AlertType.INFO); // 设置为普通阅读信息框
  alt.setTimeout(Alert.FOREVER); // 信息窗口在按下DONE键后才能进入下一页面
  disp.setCurrent(alt, textbox); // 显示信息窗口
 }
 protected void pauseApp() {}
 protected void destroyApp(boolean arg0){}
 public void commandAction(Command arg0, Displayable arg1)
 {
  if (arg0 == cmdExit) { // 按下退出键时停止运行
   destroyApp(false);
   notifyDestroyed();
  }
  if (arg0 == cmdOK) { // 按下阅读键后阅读对应信息
   TextBox textbox = (TextBox)arg1; // 得到用户输入的内容
   String sInfo = textbox.getString();
   if (sInfo.equals("1") || sInfo.equals("2") || sInfo.equals("3") || sInfo.equals("4") || sInfo.equals("5")) { // 显示项目1的内容
    // 根据所选项目选择要显示的内容
    if (sInfo.equals("1")) alt.setString("一兄弟脾气甚……");
    if (sInfo.equals("2")) alt.setString("猪的四大愿望……");
    if (sInfo.equals("3")) alt.setString("春风里,百花下……");
    if (sInfo.equals("4")) alt.setString("为什么……");
    if (sInfo.equals("5")) alt.setString("昨夜做了……");
    alt.setTitle("您正在阅读短信" + sInfo); // 设置标题
   }else{
    alt.setString("很抱歉,暂时还没有您选择的项目,请重新输入!");
    alt.setTitle("错误警告"); // 设置标题
   }
   alt.setType(AlertType.INFO); // 设置为普通阅读信息框
   alt.setTimeout(Alert.FOREVER); // 信息窗口在按下DONE键后进入下一页面
   disp.setCurrent(alt, textbox); // 显示信息窗口
  }
 }
}


  在讲述这段代码之前首先介绍一下MIDlet的生命周期:一个MIDlet在其生命周期*有三种状态,分别是暂停、活动和停止。MIDlet被加载后首先是处于暂停状态,在J2ME调用startApp()方法后转入活动状态。通常情况下应用程序是不必考虑如何控制其运行状态的,其状态的切换由手机来决定。例如,在程序运行过程中如果有电话呼入则会自动转入暂停状态而无须在与用户交互后才能做出判断。最后,当用户按下手机的取消键时,MIDlet将进入停止状态。

  在Test类的构造函数中首先得到当前MIDlet的Display对象,以便进行界面显示。随后通过new操作符新建项目将要用到的命令按钮、文本框等高级用户界面类的对象。在创建命令按钮时,可以通过参数指定所要创建的命令按钮种类。在TextBox类方法addCommand()将其添加到文本框后需要继续调用setCommandListener()方法以开始命令的侦听,否则创建出来的命令按钮仅仅是个无法响应任何操作的摆设。由于需要处理按键,因此在这里必须实现CommandListener接口并处理commandAction方法,该方法的具体实现过程稍后在进行介绍。

  为了在程序开始之初启动程序封面,以显示版权信息、软件介绍等简介性质的文字或画面,需要在startApp()方法中添加相应的代码。这里是通过信息框来实现这一功能的。首先新建一Alert对象,并设置标题、内容信息和信息框类型。通常我们更习惯在按键之后再进入下一页面,为了实现这一效果可以在调用setTimeout()方法时指定FOREVER这一属性参数。设置完毕后通过Display的setCurrent()方法指定该信息框为当前显示界面。

  本程序具有用户交互功能,用户可以通过输入要查看短信的序号来阅读不同的短信内容。为实现该功能就要在commandAction()方法中添加代码进行处理。由于本程序添加有两种不同功能的按键,因此首先需要对第一个参数进行检查以区分当前执行的是退出命令还是确定命令。如果按下的是后者,再通过第二个参数得到用户通过键盘在文本框录入的字符并进行检测判断,对于习惯了C++编程的开发人员需要注意,在判断字符变量是否与其他字符相等时不能使用"=="操作符而要使用String的equals()方法进行判断。剩下的工作就是再以信息框将用户需要的短信显示出来即可,具体实现过程与前述方法类似。

用Eclipse开发J2ME手机游戏入门讲座(续)


  Eclipse在代码编写过程中会动态检查错误,在出现错误后,可以将鼠标移到在出错代码左侧的错误图标上双击鼠标,将弹出如上图所示的更改建议,用户可以在其上双击鼠标接受其建议,在右侧浮动窗口显示的代码将自动添加到适当的位置。

  运行程序并打包

  代码编写无误后可以先在PC上的模拟器中运行调试,并对出现的问题进行修改,一切无误后再打包发布。在模拟器的运行过程在上一篇文章已有详细介绍,这里就不再重复。由于程序即将在真机运行,因此最好使用手机厂商提供的J2ME SDK。下图为使用SonyErisson J2ME SDK (WTK 1.0.4)和SonyErission_T630模拟器的运行过程截图:

用Eclipse开发J2ME手机游戏入门讲座(续)

  在程序列表中选中本程序Test,然后按下Lautch键将装载程序并进入软件首页(左2图),按下Done键进入用户交互界面(左3图)通过点击模拟器的数字按键录入要查看的短信序号并按下"阅读"键将显示相应短信内容(左4图)按下Done键后返回到前一页面,可以再次输入其他短信序号继续阅读其他短信的内容,直到按下"退出"键返回到最开始的界面(左1图)。

用Eclipse开发J2ME手机游戏入门讲座(续)

  显然,编写的程序并没有什么问题,可以向真机发布了。在发布时,首先要确保已经添加有对MIDlet的定义。可以在导航器视图中双击"Test.jad"项打开jad编辑器(见上图)。在编辑器下方窗口切换中选择Midlets进入Midlet定义窗体,确保有如上图所示的项目出现,否则添加之。如果需要添加图标的话,可以指定待使用的图标,但一定要预先将图标文件转换成png格式的文件。

用Eclipse开发J2ME手机游戏入门讲座(续)

用Eclipse开发J2ME手机游戏入门讲座(续)

  最后要进行的应用程序打包处理简单的几乎难以置信,只需右击项目并选择上下文菜单的"J2ME"菜单所弹出的"Create Package"菜单项即可(见上图)。EclipseMe将自动在项目存放目录下的deployed文件夹下生成两个文件,分别是Test.jad和Test.jar。只要通过手机上传软件经由数据线、红外口或是蓝牙将Test.jar上传至手机即可。当然,手机必须是支持Java的才行。如果不清楚是否支持,可查阅手机用户手册。

  小结

  到此为止,已经实现了一个真正能够在手机运行的J2ME程序。虽然最后完成的"整蛊专家"程序功能仍然有限,但是读者可以发现我们开发出来的软件与下载得到的各种Java手机程序并没有本质的差别。通过对其开发过程的剖析可以发现J2ME程序的开发并没有原先想象的那么神秘与高深。只要投入更多的精力和创意,不难写出功能更强大、界面更美观的J2ME程序。目前做到的是J2ME程序的突破,今后需要做的是不断的提高。在下一篇文章,也就是本系列文章的最后一篇文章,将在此基础上实现一个图形化的手机游戏程序。

第六讲 制作图形化手机游戏

  引言

  现在的手机作为一种娱乐性的电子通信设备,早已超出原先的通话、短信息等基本通信功能,越来越多的娱乐、休闲性软件如手机游戏、电子书、音乐编辑、拍照与图象处理等也都流行于当今各种品牌的手机。其中,游戏软件占有相当大的比重。既然我们已经掌握了手机软件的开发过程,为什么不自己开发一个个性化的手机游戏呢?本文将介绍一个简单的图象化手机游戏--"花皮猫大战流氓兔"的制作过程。花皮猫自然是笔者养的爱猫了,感兴趣的读者也完全可以让自己喜欢的阿猫阿狗担当游戏中的主角,充分展示DIY的魅力!

  游戏的设计

  手机游戏的开发首先需要规划好整体流程和具体的游戏规则(或游戏剧本),然后才能根据此剧本进行具体的编码实现。受文章篇幅限制,本游戏剧本设计不能太复杂。首先将游戏定位为人机对弈类游戏,程序运行开始首先显示本游戏的封面画面,停留几秒后自动转入角色选择画面,在玩家选择某一角色后开始游戏。游戏开始时随机决定哪一方先行。人机分别在3乘3大小的棋盘网格中交替落子(双方棋子图案是有区别的),而且只允许在没有落过子的空网格中下子。只要有一方所落棋子在横、竖、斜任何一方向上的总数达到三颗即获胜。如棋盘被填满时双方均未在上述方向达到三颗棋子则该局为平局。无论结果如何,在每局结束后均显示当局胜负结果与总比分。玩家可以选择退出或是重新开始新的一局。以上便是本游戏的主体框架和基本游戏规则,随后进行的编码工作便以此为依据。

  游戏框架的搭建

用Eclipse开发J2ME手机游戏入门讲座(续)
图1

  首先建立项目并新建一Midlet TicTacToe加入其中,继续添加ChoosePieceScreen、GameScreen和Game三个类到项目。作为一款游戏,如果仍拿文字来作软件封面显得也太不专业了。如果要在J2ME程序中使用图片,必须预先将其转换为png格式图片然后在项目上点击鼠标右键,从新建菜单下选择文件菜单项将弹出如上所示对话框。刚开始下半部分是隐藏的,需要通过点击高级按钮将其显示出来。选中链接至文件系统中的文件并通过浏览对话框指定要添加的图片路径。最后在文件名一栏输入图片的文件名并点击完成,将图片添加到项目。下面只须在startApp()中通过如下代码装载图片并通过信息框将其显示出来即可:

Image logo = null;
try {
 logo = Image.createImage("/logo.png");
}catch (IOException e) {}
Alert splashScreen = new Alert(null, "郎锐2004年作/n版权所有(c)/n2004--2005", logo, AlertType.INFO);
splashScreen.setTimeout(4000); // 延迟4秒

用Eclipse开发J2ME手机游戏入门讲座(续)用Eclipse开发J2ME手机游戏入门讲座(续)用Eclipse开发J2ME手机游戏入门讲座(续)用Eclipse开发J2ME手机游戏入门讲座(续)
图2 图3 图4 图5

  在持续显示图2四秒后进入角色选择界面(图3):

choosePieceScreen = new ChoosePieceScreen(this);
Display.getDisplay(this).setCurrent(splashScreen, choosePieceScreen);

  此任务在ChoosePieceScreen类中实现,主要的功能有对角色图标的装载显示、对选定角色的确认等。在其构造函数中首先指定当前界面为列表选择方式,然后通过append()将装载的图象与相应的列表文字建立关联。最后,为了响应用户的输入选择还必须调用setCommandListener()来检测按键事件的发生,并在commandAction()方法中实现对选定角色的确认:

super("请选择:", List.IMPLICIT); // 设置列表选择
this.midlet = midlet;
append(CAT_TEXT, loadImage("/cat.png")); // 添加图象选项到列表
append(RABBIT_TEXT, loadImage("/rabbit.png"));
setCommandListener(this); // 侦听按键响应
……
public void commandAction(Command arg0, Displayable arg1) {
 if (arg0 == List.SELECT_COMMAND){
  // 检测是否为列表按键响应
  // 检测用户选中的选项
  boolean isPlayerCat = getString(getSelectedIndex()).equals(CAT_TEXT);     
  midlet.choosePieceScreenDone(isPlayerCat); // 进入游戏画面
 }
}

  这里是通过检测用户选择的列表项文字来判断玩家选择的是花皮猫还是流氓兔并通过变量isPlayerCat来标识,在choosePieceScreenDone()方法中新建一个GameScreen对象并将其作为当前显示界面来开始一局新的游戏。GameScreen类负责游戏界面的绘制,如对棋盘和双方棋子的绘制以及对光标移动的处理等工作。

  游戏界面编程

  对弈游戏最主要的界面就是棋盘与棋子的绘制。这首先要根据屏幕大小计算棋盘网格间距和棋子的大小:

screenWidth = getWidth();// 获取屏幕大小
screenHeight = getHeight();
if (screenWidth > screenHeight) {// 计算网格大小
 boardCellSize = (screenHeight - 2) / 3;
 boardLeft = (screenWidth - (boardCellSize * 3)) / 2;
 boardTop = 1;
}else{
 boardCellSize = (screenWidth - 2) / 3;
 boardLeft = 1;
 boardTop = (screenHeight - boardCellSize * 3) / 2;
}

  绘制棋盘时,首先用背景色清空整个画布然后再分别按行列绘制出黑色网格即可:

g.setColor(WHITE);
g.fillRect(0, 0, screenWidth, screenHeight);
g.setColor(BLACK);
for (int i = 0; i < 4;i++) {
 g.fillRect(boardLeft, boardCellSize*i+boardTop,(boardCellSize*3)+2,2);
 g.fillRect(boardCellSize * i + boardLeft, boardTop, 2, boardCellSize * 3);
}

  棋子的绘制可以通过在指定位置显示装载的图象来实现。例如,对于花皮猫棋子的绘制可按如下代码先装载预先准备好的图象(大小须与网格相匹配)然后再调用drawImage方法在指定位置绘制。对于流氓兔棋子的绘制只需更改待装载的图象即可:

private void drawCat(Graphics g, int x, int y) {
 Image image = null;
 try {// 装载图象
  image = Image.createImage("/cat.png");
 }catch (Exception e) {}
 g.drawImage(image, x + 1, y + 1, 0); // 在指定位置绘制图象
}

  至于对移动光标的处理,可以先在将要移动到的网格内侧绘制一个新的、四边与棋盘网格紧密相连的黑色矩形框,然后再在原网格位置用原网格背景进行重绘以擦除上次绘制的光标痕迹。在擦除旧光标痕迹时首先需要判断该位置是空白还是绘制有棋子图案,并根据判断结果绘制白色矩形或是重新装载当前显示的棋子图象。图4给出了几个回合后的游戏截图,只要游戏没有结束,上述绘制模块将会多次反复调用执行。如果程序的智能控制部分判断出游戏已经结束并给出胜负结果,则不再显示棋盘界面而是通过下面这段代码以特定的字体在白色画布上绘制出当前战绩(如图5所示)。

Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM); // 设置字体
int strHeight = font.getHeight();
int statusMsgWidth = font.stringWidth(statusMsg);
int tallyMsgWidth = font.stringWidth(tallyMsg);
int strWidth = tallyMsgWidth;
if (statusMsgWidth > tallyMsgWidth)
strWidth = statusMsgWidth;
int x = (screenWidth - strWidth) / 2; // 计算字符绘制位置
x = x < 0 ? 0 : x;
int y = (screenHeight - 2 * strHeight) / 2;
y = y < 0 ? 0 : y;
g.setColor(WHITE); // 白色清空画布
g.fillRect(0, 0, screenWidth, screenHeight);
g.setColor(BLACK); // 黑色显示信息
g.drawString(statusMsg, x, y, (Graphics.TOP | Graphics.LEFT));
g.drawString(tallyMsg, x, (y + 1 + strHeight), (Graphics.TOP | Graphics.LEFT));

  在显示此界面时,如果用户按下退出或开始键,则在commandAction方法中将通过如下代码分别执行程序退出处理或是重新开始下一局新的游戏:

if (arg0 == exitCommand) // 退出
 midlet.quit();
else if (arg0 == newGameCommand) // 开始游戏
 initialize();

  人工智能的实现

  如果说前面介绍的框架是骨骼,界面是皮肉的话,那么接下来将要介绍的人工智能部分则可以说是整个程序的灵魂了。它将进行对弈双方落子的合法性检测、计算机行棋的智能计算、游戏结束检测以及对胜负结果的判定等工作。以上这些都需要有合理的设计才能实现较高的游戏运行效率。考虑到游戏规则始终是围绕双方棋子的排列形状来进行的,因此可以把棋盘网格作为主要因素进行设计。按从左到右,从上到下的次序从0开始依次对棋盘的9个网格进行编号,可以得出如下几组获胜条件:0,1,2;3,4,5;6,7,8;0,3,6;1,4,7;2,5,8;0,4,8;2,4,6。只要有一方有三颗棋子的位置符合其中任何一组即可认定该方获胜(读者可以在纸上验证一下)。在程序实现过程中以WINS数组记录上述几种获胜条件,并在每一次行棋完毕后进行比对,以判断游戏是否有获胜方产生。限于篇幅,下面主要对计算机行棋思路的人工智能设计进行介绍。

  首先明确计算机的对弈目的:获胜,如果暂时无法获胜则阻止选手获胜,如果双方都暂时无法获胜则可以下一些"随手棋"。在计算出合适的下子位置后将其添加到己方的行棋记录(打谱)以备后用。由此可以写出如下代码:

int move = getWinningComputerMove();//如能立即获胜则在获胜位置下子
if (move == -1) {
 //如选手即将获胜则在选手将获胜的位置下子
 move = getRequiredBlockingComputerMove();
 if (move == -1) // 如双方均暂时无法获胜则下随手棋
  move = getRandomComputerMove();
}
computerState |= bit(move); // 当前计算机占用的所有位置

  其中,getWinningComputerMove方法通过对所有可能下子位置(即尚未落子的网格)的枚举,智能判断计算机下一步走到哪里才能获胜:

int move = -1;
for (int i = 0; i < 9;++i) {
 if (isFree(i) && isWin(computerState | bit(i))) {
  move = i; // 找到获胜位置时中断
  break;
 }
}

  如果循环完毕仍没有找到获胜位置则表示目前己方暂无法获胜,需要进一步调用getRequiredBlockingComputerMove方法来计算下一回合对方有无获胜的可能,其实现代码与getWinningComputerMove完全类似,只是以选手的行棋记录playerState替代计算机的行棋记录computerState而已。以上寥寥数行代码即构成了计算机对弈算法的人工智能核心部分,显然人工智能在实现上并没有想象的那么复杂与困难。

  小结

  通过本系列文章的介绍,陆续将J2ME手机应用程序的一般开发过程向读者作了一个较为系统和全面的介绍。尤其是本篇对图形化手机游戏的介绍相信一定对读者有不同程度的启发作用,而且本文所述程序框架完全是通用的,读者只需在此基础之上重新设计游戏剧本即可实现类似的手机游戏如"华容道"、"俄罗斯方块"等。本系列文章开发环境为:

  Windows 2000 Professional + SP4;
  Java2SDK 1.5.0;
  J2ME Wireless ToolKits 2.1;
  SonyErisson J2ME SDK(WTK 1.0.4);
  SonyErisson T628;
  Eclipse 3.0.1-win32;
  EclipseMe 0.5.5;
  NLpack-eclipse-SDK-3.0.x-win32

 

用Eclipse开发J2ME手机游戏入门讲座(续)



  刚才创建的是MIDlet Suite,一般也称作MIDlet应用程序套件,可以包含一个或多个MIDlet,只是在发布时是以MIDlet Suite为单位进行。实质性的工作都是在MIDlet中完成的。因此,需要继续添加MIDlet到项目。在导航器上点击鼠标右键,从弹出菜单中选择"新建"、"其他"菜单项启动上图所示对话框,选择J2ME下的J2ME Midlet子项后进入下一步:

           

用Eclipse开发J2ME手机游戏入门讲座(续)



  这里需要指定包(也可以取缺省值)和名称,点击完成后EclipseMe将自动生成框架代码。可以添加必要的功能代码(阴影部分)到其中,以达到"Hello World"字符显示的目的。