J2ME伪高手先锋开讲——扫雷游戏的设计 首先我要装得像高手一样,来假装把系统稍微分析一下。 一般,按照java得开发模式,这种程序一般是分为三个模块来开发。 如下三个: 一个程序运作的主文件,也就是一个midlet的继承; 一个界面的表示类,也就是一个canvas的继承,界面上应该有些菜单,如new、exit 什么的,那就应该要 implements一个 commandListener消息监听类(大家可以把java的消息监听理解为一个线程,一直像倭寇那样对看得顺眼的东西虎视耽耽,当然这里指的是他所能触及到的消息,当收到消息的时候,会调用一个抽象函数public void commandAction(Command c, Displayable d),而这个抽象函数使得我们可以通过对他的实现来处理收到的消息,即消息响应) 最后一个当然就是与界面无关的逻辑单元了,在这里我们定义整个游戏的逻辑,做到逻辑与界面分开。这是我学java的最大收获,呵呵。 首先正式开始第一讲 <扫雷游戏的逻辑> 我的设想是,扫雷的地图一般是一个矩形,因为,圆形屏幕的手机看起来蛮变态的,没有必要迁就他,所以,我用一个a*b的二维数组就完全可以表示整个地图。 有了地图以后地图里面的类容自然就有一部分是表示地雷啦,既然这样,那不如就这样<废话来的,小朋友不要学> /** * 20 标志该位置为地雷 * <=10的数字表示未翻开的方块及周围的地雷数目 * >=10的数字表示已翻开的方块及周围的地雷数目 * */ 表示方法就出来了,逻辑也明朗起来了。 我要将某个块翻开,只要将他加上10就可以了。 Java编程第一步,当然是先要class啊 package games; import java.util.Random; import java.lang.Math; class gamelogic { /**表示一个10*10的棋盘*/ private int[][] pan = new int; private Random random;//一个随机变量,主要作用是用来指定哪些位置为地雷 private int BombNum = 0; //统计地雷总数 /**游戏是否结束*/ private boolean GameOver; 接下来就是要初始化地图了,地图首先要扔一个雷在上面啊,不然怎么叫扫雷呢,扔完了地雷以后接下来当然是遍历一次地图(我们还是很仁慈地,我们得告诉扫雷的同志,某某位置,有多少雷,比如这样:"01、01、12点中方向有地雷,14点钟方向有幺鸡,2点钟方向有东风之类的啊")。 /**初始化数组,生成地图*/ public void InitArray() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { pan[i][j] = 0; } } RandomArray(); CountBomb(); BombNum = Bomb(); } /**统计地雷总数 * @return int 返回地雷总数 */ private int Bomb() { int count = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (pan[i][j] == 20) { count += 1; } } } return count; } /**随机决定地雷的位置*/ private void RandomArray() { int i, j, k; // 先扔15个左右的地雷吧,注意,这里不一定有15个哦,因为随机值可能重复,我不管啦 for (int r = 0; r < 15; r++) { k = java.lang.Math.abs(random.nextInt()) % 64; //random.nextInt(100); i = k / 8; j = k % 8; this.pan[i][j] = 20; //指定该位置为地雷 } } /**统计棋盘上的数据*/ private void CountBomb() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { int count = 0; //当需要检测的单元格本身无地雷的情况下,统计周围的地雷个数 if (pan[i][j] != 20) { if ( (i - 1 >= 0) && (j - 1 >= 0)) { if (pan[i - 1][j - 1] == 20) { count += 1; //检测左上方空格是否是地雷 } } if ( (i - 1 >= 0)) { if (pan[i - 1][j] == 20) { count += 1; //检测上方空格是否为地雷 } } if ( (i - 1 >= 0) && (j + 1 <= 7)) { if (pan[i - 1][j + 1] == 20) { count += 1; //检测右上方是否为地雷 } } if ( (j - 1 >= 0)) { if (pan[i][j - 1] == 20) { count += 1; //检测左边是否为地雷 } } if ( (i >= 0) && (j + 1 <= 7)) { if (pan[i][j + 1] == 20) { count += 1; //右边 } } if ( (j - 1 >= 0) && (i + 1 <= 7)) { if (pan[i + 1][j - 1] == 20) { count += 1; //左下 } } if ( (i + 1 <= 7)) { if (pan[i + 1][j] == 20) { count += 1; //下 } } if ( (j + 1 <= 7) && (i + 1 <= 7)) { if (pan[i + 1][j + 1] == 20) { count += 1; //右下 } } pan[i][j] = count; } } } } /**检测已经被揭开的位置总和 * @return 返回被揭开的数量 */ private int countOpen() { int count = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if (pan[i][j] < 20 && pan[i][j] > 9) { count += 1; } } } return count; } /**检测是否胜利 * @return 是否胜利boolean值 */ public boolean isWin() { // System.out.println(BombNum +""+ countOpen()); if ( (BombNum + countOpen()) == 64) { this.GameOver = true; return true; } else { return false; } } /**选中棋盘上的位置,并翻开 * @param matrix 位置 */ public void openpan(int matrix) { switch (getBomb(matrix)) { case 20: //当选中的位置为地雷,游戏结束 setGameOver(); break; case 0: isNull(matrix); //当选中的位置为空,则翻开周围的地图 break; default: this.isNotNull(matrix); //否则,翻开当前位置,并作上翻开的标记 } } /**当选中的位置为空,则翻开周围的地图 * @param matrix 位置 */ private void isNull(int matrix) { int i, j; i = matrix / 8; j = matrix % 8; if (pan[i][j] < 9) { pan[i][j] += 10; } if ( (i - 1 >= 0) && (j - 1 >= 0)) { //检测左上方空格是否是空 if (pan[i - 1][j - 1] == 0) { isNull( (i - 1) * 8 + (j - 1)); } if (pan[i - 1][j - 1] < 9) { pan[i - 1][j - 1] += 10; } } if ( (i - 1 >= 0)) { //检测上方空格是否为空 if (pan[i - 1][j] == 0) { isNull( (i - 1) * 8 + j); } if (pan[i - 1][j] < 9) { pan[i - 1][j] += 10; } } if ( (i - 1 >= 0) && (j + 1 <= 7)) { //检测右上方是否为空 if (pan[i - 1][j + 1] == 0) { isNull( (i - 1) * 8 + (j + 1)); } if (pan[i - 1][j + 1] < 9) { pan[i - 1][j + 1] += 10;} } if ( (j - 1 >= 0)) { //检测左边是否为空 if (pan[i][j - 1] == 0) { isNull(i * 8 + (j - 1)); } if (pan[i][j - 1] < 9) { pan[i][j - 1] += 10; } } if ( (i >= 0) && (j + 1 <= 7)) { //右边 if (pan[i][j + 1] == 0) { isNull(i * 8 + (j + 1)); } if (pan[i][j + 1] < 9) { pan[i][j + 1] += 10; } } if ( (j - 1 >= 0) && (i + 1 <= 7)) { //左下 if (pan[i + 1][j - 1] == 0) { isNull( (i + 1) * 8 + (j - 1)); } if (pan[i + 1][j - 1] < 9) { pan[i + 1][j - 1] += 10; } } if ( (i + 1 <= 7)) { //下 if (pan[i + 1][j] == 0) { isNull( (i + 1) * 8 + j); } if (pan[i + 1][j] < 9) { pan[i + 1][j] += 10; } } if ( (j + 1 <= 7) && (i + 1 <= 7)) { //右下 if (pan[i + 1][j + 1] == 0) { isNull( (i + 1) * 8 + (j + 1)); } if (pan[i + 1][j + 1] < 9) { pan[i + 1][j + 1] += 10; } } } /**选中棋盘上的位置,并翻开当前位置 * @param matrix 位置 */ private void isNotNull(int matrix) { int i, j; i = matrix / 8; j = matrix % 8; pan[i][j] += 10; } /**取得指定位置的数据 * @param matrix 位置 * @return int 数据 */ public int getBomb(int matrix) { int i, j; i = matrix / 8; j = matrix % 8; return this.pan[i][j]; } /**检测游戏是否结束 * @return boolean 游戏是否结束的状态 */ public boolean isGameOver() { return GameOver; } /**设置游戏结束 */ private void setGameOver() { GameOver = true; } /**开新局*/ public void setNewGame() { this.GameOver = false; } /**指定位置是否被揭开 * @param matrix 位置 * @return boolean 返回是否可以被揭开 */ public boolean isFree(int matrix) { int i, j; i = matrix / 8; j = matrix % 8; return pan[i][j] < 8 || pan[i][j] == 20; } } public void openpan(int matrix) 是整个程序的核心所在,他描述了所有的动作, 1、有可能你踩到屎,踩到屎当然就gameover啦 2、有可能踩到钱,有一大片空地给你玩 3、命好,没有炸死你,继续探索 程序源码: //gamecCanvans.java package games; import java.lang.System.*; import java.util.Random; import java.util.Vector; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; /**游戏动作类*/ class gameCanvas extends Canvas implements CommandListener { /**黑*/ private static final int BLACK = 0x00000000; /**白*/ private static final int WHITE = 0x00FFFFFF; /**红*/ private static final int RED = 0x00FF0000; /**蓝*/ private static final int BLUE = 0x000000FF; /**没有移动的标志*/ private static final int NO_MOVE = -1; /**主窗体类*/ private final control midlet; /**逻辑类*/ private final gamelogic game; /**退出菜单*/ private final Command exitCommand; /**重新开始菜单*/ private final Command newGameCommand; /**随机数*/ private final Random random = new Random(); /**屏幕宽度*/ private int screenWidth; /**屏幕高度*/ private int screenHeight; /**boardCellSize 正方形单元格的大小, * boardTop 棋盘top的位置, * boardLeft 棋盘left位置*/ private int boardCellSize, boardTop, boardLeft; /**preCursorPosition 前一次光标选择的位置,cursorPosition 当前光标选择的位置*/ private int preCursorPosition, cursorPosition; /**用于存储被标记的地雷的位置 */ private Vector BombVector = new Vector(); private boolean isRestart; /**构造器 * @param midlet 主窗体类 */ public gameCanvas(control midlet) { this.midlet = midlet; game = new gamelogic(random); initializeBoard(); /**初始化菜单*/ exitCommand = new Command("退出", Command.EXIT, 1); newGameCommand = new Command("新游戏", Command.SCREEN, 2); addCommand(exitCommand); addCommand(newGameCommand); setCommandListener(this); /**开始游戏*/ initialize(); } /**添加一个地雷位置标记 *@param matrix 位置标记 */ private void addBomb(int matrix) { BombVector.addElement(Integer.toString(matrix)); } /**删除一个地雷位置标记 *@param matrix 位置标记 */ private void delBomb(int matrix) { BombVector.removeElement(Integer.toString(matrix)); } /**搜索该位置是否被标记 * @param matrix 位置标记 * @return boolean 该位置是否被记录,false为被记录 */ private boolean searchBomb(int matrix) { return BombVector.indexOf(Integer.toString(matrix)) == -1; //-1表示没有找到该位置的信息 } /**初始化屏幕,取得棋盘的初始位置*/ private void initializeBoard() { screenWidth = getWidth(); //取得屏幕宽度 screenHeight = getHeight(); //取得屏幕高度 if (screenWidth > screenHeight) { boardCellSize = (screenHeight - 1) / 8; boardLeft = (screenWidth - (boardCellSize * 8)) / 2; boardTop = 1; } else { boardCellSize = (screenWidth - 1) / 8; boardLeft = 1; boardTop = (screenHeight - boardCellSize * 8) / 2; } } /** 初始化游戏和屏幕. 使游戏重新启动*/ private void initialize() { preCursorPosition = cursorPosition = 0; game.setNewGame(); game.InitArray(); isRestart = true; BombVector.removeAllElements(); repaint(); } /**重画canvas * @param g 重画的Graphics对象*/ public void paint(Graphics g) { game.isWin(); if (!game.isGameOver()) { paintGame(g); } else { paintGameOver(g); } } 作者:未知 转贴自:everenter.com

评论