Java制作一款扫雷游戏
题目
- 扫雷游戏分为初级、中级和高级三个级别,初级模式99个方块中有10个雷、中级模式1616个方块中有40个雷、高级模式16*30个方块中有99个雷,单击游戏菜单可以选择“开局”、“初级”、“中级”、“高级”或“退出”。
- 选择级别后出现相应雷区,若不选择默认初级模式,用户使用鼠标左键单击雷区中任一方块开始计时。
- 用户要揭开某个方块,单击它。若所揭方块下有雷,用户便输了这一局,若所揭方块下无雷,则显示一个数字,该数字代表方块的周围的8个方块中共有多少颗雷。
- 如果用户认为某个方块下埋着雷,右键单击该方块,方块将出现一个扫雷标记。用户每标记出一个扫雷标记(无论用户是否正确),程序将显示的剩余雷数减少一个。
- 准确地找出所有雷,将取得该局游戏的胜利。否则,将会弹出失败框。
运行结果
项目结构
data
Block
import javax.swing.ImageIcon;
public class Block {
String name;
int aroundMineNumber;
ImageIcon mineIcon;
public boolean isMine=false;
boolean isMark=false;
boolean isOpen=false;
ViewForBlock blockView;
public void setName(String name) {
this.name=name;
}
public void setAroundMineNumber(int n) {
aroundMineNumber=n;
}
public int getAroundMineNumber() {
return aroundMineNumber;
}
public String getName() {
return name;
}
public boolean isMine() {
return isMine;
}
public void setIsMine(boolean b) {
isMine=b;
}
public void setMineIcon(ImageIcon icon){
mineIcon=icon;
}
public ImageIcon getMineicon(){
return mineIcon;
}
public boolean getIsOpen() {
return isOpen;
}
public void setIsOpen(boolean p) {
isOpen=p;
}
public boolean getIsMark() {
return isMark;
}
public void setIsMark(boolean m) {
isMark=m;
}
public void setBlockView(ViewForBlock view){
blockView = view;
blockView.acceptBlock(this);
}
public ViewForBlock getBlockView(){
return blockView ;
}
}
LayMines
import java.util.LinkedList;
import javax.swing.ImageIcon;
public class LayMines {
ImageIcon mineIcon;
public LayMines() {
mineIcon=new ImageIcon("扫雷图片/mine.gif");
}
public void initBlock(Block [][] block){
for(int i=0;i<block.length;i++) {
for(int j=0;j<block[i].length;j++)
block[i][j].setIsMine(false);
}
}
public void layMinesForBlock(Block [][] block,int mineCount){
initBlock(block);
int row=block.length;
int column=block[0].length;
LinkedList<Block> list=new LinkedList<Block>();
for(int i=0;i<row;i++) {
for(int j=0;j<column;j++)
list.add(block[i][j]);
}
while(mineCount>0){
int size=list.size();
int randomIndex=(int)(Math.random()*size);
Block b=list.get(randomIndex);
b.setIsMine(true);
b.setName("雷");
b.setMineIcon(mineIcon);
list.remove(randomIndex);
mineCount--;
}
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(block[i][j].isMine()){
block[i][j].setIsOpen(false);
block[i][j].setIsMark(false);
}
else {
int mineNumber=0;
for(int k=Math.max(i-1,0);k<=Math.min(i+1,row-1);k++) {
for(int t=Math.max(j-1,0);t<=Math.min(j+1,column-1);t++){
if(block[k][t].isMine())
mineNumber++;
}
}
block[i][j].setIsOpen(false);
block[i][j].setIsMark(false);
block[i][j].setName(""+mineNumber);
block[i][j].setAroundMineNumber(mineNumber);
}
}
}
}
}
PeopleScoutMine
import java.util.Stack;
public class PeopleScoutMine {
public Block [][] block;
Stack<Block> notMineBlock;
int m,n ;
int row,colum;
int mineCount;
public PeopleScoutMine(){
notMineBlock = new Stack<Block>();
}
public void setBlock(Block [][] block,int mineCount){
this.block = block;
this.mineCount = mineCount;
row = block.length;
colum = block[0].length;
}
public Stack<Block> getNoMineAroundBlock(Block bk){
notMineBlock.clear();
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
if(bk == block[i][j]){
m=i;
n=j;
break;
}
}
}
if(!bk.isMine()) {
show(m,n);
}
return notMineBlock;
}
public void show(int m,int n) {
if(block[m][n].getAroundMineNumber()>0&&block[m][n].getIsOpen()==false){
block[m][n].setIsOpen(true);
notMineBlock.push(block[m][n]);
return;
}
else if(block[m][n].getAroundMineNumber()==0&&block[m][n].getIsOpen()==false){
block[m][n].setIsOpen(true);
notMineBlock.push(block[m][n]);
for(int k=Math.max(m-1,0);k<=Math.min(m+1,row-1);k++) {
for(int t=Math.max(n-1,0);t<=Math.min(n+1,colum-1);t++)
show(k,t);
}
}
}
public boolean verifyWin(){
boolean isOK = false;
int number=0;
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
if(block[i][j].getIsOpen()==false)
number++;
}
}
if(number==mineCount){
isOK =true;
}
return isOK;
}
}
RecordOrShowRecord
import java.sql.*;
public class RecordOrShowRecord{
Connection con;
String tableName ;
int heroNumber = 3;
public RecordOrShowRecord(){
try{Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
}
catch(Exception e){}
}
public void setTable(String str){
tableName = "t_"+str;
connectDatabase();
try {
Statement sta = con.createStatement();
String SQL="create table "+tableName+
"(p_name varchar(50) ,p_time int)";
sta.executeUpdate(SQL);
con.close();
}
catch(SQLException e) {
}
}
public boolean addRecord(String name,int time){
boolean ok = true;
if(tableName == null)
ok = false;
int amount = verifyScore(time);
if(amount >= heroNumber) {
ok = false;
}
else {
connectDatabase();
try {
String SQL ="insert into "+tableName+" values(?,?)";
PreparedStatement sta = con.prepareStatement(SQL);
sta.setString(1,name);
sta.setInt(2,time);
sta.executeUpdate();
con.close();
ok = true;
}
catch(SQLException e) {
ok = false;
}
}
return ok;
}
public String [][] queryRecord(){
if(tableName == null)
return null;
String [][] record = null;
Statement sql;
ResultSet rs;
try {
sql=
con.createStatement
(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
String str = "select * from "+tableName+" order by p_time ";
rs=sql.executeQuery(str);
boolean boo =rs.last();
if(boo == false)
return null;
int recordAmount =rs.getRow();
record = new String[recordAmount][2];
rs.beforeFirst();
int i=0;
while(rs.next()) {
record[i][0] = rs.getString(1);
record[i][1] = rs.getString(2);
i++;
}
con.close();
}
catch(SQLException e) {}
return record;
}
private void connectDatabase(){
try{
String uri ="jdbc:derby:record;create=true";
con=DriverManager.getConnection(uri);
}
catch(Exception e){}
}
private int verifyScore(int time){
if(tableName == null)
return Integer.MAX_VALUE ;
connectDatabase();
Statement sql;
ResultSet rs;
int amount = 0;
String str =
"select * from "+tableName+" where p_time < "+time;
try {
sql=con.createStatement();
rs=sql.executeQuery(str);
while(rs.next()){
amount++;
}
con.close();
}
catch(SQLException e) {}
return amount;
}
}
ViewForBlock
public interface ViewForBlock {
public void acceptBlock(Block block);
public void setDataOnView();
public void seeBlockNameOrIcon();
public void seeBlockCover();
public Object getBlockCover();
}
gui
AppWindow
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import ch8.view.MineArea;
import ch8.view.ShowRecord;
public class AppWindow extends JFrame implements MenuListener,ActionListener{
JMenuBar bar;
JMenu fileMenu;
JMenu gradeOne,gradeTwo,gradeThree;
JMenuItem gradeOneList,gradeTwoList,gradeThreeList;
MineArea mineArea=null;
ShowRecord showHeroRecord=null;
public AppWindow(){
bar=new JMenuBar();
fileMenu=new JMenu("扫雷游戏");
gradeOne=new JMenu("初级");
gradeTwo=new JMenu("中级");
gradeThree=new JMenu("高级");
gradeOneList=new JMenuItem("初级英雄榜");
gradeTwoList=new JMenuItem("中级英雄榜");
gradeThreeList=new JMenuItem("高级英雄榜");
gradeOne.add(gradeOneList);
gradeTwo.add(gradeTwoList);
gradeThree.add(gradeThreeList);
fileMenu.add(gradeOne);
fileMenu.add(gradeTwo);
fileMenu.add(gradeThree);
bar.add(fileMenu);
setJMenuBar(bar);
gradeOne.addMenuListener(this);
gradeTwo.addMenuListener(this);
gradeThree.addMenuListener(this);
gradeOneList.addActionListener(this);
gradeTwoList.addActionListener(this);
gradeThreeList.addActionListener(this);
mineArea=new MineArea(9,9,10,gradeOne.getText());
add(mineArea,BorderLayout.CENTER);
showHeroRecord=new ShowRecord();
setBounds(300,100,500,450);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
validate();
}
public void menuSelected(MenuEvent e){
if(e.getSource()==gradeOne){
mineArea.initMineArea(9,9,10,gradeOne.getText());
validate();
}
else if(e.getSource()==gradeTwo){
mineArea.initMineArea(16,16,40,gradeTwo.getText());
validate();
}
else if(e.getSource()==gradeThree){
mineArea.initMineArea(22,30,99,gradeThree.getText());
validate();
}
}
public void menuCanceled(MenuEvent e){}
public void menuDeselected(MenuEvent e){}
public void actionPerformed(ActionEvent e){
if(e.getSource()==gradeOneList){
showHeroRecord.setGrade(gradeOne.getText());
showHeroRecord.showRecord();
}
else if(e.getSource()==gradeTwoList){
showHeroRecord.setGrade(gradeTwo.getText());
showHeroRecord.showRecord();
}
else if(e.getSource()==gradeThreeList){
showHeroRecord.setGrade(gradeThree.getText());
showHeroRecord.showRecord();
}
}
public static void main(String args[]){
new AppWindow();
}
}
test
Apptest
import ch8.data.*;
import java.util.Stack;
public class AppTest {
public static void main(String [] args) {
Block block[][] = new Block[5][10];
for(int i=0;i<block.length;i++) {
for(int j = 0;j<block[i].length;j++) {
block[i][j] = new Block();
}
}
LayMines layMines = new LayMines();
PeopleScoutMine peopleScoutMine = new PeopleScoutMine();
layMines.layMinesForBlock(block,10);
System.out.println("雷区情况:");
intputShow(block);
peopleScoutMine.setBlock(block,10);
Stack<Block> stack = peopleScoutMine.getNoMineAroundBlock(block[0][0]);
if(block[0][0].isMine()){
System.out.println("我的天啊,踩着地雷了啊");
return;
}
System.out.println("扫雷情况:");
intputProcess(block,stack);
System.out.println("成功了吗:"+peopleScoutMine.verifyWin());
if(block[3][3].isMine()){
System.out.println("我的天啊,踩着地雷了啊");
return;
}
stack = peopleScoutMine.getNoMineAroundBlock(block[3][3]);
System.out.println("扫雷情况:");
intputProcess(block,stack);
System.out.println("成功了吗:"+peopleScoutMine.verifyWin());
}
static void intputProcess(Block [][] block,Stack<Block> stack){
int k = 0;
for(int i=0;i<block.length;i++) {
for(int j = 0;j<block[i].length;j++){
if(!stack.contains(block[i][j])&&block[i][j].getIsOpen()==false){
System.out.printf("%2s","■ ");
}
else {
int m = block[i][j].getAroundMineNumber();
System.out.printf("%2s","□"+m);
}
}
System.out.println();
}
}
static void intputShow(Block [][] block){
int k = 0;
for(int i=0;i<block.length;i++) {
for(int j = 0;j<block[i].length;j++){
if(block[i][j].isMine()){
System.out.printf("%2s","#");
}
else {
int m = block[i][j].getAroundMineNumber();
System.out.printf("%2s",m);
}
}
System.out.println();
}
}
}
view
BlockView
import javax.swing.*;
import java.awt.*;
import ch8.data.*;
public class BlockView extends JPanel implements ViewForBlock{
JLabel blockNameOrIcon;
JButton blockCover;
CardLayout card;
Block block ;
BlockView(){
card=new CardLayout();
setLayout(card);
blockNameOrIcon=new JLabel("",JLabel.CENTER);
blockNameOrIcon.setHorizontalTextPosition(AbstractButton.CENTER);
blockNameOrIcon.setVerticalTextPosition(AbstractButton.CENTER);
blockCover=new JButton();
add("cover",blockCover);
add("view",blockNameOrIcon);
}
public void acceptBlock(Block block){
this.block = block;
}
public void setDataOnView(){
if(block.isMine()){
blockNameOrIcon.setText(block.getName());
blockNameOrIcon.setIcon(block.getMineicon());
}
else {
int n=block.getAroundMineNumber();
if(n>=1)
blockNameOrIcon.setText(""+n);
else
blockNameOrIcon.setText(" ");
}
}
public void seeBlockNameOrIcon(){
card.show(this,"view");
validate();
}
public void seeBlockCover(){
card.show(this,"cover");
validate();
}
public JButton getBlockCover(){
return blockCover;
}
}
MineArea
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import ch8.data.*;
import java.util.Stack;
public class MineArea extends JPanel implements ActionListener,MouseListener{
JButton reStart;
Block [][] block;
BlockView [][] blockView;
LayMines lay;
PeopleScoutMine peopleScoutMine;
int row,colum,mineCount,markMount;
ImageIcon mark;
String grade;
JPanel pCenter,pNorth;
JTextField showTime,showMarkedMineCount;
Timer time;
int spendTime=0;
Record record;
PlayMusic playMusic;
public MineArea(int row,int colum,int mineCount,String grade) {
record = new Record();
reStart=new JButton("重新开始");
mark=new ImageIcon("扫雷图片/mark.png");
time=new Timer(1000,this);
showTime=new JTextField(5);
showMarkedMineCount=new JTextField(5);
showTime.setHorizontalAlignment(JTextField.CENTER);
showMarkedMineCount.setHorizontalAlignment(JTextField.CENTER);
showMarkedMineCount.setFont(new Font("Arial",Font.BOLD,16));
showTime.setFont(new Font("Arial",Font.BOLD,16));
pCenter=new JPanel();
pNorth=new JPanel();
lay=new LayMines();
peopleScoutMine = new PeopleScoutMine();
initMineArea(row,colum,mineCount,grade);
reStart.addActionListener(this);
pNorth.add(new JLabel("剩余雷数(千万别弄错啊):"));
pNorth.add(showMarkedMineCount);
pNorth.add(reStart);
pNorth.add(new JLabel("用时:"));
pNorth.add(showTime);
setLayout(new BorderLayout());
add(pNorth,BorderLayout.NORTH);
add(pCenter,BorderLayout.CENTER);
playMusic = new PlayMusic();
playMusic.setClipFile("扫雷图片/mine.wav");
}
public void initMineArea(int row,int colum,int mineCount,String grade){
pCenter.removeAll();
spendTime=0;
markMount=mineCount;
this.row=row;
this.colum=colum;
this.mineCount=mineCount;
this.grade=grade;
block=new Block[row][colum];
for(int i=0;i<row;i++){
for(int j=0;j<colum;j++)
block[i][j]=new Block();
}
lay.layMinesForBlock(block,mineCount);
peopleScoutMine.setBlock(block,mineCount);
blockView=new BlockView[row][colum];
pCenter.setLayout(new GridLayout(row,colum));
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
blockView[i][j]=new BlockView();
block[i][j].setBlockView(blockView[i][j]);
blockView[i][j].setDataOnView();
pCenter.add(blockView[i][j]);
blockView[i][j].getBlockCover().addActionListener(this);
blockView[i][j].getBlockCover().addMouseListener(this);
blockView[i][j].seeBlockCover();
blockView[i][j].getBlockCover().setEnabled(true);
blockView[i][j].getBlockCover().setIcon(null);
}
}
showMarkedMineCount.setText(""+markMount);
repaint();
}
public void setRow(int row){
this.row=row;
}
public void setColum(int colum){
this.colum=colum;
}
public void setMineCount(int mineCount){
this.mineCount=mineCount;
}
public void setGrade(String grade) {
this.grade=grade;
}
public void actionPerformed(ActionEvent e) {
if(e.getSource()!=reStart&&e.getSource()!=time) {
time.start();
int m=-1,n=-1;
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
if(e.getSource()==blockView[i][j].getBlockCover()){
m=i;
n=j;
break;
}
}
}
if(block[m][n].isMine()) {
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
blockView[i][j].getBlockCover().setEnabled(false);
if(block[i][j].isMine())
blockView[i][j].seeBlockNameOrIcon();
}
}
time.stop();
spendTime=0;
markMount=mineCount;
playMusic.playMusic();
}
else {
Stack<Block> notMineBlock =peopleScoutMine.getNoMineAroundBlock(block[m][n]);
while(!notMineBlock.empty()){
Block bk = notMineBlock.pop();
ViewForBlock viewforBlock = bk.getBlockView();
viewforBlock.seeBlockNameOrIcon();
System.out.println("ookk");
}
}
}
if(e.getSource()==reStart) {
initMineArea(row,colum,mineCount,grade);
repaint();
validate();
}
if(e.getSource()==time){
spendTime++;
showTime.setText(""+spendTime);
}
if(peopleScoutMine.verifyWin()) {
time.stop();
record.setGrade(grade);
record.setTime(spendTime);
record.setVisible(true);
}
}
public void mousePressed(MouseEvent e){
JButton source=(JButton)e.getSource();
for(int i=0;i<row;i++) {
for(int j=0;j<colum;j++) {
if(e.getModifiers()==InputEvent.BUTTON3_MASK&&
source==blockView[i][j].getBlockCover()){
if(block[i][j].getIsMark()) {
source.setIcon(null);
block[i][j].setIsMark(false);
markMount=markMount+1;
showMarkedMineCount.setText(""+markMount);
}
else{
source.setIcon(mark);
block[i][j].setIsMark(true);
markMount=markMount-1;
showMarkedMineCount.setText(""+markMount);
}
}
}
}
}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
}
PlayMusic
import java.net.URI;
import java.net.URL;
import java.io.File;
import java.applet.Applet;
import java.applet.AudioClip;
public class PlayMusic implements Runnable {
String musicName;
Thread threadPlay;
AudioClip clip = null;
public PlayMusic(){
threadPlay = new Thread(this);
}
public void run() {
clip.play();
}
public void playMusic(){
threadPlay = new Thread(this);
try{
threadPlay.start();
}
catch(Exception exp) {}
}
public void setClipFile(String name){
musicName = name;
if(musicName == null)
musicName = "扫雷图像/mine.wav";
File file=new File(musicName);
try { URI uri=file.toURI();
URL url=uri.toURL();
clip=Applet.newAudioClip(url);
}
catch(Exception ee){}
}
}
Record
import javax.swing.*;
import java.awt.event.*;
import ch8.data.RecordOrShowRecord;
public class Record extends JDialog implements ActionListener{
int time=0;
String grade=null;
String key=null;
String message=null;
JTextField textName;
JLabel label=null;
JButton confirm,cancel;
public Record(){
setTitle("记录你的成绩");
this.time=time;
this.grade=grade;
setBounds(100,100,240,160);
setResizable(false);
setModal(true);
confirm=new JButton("确定");
cancel=new JButton("取消");
textName=new JTextField(8);
textName.setText("匿名");
confirm.addActionListener(this);
cancel.addActionListener(this);
setLayout(new java.awt.GridLayout(2,1));
label=new JLabel("输入您的大名看是否可上榜");
add(label);
JPanel p=new JPanel();
p.add(textName);
p.add(confirm);
p.add(cancel);
add(p);
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
}
public void setGrade(String grade){
this.grade=grade;
}
public void setTime(int time){
this.time=time;
}
public void actionPerformed(ActionEvent e){
if(e.getSource()==confirm){
String name = textName.getText();
writeRecord(name,time);
setVisible(false);
}
if(e.getSource()==cancel){
setVisible(false);
}
}
public void writeRecord(String name,int time){
RecordOrShowRecord rd = new RecordOrShowRecord();
rd.setTable(grade);
boolean boo= rd.addRecord(name,time);
if(boo){
JOptionPane.showMessageDialog
(null,"恭喜您,上榜了","消息框", JOptionPane.WARNING_MESSAGE);
}
else {
JOptionPane.showMessageDialog
(null,"成绩不能上榜","消息框", JOptionPane.WARNING_MESSAGE);
}
}
}
ShowRecord
import java.awt.*;
import javax.swing.*;
import ch8.data.RecordOrShowRecord;
public class ShowRecord extends JDialog {
String [][] record;
JTextArea showMess;
RecordOrShowRecord rd;
public ShowRecord() {
rd = new RecordOrShowRecord();
showMess = new JTextArea();
showMess.setFont(new Font("楷体",Font.BOLD,15));
add(new JScrollPane(showMess));
setTitle("显示英雄榜");
setBounds(400,200,400,300);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void setGrade(String grade){
rd.setTable(grade);
}
public void setRecord(String [][]record){
this.record=record;
}
public void showRecord() {
showMess.setText(null);
record = rd.queryRecord();
if(record == null ) {
JOptionPane.showMessageDialog
(null,"没人上榜呢","消息框", JOptionPane.WARNING_MESSAGE);
}
else {
for(int i =0 ;i<record.length;i++){
int m = i+1;
showMess.append("\n英雄"+m+":"+record[i][0]+" "+"成绩:"+record[i][1]);
showMess.append("\n--------------------------------");
}
setVisible(true);
}
}
}