作者:雷神QQ:38929568
QQ群:28048051(满)28047782(将满)
新建一个j2me midlet工程
在src里添加如下连个类
Minesweeper.java
cGame.java
详尽注释,方便初学者!
工程文件已经打包上传到csdn,地址如下
download.csdn.net/user/kome2000/
//////////////////////////////////////////////////////////////////////////////////////////
//
// 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();
}
}
//
// 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;
}
}
}
}
//
// 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行的小游戏就做好了!可以玩了, 不过,这个还没有完成,没有标志是雷,和全部找到雷的成功完成游戏界面,只是基本的布雷,挖雷,在下一篇,我们将完善这个小游戏!
扫雷(2)是在扫雷(1)的基础上增加 完善了部分代码基本逻辑不变!
使得游戏更好玩了,代码两也增加到400行,比较适合初学者,可读性强,有详尽的代码注释。
数字键1标红旗,不确定,取消标记。数字键3显示/不显示 游戏信息!
方向键,数字键2468,控制光标上下左右移动!
工程文件已经打包上传到csdn,地址如下
download.csdn.net/user/kome2000/
Minesweeper.java
这个类是游戏入口类,基本不做修改!而且每个游戏的这个midlet类都差不太多!
/////////////////////////////////////////////////////////////////////////////////////////
//
// 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();
}
}
//
// 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
{
//游戏状态
private static final int STATEPLAY = 0; //游戏中
private static final int STATELOST = 1; //游戏失败
private static final int STATEWIN = 2; //游戏胜利
//格子状态
private static final int MINE_OFF_SHOW = 0; //不显示格子中雷的数
private static final int MINE_ON_SHOW = 1; //显示格子中雷的数
private static final int MINE_ASK = 9; //设置问号
private static final int MINE_FLAG = 10; //设置红旗
private static final int MINE_GUESS_ERR = 11; //显示猜错了雷
//定义键值
private static final int KEY_UP = 1; //上
private static final int KEY_DOWN = 2; //下
private static final int KEY_LEFT = 3; //左
private static final int KEY_RIGHT = 4; //右
private static final int KEY_FIRE = 5; //中间确认键
public static Random rand; //随机数对象
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 flagNum = mine_num; //剩余红旗数
private int rightNum= 0; //猜对的雷数
private int[][] map; //雷区的地图数组 >=10 为雷, <10 为周围的雷数, 0位附近没有雷
private int[][] map_show; //雷区的地图数组是否显示该位置的雷数//1显示//0不显示//9问号//10红旗
private int gameState = STATEPLAY; //游戏状态
private int s_width = 0; //屏幕尺寸 宽
private int s_height = 0; //屏幕尺寸 高
private int addMine = 0; //重新开始后雷数增加的个数
private boolean isShowInfo = false; //是否显示游戏信息
private String strFlagNum = "红旗数";
private String strMineNum = "正确率";
private String[] gameInfo = {"游戏中","游戏失败 按0重新开始","游戏胜利 按0进入多雷区"};
private Font font = Font.getFont( Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE );
cGame()
{
setFullScreenMode(true); //设置游戏为全屏幕模式,该函数只能在支持midp2.0的手机上使用
s_width = getWidth(); //得到屏幕尺寸 宽
s_height= getHeight(); //得到屏幕尺寸 高
rePlay( 0 ); //游戏初始化//重新游戏
}
/**
* 系统自动调用该绘图函数,并传入绘图设备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);
}
for( int i=0; i<map_x; i++ )
{
for( int j=0; j<map_y; j++ )
{
if( map_show[i][j] == MINE_ON_SHOW ) //遍历地图数组 看该位置的雷数 是否应该显示
{
if( map[i][j]==0 ) //周围没有雷
{
g.setColor(0x666666);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
}
else if(map[i][j]<10) //显示周围的雷数
{
g.setColor(0x666666);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
g.setColor(0x00ff00);
g.drawString(""+map[i][j], j*map_h+8, i*map_w+4, g.LEFT|g.TOP); //显示该位置的雷数
}
else //踩到雷了
{
g.setColor(0xff0000);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
// g.drawString(""+map[i][j], j*map_h+5, i*map_w+4, g.LEFT|g.TOP); //显示该位置是雷
}
}
else if( map_show[i][j] == MINE_FLAG ) //显示红旗
{
paintFlag( g, j, i );
}
else if( map_show[i][j] == MINE_ASK ) //显示问号
{
paintInterrogation( g, j, i );
}
else if( map_show[i][j] == MINE_GUESS_ERR )//显示猜错了
{
g.setColor(0x666666);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
paintGuessErr( g, j, i );
}
}
}
g.setColor(0xFF0000); //设置颜色 红
g.drawRect(key_x*map_w+1, key_y*map_h+1, map_w-2, map_h-2); //绘制一个空心矩形框//为光标
g.drawRect(key_x*map_w+2, key_y*map_h+2, map_w-4, map_h-4); //绘制一个空心矩形框//为光标
if( isShowInfo || gameState != STATEPLAY ) //如果游戏 结束
{
g.setFont( font );
g.drawString( strFlagNum+":"+flagNum, 20, s_height-60, g.LEFT|g.TOP ); //显示剩余旗数
g.drawString( strMineNum+":"+rightNum +"/"+ mine_num, 20, s_height-45, g.LEFT|g.TOP ); //显示正确率 猜对雷数/总雷数
g.drawString( gameInfo[ gameState ], 20, s_height-30, g.LEFT|g.TOP ); //显示游戏状态
}
}
/**
* 系统自动调用该函数,当有键盘事件发生为按下某键,参数key为按下键的键值
*/
public void keyPressed(int key)
{
key = Math.abs(key);
System.out.println("key="+key);
//上下左右 为移动光标事件,只需要调整光标位置即可,但需要做边界判断
switch( key )
{
case KEY_NUM2:
case KEY_UP:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_y--;
if( key_y<0 )
key_y = map_x-1;
}
break;
case KEY_NUM8:
case KEY_DOWN:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_y++;
key_y %=map_x;
}
break;
case KEY_NUM4:
case KEY_LEFT:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_x--;
if( key_x<0 )
key_x = map_y-1;
}
break;
case KEY_NUM6:
case KEY_RIGHT:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_x++;
key_x %=map_y;
}
break;
case KEY_FIRE:
case KEY_NUM5:
if( gameState == STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
{
if( map_show[key_y][key_x] == MINE_FLAG )
break;
showMap( key_y, key_x ); //显示该位置的雷数
if( map[key_y][key_x] >=10 )//如果雷数>=10 该位置是雷,
{
isWinGame();
addMine = 0;
isShowInfo = true;
gameState = STATELOST; //游戏失败
}
}
break;
case KEY_NUM1: //设置红旗//问号//取消
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
switch( map_show[key_y][key_x] )
{
case MINE_OFF_SHOW:
map_show[key_y][key_x] = MINE_FLAG;
flagNum--;
if( flagNum == 0 )
{
if( isWinGame() )
{
addMine = 5;
isShowInfo = true;
gameState = STATEWIN;
}
else
{
addMine = 0;
isShowInfo = true;
gameState = STATELOST;
}
}
break;
case MINE_FLAG:
flagNum++;
map_show[key_y][key_x] = MINE_ASK;
break;
case MINE_ASK:
map_show[key_y][key_x] = MINE_OFF_SHOW;
break;
}
break;
case KEY_NUM3: //是否显示游戏信息
isShowInfo = !isShowInfo;
break;
case KEY_NUM0: //当按下 数字键 0
rePlay( addMine ); //重新开始游戏
break;
}
/**
* 重新执行 paint() 但该函数是立刻返回,也就是说他不会等待paint()执行完毕就返回了,
* 如果 需要 paint()执行完毕才返回,可以使用serviceRepaints(),也可以两个都是用,但
* repaint()应该在serviceRepaints()之前.
*/
this.repaint(); //本例为键盘事件驱动,刷新函数也就是每次按下键盘才作
}
boolean isWinGame()
{
boolean isWin = true;
for( int i=0; i<map_x; i++ )
{
for( int j=0; j<map_y; j++ )
{
if( map_show[i][j] == MINE_FLAG ) //显示红旗
{
if( map[i][j] < 10 ) //地雷猜错了
{
map_show[i][j] = MINE_GUESS_ERR;
isWin = false;
}
else
{
rightNum ++;
}
}
}
}
return isWin; //群不红旗都插对了 才能通关
}
void paintFlag( Graphics g, int key_x, int key_y )
{
int x = key_x*map_h+9;
int y = key_y*map_w+5;
g.setColor( 0xFF0000 );
g.drawLine( x , y , x , y+11 ); // |
g.drawLine( x-2, y+11, x+3, y+11 ); // -
g.drawLine( x , y , x+5, y+ 2 ); // >
g.drawLine( x+5, y+2 , x , y+ 4 ); // >
x += 1;
y += 1;
g.drawLine( x , y , x , y+11 ); // |
g.drawLine( x-5, y+11, x+4, y+11 ); // -
g.drawLine( x , y , x+5, y+ 2 ); // >
g.drawLine( x+5, y+2 , x , y+ 4 ); // >
}
void paintInterrogation( Graphics g, int key_x, int key_y )
{
int x = key_x*map_h+8;
int y = key_y*map_w+5;
g.setColor( 0xFF0000 );
g.drawString("?", x, y, g.LEFT|g.TOP); // ?
}
void paintGuessErr( Graphics g, int key_x, int key_y )
{
int x = key_x*map_h+8;
int y = key_y*map_w+5;
g.setColor( 0xFF0000 );
g.drawString("x", x, y, g.LEFT|g.TOP); // x
}
//该函数是一个递归函数,把当前位置设置成显示,并判断当前位置雷数是否为0个
//如果是0个雷,那么它周围的8个格子都要再作一次showMap
void showMap(int x, int y)
{
if( map_show[x][y] == MINE_FLAG )
return;
if( map_show[x][y] == MINE_ON_SHOW )
return;
else
map_show[x][y] = MINE_ON_SHOW;
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( int add )
{
if( add > 0 )
{
map_x += 1; //雷区的 行数 // 10 - 15
map_y += 1; //雷区的 列数 // 10 - 12
if( map_x >= 15 ) map_x = 15;
if( map_y >= 12 ) map_y = 12;
addMine = 0; //每次增加的雷数
}
else
add = 0;
key_x = map_x / 2; //游戏初始时 光标所在雷区的格子位置
key_y = map_y / 2; //游戏初始时 光标所在雷区的格子位置
mine_num += add; //雷区的雷数 不应该大于雷区的格子总数
if(mine_num >= map_x*map_y/2)
mine_num = map_x*map_y/10; //纠正雷数不能超过雷区的格子数
flagNum = mine_num; //剩余红旗数
rightNum = 0; //猜对的雷数
gameState = STATEPLAY;
map = new int[map_x][map_y];
map_show = new int[map_x][map_y];
rand = new Random( System.currentTimeMillis() ); //用事件作随机数种子的随机数
isShowInfo = false;
//布雷
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;
}
}
}
}
//
// cGame.java
//
// Project: Minesweeper
// Author(s): Gao Lei
// Create: 2007-10-08
////////////////////////////////////////////////////////////////////////////////
import java.util.Random; //得到 随机函数
import javax.microedition.lcdui.*; //写界面所需要的包
////////////////////////////////////////////////////////////////////////////////
class cGame extends Canvas
{
//游戏状态
private static final int STATEPLAY = 0; //游戏中
private static final int STATELOST = 1; //游戏失败
private static final int STATEWIN = 2; //游戏胜利
//格子状态
private static final int MINE_OFF_SHOW = 0; //不显示格子中雷的数
private static final int MINE_ON_SHOW = 1; //显示格子中雷的数
private static final int MINE_ASK = 9; //设置问号
private static final int MINE_FLAG = 10; //设置红旗
private static final int MINE_GUESS_ERR = 11; //显示猜错了雷
//定义键值
private static final int KEY_UP = 1; //上
private static final int KEY_DOWN = 2; //下
private static final int KEY_LEFT = 3; //左
private static final int KEY_RIGHT = 4; //右
private static final int KEY_FIRE = 5; //中间确认键
public static Random rand; //随机数对象
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 flagNum = mine_num; //剩余红旗数
private int rightNum= 0; //猜对的雷数
private int[][] map; //雷区的地图数组 >=10 为雷, <10 为周围的雷数, 0位附近没有雷
private int[][] map_show; //雷区的地图数组是否显示该位置的雷数//1显示//0不显示//9问号//10红旗
private int gameState = STATEPLAY; //游戏状态
private int s_width = 0; //屏幕尺寸 宽
private int s_height = 0; //屏幕尺寸 高
private int addMine = 0; //重新开始后雷数增加的个数
private boolean isShowInfo = false; //是否显示游戏信息
private String strFlagNum = "红旗数";
private String strMineNum = "正确率";
private String[] gameInfo = {"游戏中","游戏失败 按0重新开始","游戏胜利 按0进入多雷区"};
private Font font = Font.getFont( Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE );
cGame()
{
setFullScreenMode(true); //设置游戏为全屏幕模式,该函数只能在支持midp2.0的手机上使用
s_width = getWidth(); //得到屏幕尺寸 宽
s_height= getHeight(); //得到屏幕尺寸 高
rePlay( 0 ); //游戏初始化//重新游戏
}
/**
* 系统自动调用该绘图函数,并传入绘图设备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);
}
for( int i=0; i<map_x; i++ )
{
for( int j=0; j<map_y; j++ )
{
if( map_show[i][j] == MINE_ON_SHOW ) //遍历地图数组 看该位置的雷数 是否应该显示
{
if( map[i][j]==0 ) //周围没有雷
{
g.setColor(0x666666);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
}
else if(map[i][j]<10) //显示周围的雷数
{
g.setColor(0x666666);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
g.setColor(0x00ff00);
g.drawString(""+map[i][j], j*map_h+8, i*map_w+4, g.LEFT|g.TOP); //显示该位置的雷数
}
else //踩到雷了
{
g.setColor(0xff0000);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
// g.drawString(""+map[i][j], j*map_h+5, i*map_w+4, g.LEFT|g.TOP); //显示该位置是雷
}
}
else if( map_show[i][j] == MINE_FLAG ) //显示红旗
{
paintFlag( g, j, i );
}
else if( map_show[i][j] == MINE_ASK ) //显示问号
{
paintInterrogation( g, j, i );
}
else if( map_show[i][j] == MINE_GUESS_ERR )//显示猜错了
{
g.setColor(0x666666);
g.fillRect(j*map_h+2, i*map_w+2, map_w-3, map_h-3);
paintGuessErr( g, j, i );
}
}
}
g.setColor(0xFF0000); //设置颜色 红
g.drawRect(key_x*map_w+1, key_y*map_h+1, map_w-2, map_h-2); //绘制一个空心矩形框//为光标
g.drawRect(key_x*map_w+2, key_y*map_h+2, map_w-4, map_h-4); //绘制一个空心矩形框//为光标
if( isShowInfo || gameState != STATEPLAY ) //如果游戏 结束
{
g.setFont( font );
g.drawString( strFlagNum+":"+flagNum, 20, s_height-60, g.LEFT|g.TOP ); //显示剩余旗数
g.drawString( strMineNum+":"+rightNum +"/"+ mine_num, 20, s_height-45, g.LEFT|g.TOP ); //显示正确率 猜对雷数/总雷数
g.drawString( gameInfo[ gameState ], 20, s_height-30, g.LEFT|g.TOP ); //显示游戏状态
}
}
/**
* 系统自动调用该函数,当有键盘事件发生为按下某键,参数key为按下键的键值
*/
public void keyPressed(int key)
{
key = Math.abs(key);
System.out.println("key="+key);
//上下左右 为移动光标事件,只需要调整光标位置即可,但需要做边界判断
switch( key )
{
case KEY_NUM2:
case KEY_UP:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_y--;
if( key_y<0 )
key_y = map_x-1;
}
break;
case KEY_NUM8:
case KEY_DOWN:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_y++;
key_y %=map_x;
}
break;
case KEY_NUM4:
case KEY_LEFT:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_x--;
if( key_x<0 )
key_x = map_y-1;
}
break;
case KEY_NUM6:
case KEY_RIGHT:
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
else
{
key_x++;
key_x %=map_y;
}
break;
case KEY_FIRE:
case KEY_NUM5:
if( gameState == STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
{
if( map_show[key_y][key_x] == MINE_FLAG )
break;
showMap( key_y, key_x ); //显示该位置的雷数
if( map[key_y][key_x] >=10 )//如果雷数>=10 该位置是雷,
{
isWinGame();
addMine = 0;
isShowInfo = true;
gameState = STATELOST; //游戏失败
}
}
break;
case KEY_NUM1: //设置红旗//问号//取消
if( gameState != STATEPLAY ) //如果游戏没结束//结束了就不做确认键操作了
break;
switch( map_show[key_y][key_x] )
{
case MINE_OFF_SHOW:
map_show[key_y][key_x] = MINE_FLAG;
flagNum--;
if( flagNum == 0 )
{
if( isWinGame() )
{
addMine = 5;
isShowInfo = true;
gameState = STATEWIN;
}
else
{
addMine = 0;
isShowInfo = true;
gameState = STATELOST;
}
}
break;
case MINE_FLAG:
flagNum++;
map_show[key_y][key_x] = MINE_ASK;
break;
case MINE_ASK:
map_show[key_y][key_x] = MINE_OFF_SHOW;
break;
}
break;
case KEY_NUM3: //是否显示游戏信息
isShowInfo = !isShowInfo;
break;
case KEY_NUM0: //当按下 数字键 0
rePlay( addMine ); //重新开始游戏
break;
}
/**
* 重新执行 paint() 但该函数是立刻返回,也就是说他不会等待paint()执行完毕就返回了,
* 如果 需要 paint()执行完毕才返回,可以使用serviceRepaints(),也可以两个都是用,但
* repaint()应该在serviceRepaints()之前.
*/
this.repaint(); //本例为键盘事件驱动,刷新函数也就是每次按下键盘才作
}
boolean isWinGame()
{
boolean isWin = true;
for( int i=0; i<map_x; i++ )
{
for( int j=0; j<map_y; j++ )
{
if( map_show[i][j] == MINE_FLAG ) //显示红旗
{
if( map[i][j] < 10 ) //地雷猜错了
{
map_show[i][j] = MINE_GUESS_ERR;
isWin = false;
}
else
{
rightNum ++;
}
}
}
}
return isWin; //群不红旗都插对了 才能通关
}
void paintFlag( Graphics g, int key_x, int key_y )
{
int x = key_x*map_h+9;
int y = key_y*map_w+5;
g.setColor( 0xFF0000 );
g.drawLine( x , y , x , y+11 ); // |
g.drawLine( x-2, y+11, x+3, y+11 ); // -
g.drawLine( x , y , x+5, y+ 2 ); // >
g.drawLine( x+5, y+2 , x , y+ 4 ); // >
x += 1;
y += 1;
g.drawLine( x , y , x , y+11 ); // |
g.drawLine( x-5, y+11, x+4, y+11 ); // -
g.drawLine( x , y , x+5, y+ 2 ); // >
g.drawLine( x+5, y+2 , x , y+ 4 ); // >
}
void paintInterrogation( Graphics g, int key_x, int key_y )
{
int x = key_x*map_h+8;
int y = key_y*map_w+5;
g.setColor( 0xFF0000 );
g.drawString("?", x, y, g.LEFT|g.TOP); // ?
}
void paintGuessErr( Graphics g, int key_x, int key_y )
{
int x = key_x*map_h+8;
int y = key_y*map_w+5;
g.setColor( 0xFF0000 );
g.drawString("x", x, y, g.LEFT|g.TOP); // x
}
//该函数是一个递归函数,把当前位置设置成显示,并判断当前位置雷数是否为0个
//如果是0个雷,那么它周围的8个格子都要再作一次showMap
void showMap(int x, int y)
{
if( map_show[x][y] == MINE_FLAG )
return;
if( map_show[x][y] == MINE_ON_SHOW )
return;
else
map_show[x][y] = MINE_ON_SHOW;
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( int add )
{
if( add > 0 )
{
map_x += 1; //雷区的 行数 // 10 - 15
map_y += 1; //雷区的 列数 // 10 - 12
if( map_x >= 15 ) map_x = 15;
if( map_y >= 12 ) map_y = 12;
addMine = 0; //每次增加的雷数
}
else
add = 0;
key_x = map_x / 2; //游戏初始时 光标所在雷区的格子位置
key_y = map_y / 2; //游戏初始时 光标所在雷区的格子位置
mine_num += add; //雷区的雷数 不应该大于雷区的格子总数
if(mine_num >= map_x*map_y/2)
mine_num = map_x*map_y/10; //纠正雷数不能超过雷区的格子数
flagNum = mine_num; //剩余红旗数
rightNum = 0; //猜对的雷数
gameState = STATEPLAY;
map = new int[map_x][map_y];
map_show = new int[map_x][map_y];
rand = new Random( System.currentTimeMillis() ); //用事件作随机数种子的随机数
isShowInfo = false;
//布雷
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;
}
}
}
}