用swing写了一个扫雷,代码量没有想象中那么大。
注意:代码中用url获取了一个本地图片(地雷贴图),在其他电脑上运行此程序需要自行寻找贴图,保存在与类文件同一个文件夹并改名为image。原图片格式为png,若下载图片格式不同,请自行修改private static final String url = "\\image.png";
中的后缀名。
以本人使用的eclipse为例,项目名为MySwing,package名为SwingTest,图片应放在MySwing\bin\SwingTest中
游戏效果图:
package SwingTest;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
class Coord
{
public int row;
public int col;
Coord(int r,int c)
{
row = r;
col = c;
}
}
class Mine extends JButton
{
private boolean isMine;
private boolean visit;
private int mineAround;
private int row;
private int col;
Mine(int num,boolean boom,int r,int c)
{
super();
isMine = boom;
visit = true;
mineAround = num;
row = r;
col = c;
super.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
visit = false;
if(flip())
{
Game.die();
}
else
{
Queue<Coord> queue = new LinkedList<Coord>();
queue.add(new Coord(row,col));
while(!queue.isEmpty())
{
Coord now = queue.peek();
queue.poll();
if(now.row!=0 && !Game.gameMap[now.row-1][now.col].isMine &&Game.gameMap[now.row-1][now.col].visit)
{
Game.gameMap[now.row-1][now.col].flip();
Game.gameMap[now.row-1][now.col].visit = false;
if(Game.gameMap[now.row-1][now.col].mineAround == 0)
queue.add(new Coord(now.row - 1,now.col));
}
if(now.row!=Game.size-1 && !Game.gameMap[now.row+1][now.col].isMine && Game.gameMap[now.row+1][now.col].visit)
{
Game.gameMap[now.row+1][now.col].flip();
Game.gameMap[now.row+1][now.col].visit = false;
if(Game.gameMap[now.row+1][now.col].mineAround == 0)
queue.add(new Coord(now.row+1,now.col));
}
if(now.col!=0 && !Game.gameMap[now.row][now.col-1].isMine && Game.gameMap[now.row][now.col-1].visit)
{
Game.gameMap[now.row][now.col-1].flip();
Game.gameMap[now.row][now.col-1].visit = false;
if(Game.gameMap[now.row][now.col-1].mineAround == 0)
queue.add(new Coord(now.row,now.col-1));
}
if(now.col!=Game.size-1 && !Game.gameMap[now.row][now.col+1].isMine && Game.gameMap[now.row][now.col+1].visit)
{
Game.gameMap[now.row][now.col+1].flip();
Game.gameMap[now.row][now.col+1].visit = false;
if(Game.gameMap[now.row][now.col+1].mineAround == 0)
queue.add(new Coord(now.row,now.col+1));
}
}
}
}
});
}
void setMine()
{
isMine = true;
}
boolean flip()
{
super.setEnabled(false);
if(isMine)
{
super.setEnabled(true);
Game.setButtonImage(this);
}
else
{
if(mineAround!=0)
super.setText(""+mineAround);
Game.flipNum++;
if(Game.flipNum == Game.size*Game.size-Game.mineNum)
Game.win();
}
return isMine;
}
void add()
{
mineAround++;
}
};
public class Game{
private static final int easyModeSize = 10;
private static final int easyModeMine = 10;
private static final int normalModeSize = 10;
private static final int normalModeMine = 40;
private static final int hardModeSize = 20;
private static final int hardModeMine = 80;
private static Calendar initialTime;
private static final String url = "\\image.png";
static int flipNum;
static int size;
static int mineNum;
static int minePos[][];
static Mine gameMap[][];
static JFrame mainInterface;
static JFrame gameInterface;
static void win(){
for(int[] x:minePos)
Game.gameMap[x[0]][x[1]].flip();
Calendar endTime = Calendar.getInstance();
JDialog success = new JDialog();
success.setTitle("你赢了 用时:"+
((endTime.get(Calendar.MINUTE)-initialTime.get(Calendar.MINUTE))*60
+endTime.get(Calendar.SECOND)-initialTime.get(Calendar.SECOND))+"s");
Game.setDialogImage(success);
success.setLayout(null);
Game.setPos(success, 40, 80);
JButton restart = new JButton();
restart.setText("重新开始");
restart.setBounds(30, 10, 90, 30);
restart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0) {
gameInterface.setVisible(false);
mainInterface.setVisible(true);
success.setVisible(false);
}
}
);
success.add(restart);
success.setVisible(true);
}
static void die(){
for(int[] x:minePos)
Game.gameMap[x[0]][x[1]].flip();
JDialog dead = new JDialog();
dead.setTitle("你输了");
Game.setDialogImage(dead);
dead.setLayout(null);
Game.setPos(dead, 40, 80);
JButton restart = new JButton();
restart.setText("重新开始");
restart.setBounds(30, 10, 90, 30);
restart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0) {
gameInterface.setVisible(false);
mainInterface.setVisible(true);
dead.setVisible(false);
}
}
);
dead.add(restart);
dead.setVisible(true);
}
static void setMine(){
minePos = new int[mineNum][2];
Random rand = new Random();
for(int i = 0;i<mineNum;i++)
{
minePos[i][0] = rand.nextInt(size);
minePos[i][1] = rand.nextInt(size);
for(int j = 0;j<i;j++)
if(minePos[i][0]==minePos[j][0] && minePos[i][1]==minePos[j][1])
{
i--;
break;
}
}
}
static void setGame(String difficulty){
flipNum = 0;
gameInterface = new JFrame();
setFrameImage(gameInterface);
gameInterface.setVisible(true);
gameInterface.setTitle("扫雷"+'('+difficulty+')');
if(difficulty.equals("easy")) {
size = easyModeSize;
mineNum = easyModeMine;
}
else if(difficulty.equals("normal")){
size = normalModeSize;
mineNum = normalModeMine;
}
else
{
size = hardModeSize;
mineNum = hardModeMine;
}
setPos(gameInterface, 44*size, 44*size);
gameInterface.setLayout(new GridLayout(size,size,0,0));
setMine();
gameMap = new Mine[size][size];
for(int i = 0;i <size;i++)
for(int j = 0;j<size;j++)
{
gameMap[i][j] = new Mine(0,false,i,j);
gameMap[i][j].setFont((new Font("宋体",1,12)));
gameInterface.add(gameMap[i][j]);
}
for(int[] x:minePos)
{
gameMap[x[0]][x[1]].setMine();
if(x[0]!=0)
gameMap[x[0]-1][x[1]].add();
if(x[0]!=size-1)
gameMap[x[0]+1][x[1]].add();
if(x[1]!=0)
gameMap[x[0]][x[1]-1].add();
if(x[1]!=size-1)
gameMap[x[0]][x[1]+1].add();
if(x[0]!=0 && x[1]!=0)
gameMap[x[0]-1][x[1]-1].add();
if(x[0]!=0 && x[1]!=size-1)
gameMap[x[0]-1][x[1]+1].add();
if(x[0]!=size-1 && x[1]!=0)
gameMap[x[0]+1][x[1]-1].add();
if(x[0]!=size-1 && x[1]!=size-1)
gameMap[x[0]+1][x[1]+1].add();
}
}
static void setActionListener(JButton button,String difficulty,JFrame jf){
button.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent e) {
setGame(difficulty);
jf.setVisible(false);
initialTime = Calendar.getInstance();
}
}
);
}
static void setPos(JFrame frame,int x,int y)
{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setBounds((screenSize.width-x)/2, (screenSize.height-y)/2, x, y);
}
static void setPos(JDialog dialog,int x,int y)
{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
dialog.setBounds((screenSize.width-x)/2, (screenSize.height-y)/2, x, y);
}
static JFrame initial(){
mainInterface = new JFrame();
mainInterface.setTitle("扫雷");
setFrameImage(mainInterface);
mainInterface.setVisible(true);
mainInterface.setLayout(new GridLayout(4,1,0,0));
setPos(mainInterface,250,200);
Container container = mainInterface.getContentPane();
JLabel label = new JLabel("选择难度");
label.setFont(new Font("宋体",1,20));
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setSize(20,10);
container.add(label);
JButton easy = new JButton("简单");
setActionListener(easy,"easy",mainInterface);
mainInterface.add(easy);
JButton normal = new JButton("一般");
setActionListener(normal,"normal",mainInterface);
mainInterface.add(normal);
JButton hard = new JButton("困难");
setActionListener(hard,"hard",mainInterface);
mainInterface.add(hard);
return mainInterface;
}
public static void setButtonImage(JButton button){
ImageIcon myicon = new ImageIcon(Game.class.getResource(url));
Image image = myicon.getImage().getScaledInstance(20, 20, 20);
myicon.setImage(image);
button.setIcon(myicon);
}
public static void setFrameImage(JFrame frame) {
ImageIcon myicon = new ImageIcon(Game.class.getResource(url));
Image image = myicon.getImage().getScaledInstance(20, 20, 20);
frame.setIconImage(image);
}
public static void setDialogImage(JDialog dialog) {
ImageIcon myicon = new ImageIcon(Game.class.getResource(url));
Image image = myicon.getImage().getScaledInstance(20, 20, 20);
dialog.setIconImage(image);
}
public static void main(String[] args) {
initial();
}
}
Version1.1
优化了一些边界条件,减少了如图的情况发生(在少数情况下依旧会发生)
代码更改部分:
Mine(int num,boolean boom,int r,int c)
{
super();
isMine = boom;
visit = true;
mineAround = num;
row = r;
col = c;
super.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e) {
visit = false;
if(flip())
{
Game.die();
}
else
{
Queue<Coord> queue = new LinkedList<Coord>();
queue.add(new Coord(row,col));
while(!queue.isEmpty())
{
boolean north = false,south = false,east = false,west = false;
Coord now = queue.peek();
queue.poll();
if(now.row!=0 && !Game.gameMap[now.row-1][now.col].isMine &&Game.gameMap[now.row-1][now.col].visit)
{
Game.gameMap[now.row-1][now.col].flip();
Game.gameMap[now.row-1][now.col].visit = false;
if(Game.gameMap[now.row-1][now.col].mineAround == 0)
queue.add(new Coord(now.row - 1,now.col));
else
north = true;
}
if(now.row!=Game.size-1 && !Game.gameMap[now.row+1][now.col].isMine && Game.gameMap[now.row+1][now.col].visit)
{
Game.gameMap[now.row+1][now.col].flip();
Game.gameMap[now.row+1][now.col].visit = false;
if(Game.gameMap[now.row+1][now.col].mineAround == 0)
queue.add(new Coord(now.row+1,now.col));
else
south = true;
}
if(now.col!=0 && !Game.gameMap[now.row][now.col-1].isMine && Game.gameMap[now.row][now.col-1].visit)
{
Game.gameMap[now.row][now.col-1].flip();
Game.gameMap[now.row][now.col-1].visit = false;
if(Game.gameMap[now.row][now.col-1].mineAround == 0)
queue.add(new Coord(now.row,now.col-1));
else
west = true;
}
if(now.col!=Game.size-1 && !Game.gameMap[now.row][now.col+1].isMine && Game.gameMap[now.row][now.col+1].visit)
{
Game.gameMap[now.row][now.col+1].flip();
Game.gameMap[now.row][now.col+1].visit = false;
if(Game.gameMap[now.row][now.col+1].mineAround == 0)
queue.add(new Coord(now.row,now.col+1));
else
east = true;
}
if(north && west)
{
if(!Game.gameMap[now.row-1][now.col-1].isMine && Game.gameMap[now.row-1][now.col-1].visit)
{
Game.gameMap[now.row-1][now.col-1].flip();
}
}
if(north && east)
{
if(!Game.gameMap[now.row-1][now.col+1].isMine && Game.gameMap[now.row-1][now.col+1].visit)
{
Game.gameMap[now.row-1][now.col+1].flip();
}
}
if(south && west)
{
if(!Game.gameMap[now.row+1][now.col-1].isMine && Game.gameMap[now.row+1][now.col-1].visit)
{
Game.gameMap[now.row+1][now.col-1].flip();
}
}
if(south && east)
{
if(!Game.gameMap[now.row+1][now.col+1].isMine && Game.gameMap[now.row+1][now.col+1].visit)
{
Game.gameMap[now.row+1][now.col+1].flip();
}
}
}
}
}
});
}