扫雷-Java完整仿制(网络备份)

类别:Java 点击:0 评论:0 推荐:
选择自 Nicholas_Lin 的 Blog

呵呵,前一阵子忙着考试,好长时间没上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&&currentThread==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

本文地址:http://com.8s8s.com/it/it11541.htm