📄 bombscanvas.java
字号:
package com.liigo.j2me.bombs;
import com.liigo.j2me.framework.*;
import javax.microedition.lcdui.*;
import java.util.*;
public class BombsCanvas extends MyCanvas implements CommandListener
{
static Options options = new Options();
int xCount, yCount;
int bombCount; //总雷数
int defaultOpenCount;
int xMargin, yMargin, cx, cy;
int xFocus, yFocus;
boolean isGameOver, isWin;
int bombLeftCount; //剩余地雷数 (总雷数-标记雷区数)
static Font gaveOverFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE);
Rect canvasRect = new Rect(0,0, getWidth(), getHeight());
Vector cells = new Vector();
//如果不用双缓冲区的话,格数较多时(>10*8)稍微有些迟滞(<0.5s)
Image memImage = Image.createImage(getWidth(), getHeight());
boolean paintBuffered = false;
private static BombsCanvas instance = new BombsCanvas();
Command newGameCommand = new Command("新局", Command.SCREEN, 1);
Command setupCommand = new Command("设置", Command.SCREEN, 1);
Command helpCommand = new Command("帮助", Command.SCREEN, 1);
Command aboutCommand = new Command("关于", Command.SCREEN, 1);
Command exitCommand = new Command("退出", Command.SCREEN, 1);
Command infoCommand = new Command("", Command.CANCEL, 0); //显示剩余地雷数, 或游戏结束时用于开始新局
public static BombsCanvas getInstance()
{
return instance;
}
private BombsCanvas()
{
init();
}
public void init()
{
options.loadOptionsFromDB();
setBackColor(0xffffff);
xMargin = yMargin = 2;
addCommand(newGameCommand);
addCommand(setupCommand);
addCommand(helpCommand);
addCommand(aboutCommand);
addCommand(exitCommand);
addCommand(infoCommand);
setCommandListener(this);
}
public void setOptions()
{
xCount = options.getXCount();
yCount = options.getYCount();
bombCount = options.getBombCount();
defaultOpenCount = options.getDefaultOpenCount();
}
public Options getOptions()
{
return options;
}
public void commandAction(Command c, Displayable d)
{
if(c == newGameCommand)
{
newGame();
}
else if(c == setupCommand)
{
OptionsForm.getInstance().show();
}
else if(c == helpCommand)
{
MessageBox msg = new MessageBox("", MessageBox.TYPE_OK);
msg.appendText("名称:扫雷\n");
msg.appendText("目的:根据游戏提供的相关信息,揭开所有的非雷区。\n");
msg.appendText("操作:上下左右键(或2,8,4,6键)分别用于上下左右移动当前活动区域(以红色虚线框标识);"
+"5键(或1键,或OK键)用于揭开当前活动区域;"
+"3键用于将当前活动区域标记为有雷区(再次按下3键将取消该标记)。\n");
msg.appendText("说明:未揭开区域显示为灰色背景;"
+"已揭开的非雷区显示为绿色背景,同时以文字标明其周围(八个区域)的地雷总数(每个区域最多只有一个地雷);");
msg.appendText("被标记为有雷的区域以黄色背景显示;一旦有雷区被揭开(以红色背景显示),则游戏结束。祝您玩的开心!\n");
msg.appendText("liigo");
msg.show();
}
else if(c == aboutCommand)
{
MessageBox msg = new MessageBox("", MessageBox.TYPE_OK);
msg.appendText("扫雷 v1.0\n");
msg.appendText("庄晓立(liigo)\n");
msg.appendText("QQ: 175199125\n");
msg.appendText("liigo@sina.com\n");
msg.appendText("www.liigo.com\n");
msg.appendText("http://blog.csdn.net/liigo/\n");
msg.show();
}
else if(c == exitCommand)
{
((BombsMidlet)Application.getInstance().getMidlet()).exit();
}
else if(c == infoCommand)
{
if(isGameOver() || isWin()) newGame();
}
}
public void newGame()
{
MyLog.log("newGame()");
setOptions(); //应用最新的设置信息
xFocus = yFocus = 0;
isGameOver = false;
isWin = false;
bombLeftCount = bombCount;
setInfoCommandLabel();
paintBuffered = false;
System.gc();
int i=0;
cells.removeAllElements();
for(i=0; i<getCellCount(); i++)
{
cells.addElement(new Cell());
}
//随机设置雷区
int count = 0;
MyRandom random = new MyRandom();
while(true)
{
int x = random.nextInt(getCellCount());
//MyLog.log("random: "+x);
Cell cell = (Cell)cells.elementAt(x);
if(!cell.isBomb())
{
cell.setIsBomb(true);
count++;
if(count >= bombCount) break;
}
}
calcAroundBombs();
defaultOpenCells();
repaint();
}
//计算各Cell周围的雷数
private void calcAroundBombs()
{
Cell cell = null;
for(int i=0; i<getCellCount(); i++)
{
cell = getCell(i);
cell.setAroundBombCount(getCellAroundBombs(i));
}
}
private int getCellAroundBombs(int index)
{
if(!isValidIndex(index)) return 0;
int i = getXIndex(index);
int j = getYIndex(index);
int count = 0;
Cell cell = null;
cell = getCell(i-1, j-1); if(cell!=null && cell.isBomb()) count++; //左上
cell = getCell(i, j-1); if(cell!=null && cell.isBomb()) count++; //上
cell = getCell(i+1, j-1); if(cell!=null && cell.isBomb()) count++; //右上
cell = getCell(i-1, j); if(cell!=null && cell.isBomb()) count++; //左
cell = getCell(i+1, j); if(cell!=null && cell.isBomb()) count++; //右
cell = getCell(i-1, j+1); if(cell!=null && cell.isBomb()) count++; //左下
cell = getCell(i, j+1); if(cell!=null && cell.isBomb()) count++; //下
cell = getCell(i+1, j+1); if(cell!=null && cell.isBomb()) count++; //右下
return count;
}
private int getXIndex(int index)
{
return (index % xCount);
}
private int getYIndex(int index)
{
return (index / xCount);
}
//揭开指定的Cell。如果周围没有雷,则把周围的Cell也揭开(递归处理)。
private void openCell(int i, int j)
{
if(!isValidIndex(i, j)) return;
Cell cell = getCell(i, j);
if(cell==null || cell.isOpen()) return;
//MyLog.log("openCell("+i+", "+j+") "+cell);
cell.openIt();
if(cell.isBomb())
{
gameOver(); return;
}
paintCellToMemImage(i, j, false);
if(cell.getAroundBombCount() != 0) return;
openCell(i-1,j-1); openCell(i,j-1); openCell(i+1,j-1);
openCell(i-1,j); openCell(i+1,j);
openCell(i-1,j+1); openCell(i,j+1); openCell(i+1,j+1);
}
private void defaultOpenCells()
{
if(defaultOpenCount <= 0) return;
MyRandom random = new MyRandom();
int loopCount = 0;
while(true)
{
int index = random.nextInt(getCellCount());
Cell cell = getCell(index);
if(cell.isOpen() || cell.isBomb()) continue;
int i = getXIndex(index);
int j = getYIndex(index);
openCell(i, j);
if(getOpenedCount() >= defaultOpenCount) break;
//防止(可能的)无限循环
if(loopCount++ > 2*getCellCount()) break;
}
}
private int getOpenedCount()
{
//MyLog.log("getOpenedCount()");
Cell cell = null;
int count = 0;
for(int i=0; i<getCellCount(); i++)
{
cell = getCell(i);
if(cell!=null)
{
if(cell.isOpen()) count++;
}
}
return count;
}
private boolean checkIsWin()
{
Cell cell = null;
for(int i=0; i<getCellCount(); i++)
{
cell = getCell(i);
if(cell!=null)
{
if(!cell.isBomb() && !cell.isOpen())
{
return false;
}
}
}
return true;
}
private int getCellCount()
{
return (xCount*yCount);
}
private boolean isValidIndex(int index)
{
return (index>=0 && index<getCellCount());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -