作者:雷神QQ:38929568
QQ群:28048051(满)28047782(将满)
新建一个j2me midlet工程
在src里添加如下连个类
Minesweeper.java
cGame.java
详尽注释,方便初学者!
工程文件如附件所示,地址如下:扫雷(不含线程)
程序运行如图
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Minesweeper.java
- //
- // Project: Minesweeper
- // Author(s): Gao Lei
- // Create: 2007-10-08
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- import javax.microedition.midlet.*; //j2me MIDlet程序必须继承MIDlet类,所以要引入此包
- import javax.microedition.lcdui.*; //Display这个类所在包
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- public class Minesweeper extends MIDlet
- ...{
- static Minesweeper s_midlet; //MIDlet类的静态对象,方便实用 MIDlet类方法
- static Display s_display = null;//用来显示 Canvas
- static cGame s_game = null; //Canvas类对象,主要实现游戏的类
- public Minesweeper()
- ...{
- s_midlet = this;
- }
- /** *//**
- * 程序开始 系统会调用这个函数
- * 也有些手机 可以把程序初始化部分放到构造函数里,这连个地方应视手机的不同而定!
- */
- public void startApp()
- ...{
- if (s_display == null)
- ...{
- s_display = Display.getDisplay(this);//创建Display对象,参数是MIDlet类对象,也就是我们当前写的这个Minesweeper类
- }
- if (s_game == null)
- ...{
- s_game = new cGame(); //创建 Canvas对象
- s_display.setCurrent(s_game); //把Canvas对象设置成当前显示
- }
- else
- ...{
- s_display.setCurrent(s_game);
- }
- }
- /** *//**
- * 程序暂停 系统会自动调用这个函数,不是所有手机都支持,
- * 手机在接到中断,如 来电,来短信时候会调用这个函数,这个函数 通常是空的!
- */
- public void pauseApp()
- ...{
- }
- /** *//**
- * 程序关闭 系统会调用这个函数,如果希望关闭程序的时候保存数据,可在这个函数里添加保存数据的方法
- * 比如游戏进行中,按了关机键,程序就会调用这个函数,也可以在程序中调用这个函数来结束游戏!
- */
- public void destroyApp(boolean unconditional)
- ...{
- notifyDestroyed();
- }
- }
cGame.java
代码如下
- ////////////////////////////////////////////////////////////////////////////////
- //
- // cGame.java
- //
- // Project: Minesweeper
- // Author(s): Gao Lei
- // Create: 2007-10-08
- ////////////////////////////////////////////////////////////////////////////////
- import java.util.Random; //得到 随机函数
- import javax.microedition.lcdui.*; //写界面所需要的包
- ////////////////////////////////////////////////////////////////////////////////
- class cGame extends Canvas
- ...{
- public static int s_width = 0; //屏幕尺寸 宽
- public static int s_height= 0; //屏幕尺寸 高
- public static Random rand; //随机数对象
- private int UP = 1; //定义键值 上
- private int DOWN = 2; //定义键值 下
- private int LEFT = 3; //定义键值 左
- private int RIGHT = 4; //定义键值 右
- private int FILE = 5; //定义键值 中间确认键
- private int map_x = 10; // 15 //雷区的 行数
- private int map_y = 10; // 12 //雷区的 列数
- private int map_w = 20; //一个雷区的格子的宽度
- private int map_h = 20; //一个雷区的格子的高度
- private int key_x = map_x / 2; //游戏初始时 光标所在雷区的格子位置
- private int key_y = map_y / 2; //游戏初始时 光标所在雷区的格子位置
- private int mine_num= 10; //雷区的雷数 不应该大于雷区的格子总数
- private int[][] map; //雷区的地图数组 >=10 为雷, <10 为周围的雷数, 0位附近没有雷
- private boolean[][] map_show; //雷区的地图数组 是否显示 该位置的雷数
- private boolean isGameOver = false; //游戏是否结束
- cGame()
- ...{
- setFullScreenMode(true); //设置游戏为全屏幕模式,该函数只能在支持midp2.0的手机上使用
- s_width = getWidth(); //得到屏幕尺寸 宽
- s_height= getHeight(); //得到屏幕尺寸 高
- rePlay(); //游戏初始化//重新游戏
- }
- /** *//**
- * 系统自动调用该绘图函数,并传入绘图设备g,通过该设备,我们可以绘制如直线,矩形快,字符串,图片等,
- */
- public void paint(Graphics g)
- ...{
- g.setClip(0, 0, s_width, s_height); //设置参数描述的区域为操作区
- g.setColor(0x000000); //设置颜色为 黑色, 三个16进制数表示,RGB,如0x00ff00 为绿色
- g.fillRect(0, 0, s_width, s_height); //绘制一个实心矩形区域
- g.setColor(0xFFFFFF); //设置颜色为 白色
- //绘制雷区
- for( int i=0; i<=map_y; i++ ) // ||| //画 map_y+1条竖线
- ...{
- g.drawLine(i*map_w, 0, i*map_w, map_h*map_x);
- }
- for( int i=0; i<=map_x; i++ ) // --- //画 map_x+1条横线
- ...{
- g.drawLine(0, i*map_h, map_y*map_w, i*map_h);
- }
- g.setColor(0xFF0000); //设置颜色 红
- g.drawRect(key_x*map_w+1, key_y*map_h+1, map_w-2, map_h-2); //绘制一个空心矩形框
- for( int i=0; i<map_x; i++ )
- ...{
- for( int j=0; j<map_y; j++ )
- ...{
- if( map_show[i][j] ) //遍历地图数组 看该位置的雷数 是否应该显示
- g.drawString(""+map[i][j], j*map_h+5, i*map_w+5, 0); //显示该位置的雷数
- }
- }
- if( isGameOver ) //如果游戏 结束
- g.drawString("GAME OVER", s_width/2, s_height, g.HCENTER|g.BOTTOM); //显示 GAME OVER
- }
- /** *//**
- * 系统自动调用该函数,当有键盘事件发生为按下某键,参数key为按下键的键值
- */
- public void keyPressed(int key)
- ...{
- key = Math.abs(key);
- System.out.println("key="+key);
- //上下左右 为移动光标事件,只需要调整光标位置即可,但需要做边界判断
- if( key == this.UP )
- ...{
- key_y--;
- if( key_y<0 )
- key_y = 0;
- }
- else if( key == this.DOWN )
- ...{
- key_y++;
- if( key_y>=map_x-1 )
- key_y =map_x-1;
- }
- else if( key == this.LEFT )
- ...{
- key_x--;
- if( key_x<0 )
- key_x = 0;
- }
- else if( key == this.RIGHT )
- ...{
- key_x++;
- if( key_x>=map_y-1 )
- key_x =map_y-1;
- }
- else if( key==FILE || key==KEY_NUM5)//按下的为确定键
- ...{
- if( !isGameOver ) //如果游戏没结束 //结束了就不做确认键操作了
- ...{
- showMap( key_y, key_x ); //显示该位置的雷数
- if( map[key_y][key_x] >=10 )//如果雷数>=10 该位置是雷,
- isGameOver = true; //游戏结束
- }
- }
- else if( key == this.KEY_NUM0 ) //当按下 数字键 0
- ...{
- rePlay(); //重新开始游戏
- }
- /** *//**
- * 重新执行 paint() 但该函数是立刻返回,也就是说他不会等待paint()执行完毕就返回了,
- * 如果 需要 paint()执行完毕才返回,可以使用serviceRepaints(),也可以两个都是用,但
- * repaint()应该在serviceRepaints()之前.
- */
- this.repaint(); //本例为键盘事件驱动,刷新函数也就是每次按下键盘才作
- }
- //该函数是一个递归函数,把当前位置设置成显示,并判断当前位置雷数是否为0个
- //如果是0个雷,那么它周围的8个格子都要再作一次showMap
- void showMap(int x, int y)
- ...{
- if( map_show[x][y] )
- return;
- else
- map_show[x][y] = true;
- if( map[x][y] == 0 )
- ...{
- if( x-1 >= 0 )
- ...{
- showMap( x-1, y );
- if( y-1 >= 0) showMap( x-1, y-1 );
- if( y+1 < map_y) showMap( x-1, y+1 );
- }
- if( y-1 >= 0) showMap( x , y-1 );
- if( y+1 < map_y) showMap( x , y+1 );
- if( x+1 < map_x )
- ...{
- showMap( x+1, y );
- if( y-1 >= 0) showMap( x+1, y-1 );
- if( y+1 < map_y) showMap( x+1, y+1 );
- }
- }
- }
- //重新 开始 游戏
- public void rePlay()
- ...{
- isGameOver = false;
- map = new int [map_x][map_y];
- map_show = new boolean [map_x][map_y];
- rand = new Random( System.currentTimeMillis() ); //用事件作随机数种子的随机数
- //布雷
- for(int i=0; i<mine_num; i++) //随机mine_num个雷的位置
- ...{
- int x = rand.nextInt( map_x ); //得到 随机数 雷格子的x方向位置
- int y = rand.nextInt( map_y ); //得到 随机数 雷格子的y方向位置
- if( map[x][y] >= 10) //如果该位置已经是雷了,就要重新布雷
- ...{
- i--;
- continue;
- }
- map[x][y] = 10; //否则 将该位置 设定为雷
- //并在该雷的周围 的雷数都作+1操作
- //以下判断为 边角判断,防止访问数组越界
- if( x-1 >= 0 )
- ...{
- map[x-1][y ] += 1;
- if( y-1 >= 0) map[x-1][y-1] += 1;
- if( y+1 < map_y) map[x-1][y+1] += 1;
- }
- if( y-1 >= 0) map[x ][y-1] += 1;
- if( y+1 < map_y) map[x ][y+1] += 1;
- if( x+1 < map_x )
- ...{
- map[x+1][y ] += 1;
- if( y-1 >= 0) map[x+1][y-1] += 1;
- if( y+1 < map_y) map[x+1][y+1] += 1;
- }
- }
- }
- }
这样200行的小游戏就做好了!可以玩了, 不过,这个还没有完成,没有标志是雷,和全部找到雷的成功完成游戏界面,只是基本的布雷,挖雷,在下一篇,我们将完善这个小游戏!
附件:http://down.51cto.com/data/2358276
本文转自 kome2000 51CTO博客,原文链接:http://blog.51cto.com/kome2000/578476