呵呵,前一阵子忙着考试,好长时间没上BLOG了。今天贴一个我自己做的扫雷程序,提高下人气,^_^
因为刚写这个程序的时候没有想过会写的这么复杂,所以代码注释很少,抱歉。下面稍微说一下主要类的用途:
MainFrame:主程序
ImageFactory:图片管理
LevelInfo:级别设定
LevelLog:级别记录
MineGrid:格子
*Dialog:各种各样的对话框
swing:
AboutDialog:关于对话框,模仿windows制做
awt:
LedNumber:把数字格式化为液晶字体图像
源代码:
//file MainFrame.java:
package nicholas.game.mine;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import nicholas.awt.LedNumber;
import nicholas.swing.AboutDialog;
public class MainFrame extends JFrame implements ActionListener {
//UI components
private JLabel mineLabel;
private JLabel timeLabel;
private JLabel statusButton;
private JPanel gridPanel;
private JPanel statusPanel;
private Dimension gpd;
private Dimension spd;
private MineGrid grid[][];
private boolean mode[][];
private final int margin = 7;
private final int titleh = 52;
private int xBound;
private int yBound;
private int mineCount;
private int showCount; //the amount of grids opened
private int leftCount; //the amount of mines not labeled
private int timepassed;
private boolean firstClick;
private boolean markCheck;
//Menu Components
private JMenuItem startItem;
private JMenuItem exitItem;
private JMenuItem logItem;
private JMenuItem aboutItem;
private JRadioButtonMenuItem levelItem[];
private JCheckBoxMenuItem markCheckItem;
//Game informations
private LevelInfo levelInfo;
private int currentLevel;
private LevelLog log[];
private LedNumber led;
private GridMouseAdapter gma;
private StatusMouseAdapter sma;
private TimeThread timeThread;
public MainFrame() {
super("扫雷");
//default
currentLevel = 0;
levelInfo = LevelInfo.DEFAULT_LEVEL[currentLevel];
log = new LevelLog[3];
for(int i=0;i<3;i++)
log[i] = new LevelLog();
//read from file
readLog();
led = new LedNumber();
gma = new GridMouseAdapter();
sma = new StatusMouseAdapter();
//setup menus
setMenuBar();
setStatusPanel();
resetPane();
addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
writeLog();
System.exit(0);
}
}
);
setIconImage(ImageFactory.getInstance().getImageicon(16).getImage());
setResizable(false);
}
//execution application
public static void main(String args[]) {
MainFrame application = new MainFrame();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {}
}
//file operation
private void readLog() {
try {
File logFile = new File("mine.log");
if(!logFile.exists()) return;
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(logFile));
for(int i=0;i<3;i++) {
log[i] = (LevelLog)ois.readObject();
}
markCheck = ois.readBoolean();
currentLevel = ois.readInt();
if(currentLevel==3) {
levelInfo = (LevelInfo)ois.readObject();
} else {
levelInfo = LevelInfo.DEFAULT_LEVEL[currentLevel];
}
ois.close();
} catch (Exception e) {System.out.println("read fail");}
}
private void writeLog() {
try {
File logFile = new File("mine.log");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(logFile));
for(int i=0;i<3;i++) {
oos.writeObject(log[i]);
}
oos.writeBoolean(markCheck);
oos.writeInt(currentLevel);
if(currentLevel==3) {
oos.writeObject(levelInfo);
}
oos.close();
} catch (Exception e) {System.out.println("write fail");}
}
/*
*add status label to status panel
*/
private void setStatusPanel() {
JPanel temp;
statusPanel = new JPanel(new BorderLayout());
mineLabel = new JLabel();
mineLabel.setBorder(BorderFactory.createLoweredBevelBorder());
temp = new JPanel(new FlowLayout(1,4,4));
temp.add(mineLabel);
temp.setBackground(Color.LIGHT_GRAY);
statusPanel.add(temp,BorderLayout.WEST);
timeLabel = new JLabel();
timeLabel.setBorder(BorderFactory.createLoweredBevelBorder());
temp = new JPanel(new FlowLayout(1,4,4));
temp.add(timeLabel);
temp.setBackground(Color.LIGHT_GRAY);
statusPanel.add(temp,BorderLayout.EAST);
statusButton = new JLabel();
statusButton.setBorder(BorderFactory.createRaisedBevelBorder());
statusButton.addMouseListener(sma);
temp = new JPanel(new FlowLayout(1,0,4));
temp.setBackground(Color.LIGHT_GRAY);
temp.add(statusButton);
statusPanel.add(temp,BorderLayout.CENTER);
statusPanel.setSize(10,37);
statusPanel.setBorder(BorderFactory.createLoweredBevelBorder());
spd = statusPanel.getSize();
}
private void resetStatusPanel() {
mineLabel.setIcon(new ImageIcon(led.getLedImage(leftCount,3)));
timeLabel.setIcon(new ImageIcon(led.getLedImage(timepassed,3)));
statusButton.setIcon(ImageFactory.getInstance().getImageicon(17));
}
private void setGridPanel() {
xBound = levelInfo.getXBound();
yBound = levelInfo.getYBound();
mineCount = levelInfo.getMineCount();
MineGrid.xBound = this.xBound;
MineGrid.yBound = this.yBound;
grid = new MineGrid[xBound][yBound];
mode = new boolean[xBound][yBound];
gridPanel = new JPanel();
gridPanel.setBackground(Color.GRAY);
//initialize grid panel
gridPanel.setLayout(null);
for(int x = 0; x < xBound; x++) {
for(int y =0; y < yBound; y++) {
grid[x][y] = new MineGrid(x,y);
grid[x][y].setIcon(ImageFactory.getInstance().getImageicon(9));
grid[x][y].setBounds(1+y*MineGrid.SIZE,x*MineGrid.SIZE,MineGrid.SIZE,MineGrid.SIZE);
grid[x][y].addMouseListener(gma);
gridPanel.add(grid[x][y],null);
}
}
gpd = new Dimension(yBound*MineGrid.SIZE+6, xBound*MineGrid.SIZE+6);
}//end of set grid panel
private void resetGridPanel() {
leftCount = 0;
int x,y,i,j;
boolean temp;
for(x = 0; x < xBound; x++) {
for(y =0; y < yBound; y++) {
grid[x][y].setIcon(ImageFactory.getInstance().getImageicon(9));
grid[x][y].setStatus(MineGrid.NORMAL);
//lay mines
if(leftCount < mineCount) {
mode[x][y] = true;
leftCount++;
} else {
mode[x][y] = false;
}
}
}
//exchange
showCount = leftCount;
for(x = 0; x < xBound; x++) {
for(y =0; y < yBound; y++) {
if(showCount==0) break;
i = (int)(Math.random()*xBound);
j = (int)(Math.random()*yBound);
temp = mode[x][y];
mode[x][y] = mode[i][j];
mode[i][j] = temp;
showCount--;
}
}
}
/*
*set up menu bar
*/
private void setMenuBar() {
JMenuBar menuBar = new JMenuBar();
menuBar.setBorder(BorderFactory.createLineBorder(Color.WHITE, 2));
JMenu gameMenu = new JMenu("游戏(G)");
JMenu helpMenu = new JMenu("帮助(H)");
gameMenu.setMnemonic('G');
helpMenu.setMnemonic('H');
startItem = new JMenuItem("开局(N)");
startItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2,0));
logItem = new JMenuItem("扫雷英雄榜(T)...");
markCheckItem = new JCheckBoxMenuItem("标记(?)(M)");
exitItem = new JMenuItem("退出(X)");
aboutItem = new JMenuItem("关于扫雷(A)...");
startItem.setMnemonic('N');
exitItem.setMnemonic('X');
aboutItem.setMnemonic('A');
aboutItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1,0));
logItem.setMnemonic('T');
markCheckItem.setMnemonic('M');
markCheckItem.setSelected(markCheck);
gameMenu.add(startItem);
gameMenu.addSeparator();
//radio group
levelItem = new JRadioButtonMenuItem[4];
ButtonGroup levelGroup = new ButtonGroup();
levelItem[0] = new JRadioButtonMenuItem("初级(B)");
levelItem[1] = new JRadioButtonMenuItem("中级(I)");
levelItem[2] = new JRadioButtonMenuItem("高级(E)");
levelItem[3] = new JRadioButtonMenuItem("自定义(C)...");
levelItem[0].setMnemonic('B');
levelItem[1].setMnemonic('I');
levelItem[2].setMnemonic('E');
levelItem[3].setMnemonic('C');
for(int i=0;i<4;i++) {
levelGroup.add(levelItem[i]);
levelItem[i].addActionListener(this);
gameMenu.add(levelItem[i]);
}
levelItem[currentLevel].setSelected(true);
gameMenu.addSeparator();
gameMenu.add(markCheckItem);
gameMenu.addSeparator();
gameMenu.add(logItem);
gameMenu.addSeparator();
gameMenu.add(exitItem);
helpMenu.add(aboutItem);
startItem.addActionListener(this);
markCheckItem.addActionListener(this);
logItem.addActionListener(this);
exitItem.addActionListener(this);
aboutItem.addActionListener(this);
menuBar.add(gameMenu);
menuBar.add(helpMenu);
setJMenuBar(menuBar);
}
private void showAboutDialog() {
String readme = "";
File file = new File("readme.txt");
if(file.exists()) {
try {
BufferedReader input = new BufferedReader(new FileReader(file));
StringBuffer buffer = new StringBuffer();
String text;
while((text = input.readLine())!=null)
buffer.append(text+"\n");
input.close();
readme = buffer.toString();
} catch(IOException ioException) {}
}
AboutDialog dialog = new AboutDialog(this, "扫雷",readme,
ImageFactory.getInstance().getImageicon(14),
ImageFactory.getInstance().getImageicon(16));
dialog = null;
}
public void actionPerformed(ActionEvent ae) {
if(ae.getSource()==startItem) {
restartGame();
} else if(ae.getSource()==markCheckItem) {
markCheck = markCheckItem.isSelected();
} else if(ae.getSource()==logItem) {
//show heros
LogDialog dialog = new LogDialog(this, log);
dialog = null;
} else if(ae.getSource()==exitItem) {
writeLog();
System.exit(0);
} else if(ae.getSource()==aboutItem) {
showAboutDialog();
} else {
//radio buttons
int x;
for(x = 0; x < 3; x++) {
if(ae.getSource()==levelItem[x]) break;
}
if(x < 3) {
if(currentLevel!=x) {
currentLevel = x;
levelInfo = LevelInfo.DEFAULT_LEVEL[currentLevel];
resetPane();
}
} else {
LevelInfo newLevel = CustomDialog.getUserLevel(this, levelInfo);
if(newLevel!=null) {
currentLevel = x;
levelInfo = newLevel;
resetPane();
}
}
}//radio buttons
}
/*
*1.setup grid panel
*2.restart game
*/
private void resetPane() {
Container container = getContentPane();
container.setLayout(null);
container.removeAll();
container.setBackground(Color.LIGHT_GRAY);
setGridPanel();
JPanel tempPanel = new JPanel(new BorderLayout());
tempPanel.setBounds(margin, margin, gpd.width, spd.height);
tempPanel.add(statusPanel,BorderLayout.CENTER);
container.add(tempPanel,null);
tempPanel = new JPanel(new BorderLayout());
tempPanel.setBounds(margin,margin*2+spd.height,gpd.width,gpd.height);
tempPanel.add(gridPanel,BorderLayout.CENTER);
tempPanel.setBorder(BorderFactory.createLoweredBevelBorder());
container.add(tempPanel,null);
int X = (int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() - (gpd.width+3*margin-1)) / 2;
int Y = (int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() - (gpd.height+spd.height+4*margin+titleh)) / 2;
setLocation(X, Y);
setSize(gpd.width+3*margin-1, gpd.height+spd.height+4*margin+titleh);
show();
restartGame();
}
private void restartGame() {
timepassed = 0;
timeThread = null;
firstClick = true;
resetGridPanel();
resetStatusPanel();
}
//Method labelMine
private void labelMine(MineGrid g) {
if(markCheck) {
//being labeled then to marked
if(g.isLabeled()) {
g.setMarked(true);
g.setStatus(MineGrid.NORMAL);
g.setIcon(ImageFactory.getInstance().getImageicon(13));
leftCount++;
} else {
//normal but marked then to normal
if(g.isMarked()) {
g.setMarked(false);
g.setIcon(ImageFactory.getInstance().getImageicon(9));
} else {
//normal and not marked then to labeled
g.setIcon(ImageFactory.getInstance().getImageicon(10));
g.setStatus(MineGrid.LABELED);
leftCount--;
}
}
} else {
//being labeled
if(g.isLabeled()) {
g.setIcon(ImageFactory.getInstance().getImageicon(9));
g.setStatus(MineGrid.NORMAL);
leftCount++;
} else {
//not being labeled
g.setIcon(ImageFactory.getInstance().getImageicon(10));
g.setStatus(MineGrid.LABELED);
leftCount--;
}
}
//upgrade mineLabel
mineLabel.setIcon(new ImageIcon(led.getLedImage(leftCount,3)));
}
//when grid[i] been clicked(cl indicate the botton).
private void clickGrid(int x, int y, int cl) {
int count=0;
int lcount=0;
//change status to clicked
grid[x][y].setStatus(MineGrid.CLICKED);
//mine is clicked
if(mode[x][y]) {
grid[x][y].setIcon(ImageFactory.getInstance().getImageicon(12));
endGame(0);
return;
}
//not mine
//count mines and labeled grids around grid[x][y]
for(int i=grid[x][y].xlow;i<=grid[x][y].xhigh;i++) {
for(int j=grid[x][y].ylow;j<=grid[x][y].yhigh;j++) {
if(mode[i][j])
count++;
if(grid[i][j].isLabeled())
lcount++;
}
}//end count
//click by left button
if(cl==1) {
grid[x][y].setIcon(ImageFactory.getInstance().getImageicon(count));
showCount++;
if( showCount == xBound*yBound - mineCount) {
endGame(1);
return;
}
}
//no mine around
if((cl==1&&count==0)||cl==2&&count==lcount) {
for(int i=grid[x][y].xlow;i<=grid[x][y].xhigh;i++) {
for(int j=grid[x][y].ylow;j<=grid[x][y].yhigh;j++) {
if(i==x&&j==y) continue;
else if(grid[i][j].isNormal())
clickGrid(i,j,1);
}
}
}
}
//execute on winning or losing
private void endGame(int status) {
//stop counting time
timeThread=null;
//win
if(status==1) {
statusButton.setIcon(ImageFactory.getInstance().getImageicon(19));
for(int x = 0; x < xBound; x++) {
for(int y = 0; y < yBound; y++) {
//show mines not labeled
if(mode[x][y]&&grid[x][y].isNormal())
grid[x][y].setIcon(ImageFactory.getInstance().getImageicon(10));
grid[x][y].setStatus(MineGrid.CLICKED);
}
}
leftCount = 0;
mineLabel.setIcon(new ImageIcon(led.getLedImage(0,3)));
//show user name input
if(currentLevel<3&&timepassed<log[currentLevel].getRecord()) {
log[currentLevel].setRecord(timepassed);
log[currentLevel].setUserName(
UserDialog.showInputNameDialog(
this,currentLevel,log[currentLevel].getUserName()));
LogDialog dialog = new LogDialog(this, log);
}
//lose
} else {
statusButton.setIcon(ImageFactory.getInstance().getImageicon(20));
for(int x = 0; x < xBound; x++) {
for(int y = 0; y < yBound; y++) {
//show mines not labeled
if(mode[x][y]&&grid[x][y].isNormal())
grid[x][y].setIcon(ImageFactory.getInstance().getImageicon(11));
//show grid wrong labeled
else if(!mode[x][y]&&grid[x][y].isLabeled())
grid[x][y].setIcon(ImageFactory.getInstance().getImageicon(15));
//forbid any actions
grid[x][y].setStatus(MineGrid.CLICKED);
}
}
}
}
private class StatusMouseAdapter extends MouseAdapter {
private boolean mouseIn;
private boolean mouseDown;
private Icon icon;
public StatusMouseAdapter() {
super();
}
public void mouseEntered(MouseEvent me) {
mouseIn = true;
if(mouseDown) {
statusButton.setBorder(BorderFactory.createLoweredBevelBorder());
icon = statusButton.getIcon();
statusButton.setIcon(ImageFactory.getInstance().getImageicon(18));
}
}
public void mousePressed(MouseEvent me) {
mouseDown = true;
statusButton.setBorder(BorderFactory.createLoweredBevelBorder());
icon = statusButton.getIcon();
statusButton.setIcon(ImageFactory.getInstance().getImageicon(18));
}
public void mouseReleased(MouseEvent me) {
mouseDown = false;
statusButton.setIcon(icon);
statusButton.setBorder(BorderFactory.createRaisedBevelBorder());
if(mouseIn) restartGame();
}
public void mouseExited(MouseEvent me) {
mouseIn = false;
if(mouseDown) {
statusButton.setIcon(icon);
statusButton.setBorder(BorderFactory.createRaisedBevelBorder());
}
}
}
private class GridMouseAdapter extends MouseAdapter {
private MineGrid current;
private boolean leftDown;
private boolean rightDown;
private boolean middle;
public GridMouseAdapter() {
super();
}
public void mousePressed(MouseEvent me) {
current = (MineGrid)me.getSource();
//as soon as right button down, label happen
//when not released, wait for next event
if(me.getButton()==3) {
rightDown = true;
if(!current.isClicked()&&!leftDown) labelMine(current);
}else if(me.getButton()==2) {
rightDown = true;
leftDown = true;
middle = true;
}else {
//click and double click not happen until release button
leftDown = true;
if(current.isNormal())
statusButton.setIcon(ImageFactory.getInstance().getImageicon(18));
pressGrid(current);
}
if(rightDown&&leftDown) {
//double
pressAround(current);
}
}
public void mouseEntered(MouseEvent me) {
current = (MineGrid)me.getSource();
if(leftDown&&rightDown) {
pressAround(current);
} else if(leftDown) {
pressGrid(current);
}
}
public void mouseReleased(MouseEvent me) {
if(current.isNormal())
statusButton.setIcon(ImageFactory.getInstance().getImageicon(17));
int x = current.getXpos();
int y = current.getYpos();
if(leftDown) {
leftDown = false;
if(firstClick) {
timeThread = new TimeThread();
timeThread.start();
firstClick = false;
//changeMine
if(mode[x][y]) {
int i,j;
do {
i = (int)(Math.random()*xBound);
j = (int)(Math.random()*yBound);
} while(mode[i][j]);
mode[x][y] = false;
mode[i][j] = true;
}
}
if(rightDown) {
releaseAround(current);
rightDown = false;
if(middle) {
middle = false;
}
if(current.isClicked()) clickGrid(x,y,2);
} else {
if(current.isNormal()) clickGrid(x,y,1);
}
} else {
rightDown = false;
}
}
public void mouseExited(MouseEvent me) {
current = (MineGrid)me.getSource();
if(leftDown&&rightDown) {
releaseAround(current);
} else if(leftDown) {
releaseGrid(current);
}
}
private void pressGrid(MineGrid g) {
if(!g.isNormal()) return;
g.setIcon(ImageFactory.getInstance().getImageicon(0));
}
private void releaseGrid(MineGrid g) {
if(!g.isNormal()) return;
g.setIcon(ImageFactory.getInstance().getImageicon(9));
}
private void pressAround(MineGrid g) {
int x = g.getXpos();
int y = g.getYpos();
for(int i=grid[x][y].xlow;i<=grid[x][y].xhigh;i++) {
for(int j=grid[x][y].ylow;j<=grid[x][y].yhigh;j++) {
pressGrid(grid[i][j]);
}
}
}
private void releaseAround(MineGrid g) {
int x = g.getXpos();
int y = g.getYpos();
for(int i=grid[x][y].xlow;i<=grid[x][y].xhigh;i++) {
for(int j=grid[x][y].ylow;j<=grid[x][y].yhigh;j++) {
releaseGrid(grid[i][j]);
}
}
}
}
//class TimeThread to count time
private class TimeThread extends Thread {
public TimeThread() {}
public void run() {
final Thread currentThread = Thread.currentThread();
while(timepassed<1000&¤tThread==timeThread) {
//change timeLabel
SwingUtilities.invokeLater(
//inner class Runnable
new Runnable() {
public void run() {
timeLabel.setIcon(new ImageIcon(led.getLedImage(timepassed,3)));
}
}
);
try {
Thread.sleep(999);
} catch(InterruptedException i) {
System.err.println("sleep interrupted");
}
timepassed++;
}
}//end of method run
}//end of class TimeThread
}
//file MineGrid.java
package nicholas.game.mine;
import java.awt.*;
import javax.swing.*;
public class MineGrid extends JLabel {
public static final int CLICKED = 0;
public static final int LABELED = 1;
public static final int NORMAL = 2;
public static final int SIZE = 16;
public static int xBound;
public static int yBound;
private int x, y;
private int status;
private boolean mark;
int xlow;
int ylow;
int xhigh;
int yhigh;
public MineGrid(int x, int y) {
super();
this.x = x;
this.y = y;
status = NORMAL;
mark = false;
xhigh = x;
yhigh = y;
xlow = x;
ylow = y;
if(x>0) xlow--;
if(x<xBound-1) xhigh++;
if(y>0) ylow--;
if(y<yBound-1) yhigh++;
}
public void setMarked(boolean m) {
mark = m;
}
public boolean isMarked() {
return mark;
}
public void setStatus(int s) {
status = s;
}
public int getXpos() {
return x;
}
public int getYpos() {
return y;
}
public boolean isClicked() {
return status == CLICKED;
}
public boolean isLabeled() {
return status == LABELED;
}
public boolean isNormal() {
return status == NORMAL;
}
}
/********************************************* status clickable labelable doubleClick *
*clicked false false true *
*labeled false true false *
* normal true true false *
\********************************************/
//file ImageFactory.java
package nicholas.game.mine;
import javax.swing.ImageIcon;
public class ImageFactory {
private static ImageFactory imagefactory;
private static ImageIcon images[];
private ImageFactory()
{
images = new ImageIcon[21];
images[0] = new ImageIcon(getClass().getResource("image/0.gif"));
images[1] = new ImageIcon(getClass().getResource("image/1.gif"));
images[2] = new ImageIcon(getClass().getResource("image/2.gif"));
images[3] = new ImageIcon(getClass().getResource("image/3.gif"));
images[4] = new ImageIcon(getClass().getResource("image/4.gif"));
images[5] = new ImageIcon(getClass().getResource("image/5.gif"));
images[6] = new ImageIcon(getClass().getResource("image/6.gif"));
images[7] = new ImageIcon(getClass().getResource("image/7.gif"));
images[8] = new ImageIcon(getClass().getResource("image/8.gif"));
images[9] = new ImageIcon(getClass().getResource("image/normal.gif"));
images[10] = new ImageIcon(getClass().getResource("image/flag.gif"));
images[11] = new ImageIcon(getClass().getResource("image/mine.gif"));
images[12] = new ImageIcon(getClass().getResource("image/onmine.gif"));
images[13] = new ImageIcon(getClass().getResource("image/question.gif"));
images[14] = new ImageIcon(getClass().getResource("image/topbar.gif"));
images[15] = new ImageIcon(getClass().getResource("image/wrong.gif"));
images[16] = new ImageIcon(getClass().getResource("image/mineico.gif"));
images[17] = new ImageIcon(getClass().getResource("image/qq1.gif"));
images[18] = new ImageIcon(getClass().getResource("image/qq2.gif"));
images[19] = new ImageIcon(getClass().getResource("image/qq3.gif"));
images[20] = new ImageIcon(getClass().getResource("image/qq4.gif"));
}
public ImageIcon getImageicon(int i)
{
return images[i];
}
public static synchronized ImageFactory getInstance()
{
if(imagefactory != null)
{
return imagefactory;
} else {
imagefactory = new ImageFactory();
return imagefactory;
}
}
}
//file LevelInfo.java
package nicholas.game.mine;
import java.io.Serializable;
/*
*modifiable level
*/
public class LevelInfo implements Serializable {
public static final LevelInfo DEFAULT_LEVEL[] = {
new LevelInfo(9, 9, 10),
new LevelInfo(16, 16, 40),
new LevelInfo(16, 30, 99)
};
private int mineCount;
private int xBound;
private int yBound;
public LevelInfo(int x, int y, int mc){
if(x > 24) {
xBound = 24;
} else if(x < 9) {
xBound = 9;
} else {
xBound = x;
}
if(y > 30) {
yBound = 30;
} else if(y < 9) {
yBound = 9;
} else {
yBound = y;
}
if(mc > (xBound-1)*(yBound-1)) {
mineCount = (xBound-1)*(yBound-1);
} else if(mc < 10) {
mineCount = 10;
} else {
mineCount = mc;
}
}
public int getMineCount() {
return mineCount;
}
public int getXBound() {
return xBound;
}
public int getYBound() {
return yBound;
}
}
/*
*record write to file
*/
class LevelLog implements Serializable {
private static final String DEFAULT_NAME = "匿名";
private static final int DEFAULT_RECORD = 999;
private int record;
private String user;
public LevelLog() {
setDefault();
}
public void setDefault() {
user = DEFAULT_NAME;
record = DEFAULT_RECORD;
}
public void setRecord(int r) {
record = r;
}
public void setUserName(String name) {
user = name;
}
public int getRecord() {
return record;
}
public String getUserName() {
return user;
}
public String toString() {
return record + "\t" + user + "\n";
}
}
//file LogDialog.java
package nicholas.game.mine;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LogDialog extends JDialog implements ActionListener {
private LevelLog levelLog[];
private JTextArea logArea;
private JButton resetButton;
private JButton confirmButton;
public LogDialog(JFrame frame, LevelLog log[]) {
super(frame, "扫雷英雄榜", true);
getContentPane().setLayout(null);
levelLog = log;
logArea = new JTextArea();
logArea.setEditable(false);
logArea.setBackground(UIManager.getColor("CheckBox.background"));
logArea.setBounds(10,10,160,60);
getContentPane().add(logArea, null);
resetButton = new JButton("重新计分");
resetButton.setBounds(10,70,90,25);
resetButton.addActionListener(this);
getContentPane().add(resetButton, null);
setTextArea();
confirmButton = new JButton("确定");
confirmButton.setBounds(105,70,60,25);
confirmButton.addActionListener(this);
getContentPane().add(confirmButton, null);
setSize(180,140);
setLocationRelativeTo(frame);
setResizable(false);
show();
}
private void setTextArea() {
logArea.setText("初级:" + levelLog[0].toString()
+ "中级:" + levelLog[1].toString()
+ "高级:" + levelLog[2].toString());
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()==resetButton) {
for(int i=0;i<3;i++) {
levelLog[i].setDefault();
}
setTextArea();
} else {
dispose();
}
}
}
//file CustomDialog.java
package nicholas.game.mine;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CustomDialog extends JDialog implements ActionListener {
private JTextField widthField;
private JTextField heightField;
private JTextField mineField;
private JButton confirmButton;
private JButton cancelButton;
private static LevelInfo level;
public CustomDialog(Frame frame, LevelInfo levelInfo) {
super(frame,"自定义雷区",true);
getContentPane().setLayout(null);
JLabel tempLabel = new JLabel("高度:");
tempLabel.setBounds(10,10,30,20);
heightField = new JTextField(""+levelInfo.getXBound());
heightField.setBounds(50,10,40,20);
getContentPane().add(tempLabel,null);
getContentPane().add(heightField,null);
tempLabel = new JLabel("宽度:");
tempLabel.setBounds(10,40,30,20);
widthField = new JTextField(""+levelInfo.getYBound());
widthField.setBounds(50,40,40,20);
getContentPane().add(tempLabel,null);
getContentPane().add(widthField,null);
tempLabel = new JLabel("雷数:");
tempLabel.setBounds(10,70,30,20);
mineField = new JTextField(""+levelInfo.getMineCount());
mineField.setBounds(50,70,40,20);
getContentPane().add(tempLabel,null);
getContentPane().add(mineField,null);
confirmButton = new JButton("确定");
confirmButton.addActionListener(this);
confirmButton.setBounds(100,10,60,25);
getContentPane().add(confirmButton,null);
cancelButton = new JButton("取消");
cancelButton.addActionListener(this);
cancelButton.setBounds(100,45,60,25);
getContentPane().add(cancelButton,null);
setSize(180,137);
setLocationRelativeTo(frame);
setResizable(false);
show();
}
public void actionPerformed(ActionEvent e) {
level = null;
if(e.getSource()==confirmButton) {
int x = Integer.parseInt(heightField.getText());
int y = Integer.parseInt(widthField.getText());
int m = Integer.parseInt(mineField.getText());
level = new LevelInfo(x,y,m);
}
dispose();
}
public static LevelInfo getUserLevel(JFrame frame, LevelInfo levelInfo) {
CustomDialog dialog = new CustomDialog(frame, levelInfo);
return level;
}
}
//file UserDialog.java
package nicholas.game.mine;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class UserDialog extends JDialog implements ActionListener {
private JButton confirmButton;
private JTextField nameField;
private String[] level = {"初级","中级","高级"};
private static String name;
public UserDialog(JFrame frame, int l, String n) {
super(frame, "新记录",true);
getContentPane().setLayout(null);
JLabel textLabel = new JLabel("已破"+level[l]+"记录,");
textLabel.setBounds(30,5,100,20);
getContentPane().add(textLabel,null);
textLabel = new JLabel("请留尊姓大名。");
textLabel.setBounds(30,25,100,20);
getContentPane().add(textLabel,null);
nameField = new JTextField(n);
nameField.setBounds(10,60,120,20);
nameField.selectAll();
getContentPane().add(nameField,null);
confirmButton = new JButton("确定");
confirmButton.addActionListener(this);
confirmButton.setBounds(40,90,60,25);
getContentPane().add(confirmButton,null);
this.setUndecorated(true);
setSize(145,130);
setLocationRelativeTo(frame);
setResizable(false);
show();
}
public void actionPerformed(ActionEvent e) {
name = nameField.getText();
dispose();
}
public static String showInputNameDialog(JFrame frame, int l, String n) {
UserDialog dialog = new UserDialog(frame, l, n);
return name;
}
}
//file AboutDialog.java
package nicholas.swing;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AboutDialog extends JDialog implements ActionListener {
JButton cancelButton;
JTextArea textArea;
JLabel titleLabel;
JLabel topbarLabel;
JLabel iconLabel;
public AboutDialog(JFrame frame, String title, String readme, ImageIcon topbar, ImageIcon icon) {
super(frame,"关于 "+title,true);
getContentPane().setLayout(null);
JTextArea textArea;
JLabel topbarLabel;
JLabel iconLabel;
topbarLabel = new JLabel(topbar);
topbarLabel.setBounds(0,0,413,77);
getContentPane().add(topbarLabel);
iconLabel = new JLabel(icon);
iconLabel.setBounds(new Rectangle(10, 90, 36, 36));
getContentPane().add(iconLabel);
JLabel titleLabel = new JLabel("Colinsoft (R) "+title);
titleLabel.setFont(new Font("Dialog",1,13));
titleLabel.setBounds(56,84,345,26);
getContentPane().add(titleLabel);
textArea = new JTextArea();
textArea.setText(readme);
textArea.setBackground(UIManager.getColor("CheckBox.background"));
textArea.setLineWrap(true);
textArea.setEditable(false);
textArea.setCaretPosition(0);
JScrollPane scrollPane = new JScrollPane();
JViewport viewport = scrollPane.getViewport();
viewport.add(textArea);
scrollPane.setBounds(new Rectangle(56, 110, 345, 188));
scrollPane.setBorder(null);
getContentPane().add(scrollPane,BorderLayout.CENTER);
cancelButton = new JButton("确定");
cancelButton.setBounds(new Rectangle(340, 315, 60, 23));
cancelButton.addActionListener(this);
getContentPane().add(cancelButton);
JLabel separator = new JLabel();
separator.setBounds(60,307,340,1);
separator.setBorder(BorderFactory.createRaisedBevelBorder());
getContentPane().add(separator);
separator = new JLabel();
separator.setBounds(60,308,340,1);
separator.setBorder(BorderFactory.createLoweredBevelBorder());
getContentPane().add(separator);
setSize(419,378);
setLocationRelativeTo(frame);
setResizable(false);
show();
}
public void actionPerformed(ActionEvent e) {
dispose();
}
}
//file LedNumber.java
package nicholas.awt;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.Image;
import java.awt.Color;
import java.awt.image.BufferedImage;
public class LedNumber extends Component {
private Polygon segmentPolygon[];
private int numberSegment[][] = {
{0, 1, 2, 3, 4, 5 }, //0
{1, 2 }, //1
{0, 1, 3, 4, 6 }, //2
{0, 1, 2, 3, 6 }, //3
{1, 2, 5, 6 }, //4
{0, 2, 3, 5, 6 }, //5
{0, 2, 3, 4, 5, 6 }, //6
{0, 1, 2 }, //7
{0, 1, 2, 3, 4, 5, 6 }, //8
{0, 1, 2, 3, 5, 6 } //9
};
private int div[] = {1,10,100,1000,10000,100000};
private Image numberImage[];
private Color fontColor = Color.red; //the color of number
private Color bgColor = Color.black;
private Color maskColor = Color.darkGray;
private int dWidth = 12;
private int dHeight = 21;
public LedNumber() {
init();
}
public LedNumber(Color fc) {
fontColor = fc;
init();
}
public LedNumber(Color fc, Color bgc) {
bgColor = bgc;
fontColor = fc;
init();
}
public LedNumber(Color fc,Color bgc,Color mc) {
bgColor = bgc;
fontColor = fc;
maskColor = mc;
init();
}
public Image getLedImage(int dg, int bound) {
dg %= div[bound];
Image image = new BufferedImage(dWidth*bound, dHeight,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
bound--;
for(int i = bound;i>=0;i--) {
g.drawImage(numberImage[dg/div[i]],(bound-i)*dWidth,0,this);
dg %= div[i];
}
return image;
}
public void init() {
segmentPolygon = new Polygon[7];
numberImage = new Image[10];
//setup polygons
setNumberPolygon();
setNumberImage();
}
public void setBackGround(Color bgc) {
bgColor = bgc;
}
public void setFontColor(Color fc) {
fontColor = fc;
}
public void setMaskColor(Color mkc) {
maskColor = mkc;
}
public void setDigitWidth(int w) {
dWidth = w;
init();
}
public void setDigitHeight(int h) {
dHeight = h;
init();
}
public void setDigitSize(int w, int h) {
dWidth = w;
dHeight = h;
init();
}
private void setNumberImage() {
int i = 0;
int j = 0;
int k;
Graphics g;
while(i<10) {
numberImage[i] = new BufferedImage(15,20,BufferedImage.TYPE_INT_RGB);
g = numberImage[i].getGraphics();
g.setColor(bgColor);
g.fillRect(0,0,15,20);
g.setColor(Color.DARK_GRAY);
j = 0;
while(j<numberSegment[8].length) {
k = numberSegment[8][j];
g.fillPolygon(segmentPolygon[k]);
j++;
}
g.setColor(fontColor);
j = 0;
while(j<numberSegment[i].length) {
k = numberSegment[i][j];
g.fillPolygon(segmentPolygon[k]);
j++;
}
i++;
}
}
public void setNumberPolygon() {
int mid = dHeight/2+1;
segmentPolygon[0] = new Polygon();
segmentPolygon[0].addPoint(2, 1);
segmentPolygon[0].addPoint(dWidth-2,1);
segmentPolygon[0].addPoint(dWidth-5,4);
segmentPolygon[0].addPoint(4,4);
segmentPolygon[1] = new Polygon();
segmentPolygon[1].addPoint(dWidth-1, 1);
segmentPolygon[1].addPoint(dWidth-1, mid-1);
segmentPolygon[1].addPoint(dWidth-2, mid-1);
segmentPolygon[1].addPoint(dWidth-4, mid-3);
segmentPolygon[1].addPoint(dWidth-4, 4);
segmentPolygon[2] = new Polygon();
segmentPolygon[2].addPoint(dWidth-1, mid);
segmentPolygon[2].addPoint(dWidth-1, dHeight-2);
segmentPolygon[2].addPoint(dWidth-4, dHeight-5);
segmentPolygon[2].addPoint(dWidth-4, mid+1);
segmentPolygon[2].addPoint(dWidth-3, mid);
segmentPolygon[3] = new Polygon();
segmentPolygon[3].addPoint(dWidth-2, dHeight-1);
segmentPolygon[3].addPoint(1, dHeight-1);
segmentPolygon[3].addPoint(4, dHeight-4);
segmentPolygon[3].addPoint(dWidth-4, dHeight-4);
segmentPolygon[4] = new Polygon();
segmentPolygon[4].addPoint(1, dHeight-2);
segmentPolygon[4].addPoint(1, mid);
segmentPolygon[4].addPoint(3, mid);
segmentPolygon[4].addPoint(4, mid+1);
segmentPolygon[4].addPoint(4, dHeight-5);
segmentPolygon[5] = new Polygon();
segmentPolygon[5].addPoint(1, mid-1);
segmentPolygon[5].addPoint(1, 1);
segmentPolygon[5].addPoint(4, 4);
segmentPolygon[5].addPoint(4, mid-3);
segmentPolygon[5].addPoint(2, mid-1);
segmentPolygon[6] = new Polygon();
segmentPolygon[6].addPoint(3, mid-1);
segmentPolygon[6].addPoint(4, mid-2);
segmentPolygon[6].addPoint(dWidth-4, mid-2);
segmentPolygon[6].addPoint(dWidth-3, mid-1);
segmentPolygon[6].addPoint(dWidth-5, mid+1);
segmentPolygon[6].addPoint(4, mid+1);
}
}
PS:哇,复制黏贴好痛苦,还不知道有没有漏掉文件……哪位朋友知道哪有免费空间可以申请的,请告诉我。图片和文件都没办法放上来,大家将就着看了……如果想要.jar文件的,请写Email或留言。
-------develop note of--------
---mine in java by nicholas---
2004.11.20
i hate java layout management!
见鬼了,用二维数组就有问题,用一维就没有!grids全部都挤到一块了……实在没有办法了
2004.11.21
a small step out!
问题出在MineGrid上,全部重写一遍就没有问题了……然后把布局放到一起,大体的布局就出来了
2004.11.22
好像觉得把grid用一维数组更容易实现...
如果我每次都先把雷放在前十个格,然后只进行十次交换...雷的分布应该还是均匀的...
2004.11.23
终于完成的差不多了,唯一一个问题就是破记录的时候如果左右键一起按,那么下一次开局的时候要先释放右键
2004.11.27
总算完成了。修修改改了好几天,终于通过了自己的测试,正式成为version 0.9
2004.11.27
version 1.0