扫雷游戏是一个经典的益智游戏,通过在布满雷区的网格中寻找安全路径,挑战玩家的记忆力和逻辑推理能力。自问世以来,它一直是许多程序员和技术爱好者喜爱的项目之一。今天,我们将探讨如何使用Java语言实现一个扫雷游戏。通过这个示例代码分享,不仅可以让读者了解扫雷游戏的基本原理,还能帮助那些对Java编程感兴趣的读者加深理解。
前言
windows自带的游戏《扫雷》是陪伴了无数人的经典游戏,本程序参考《扫雷》的规则进行了简化,用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想。
主要需求
1、要有难度等级,初级,中级,高级
2、由玩家逐个翻开方块,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束
3、游戏主区域由很多个方格组成。使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷。
4、用户右键可标记雷的位置
5、雷都被标记出来则胜利
主要设计
1、格子格数固定为10*10格
2、难度等级,初级:12,中级:24,高级:36
3、点击格子时,产生没有引爆的地图效果;
4、点击格子时,此格子是雷,则显示所有雷的位置,并递归清空非雷格子,结束游戏
5、实现检查所有的雷是否都被标记出来了,如果是,则胜利算法。
6、实现计时器算法,用来计时显示游戏开始多少秒
7、实现难度等级,雷数的显示
8、实现鼠标左键的实现逻辑
9、实现鼠标右键的标记逻辑
功能截图
开始界面
左键选中格子效果
左键选中雷效果
右键标记雷效果
胜利效果
代码实现
程序启动类
public class JMine extends JFrame implements MouseListener, ActionListener { private JMineArth mine; private JMineButton[][] mineButton; private GridBagConstraints constraints; private JPanel pane; private GridBagLayout gridbag; private boolean gameStarted; private static JCounter mineCounter; private static JCounter timeCounter; private Timer timer; private Timer winTimer = new Timer(); public int numMine; public int numFlaged; private JMenuBar mb; private JMenu mGame; private JMenuItem miEasy; private JMenuItem miMiddle; private JMenuItem miHard; private JMenuItem miExit; private JMenu mHelp; private JMenuItem miAbout; private JPanel controlPane; private JButton bTest; private AboutFrame about; private WinFrame winFrame; private ImageIcon[] mineNumIcon = { new ImageIcon(JMine.class.getClassLoader().getResource("blank1.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("1.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("2.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("3.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("4.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("5.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("6.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("7.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("8.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("0.gif"))}; private ImageIcon[] mineStatus = { new ImageIcon(JMine.class.getClassLoader().getResource("blank1.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("flag.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("question.gif")) }; private ImageIcon[] mineBombStatus = { new ImageIcon(JMine.class.getClassLoader().getResource("0.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("mine.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("wrongmine.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("bomb.gif")) }; private ImageIcon[] faceIcon = { new ImageIcon(JMine.class.getClassLoader().getResource("smile.gif")), new ImageIcon(JMine.class.getClassLoader().getResource("Ooo.gif")) }; // You lose private void bomb(int row, int col){ try{ //System.out.println("Bomb!"); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { mineButton[i][j].setIcon(mineBombStatus[0]); int toShow; toShow = mine.mine[i][j] != 9 ? 0 : 1; mineButton[i][j].setClickFlag(true); if (toShow == 1 && (i != row || j != col)) { mineButton[i][j].setIcon(mineBombStatus[toShow]); mineButton[i][j].setClickFlag(true); } else if (toShow == 1 && (i == row && j == col)) { mineButton[i][j].setIcon(mineBombStatus[3]); mineButton[i][j].setClickFlag(true); } else if (toShow == 0 && mineButton[i][j].getFlag() != 1) { mineButton[i][j].setEnabled(false); } else if (toShow == 0 && mineButton[i][j].getFlag() == 1) { mineButton[i][j].setIcon(mineBombStatus[2]); mineButton[i][j].setClickFlag(true); } } } timer.cancel(); }catch (Exception e){ } } // check if you win() { private boolean isWin() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if (mine.mine[i][j] == 9 && mineButton[i][j].getFlag() != 1) { return (false); } if (mine.mine[i][j] != 9 && mineButton[i][j].getFlag() == 1) { return (false); } if (mine.mine[i][j] != 9 && mineButton[i][j].getClickFlag() == false) { return (false); } } } return (true); } // You Win private void win(){ timer.cancel(); winFrame.setVisible(true); winTimer.schedule(new TimerTask(){ public void run() { while(!winFrame.getWinOk()){ } numMine = winFrame.getMineNum(); winFrame.setVisible(false); setNewGame(numMine); //System.out.println("Jerry Debug:"+numMine); this.cancel(); winFrame.setWinOk(false); } },0L); } // Constructor of the game public JMine() { super("JMine Game"); setSize(250, 350); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Insets space = new Insets(0, 0, 0, 0); // Game vars gameStarted = false; numMine = 12; numFlaged = 0; ImageIcon myIcon = new ImageIcon(JMine.class.getClassLoader().getResource("blank1.gif")); gridbag = new GridBagLayout(); constraints = new GridBagConstraints(); pane = new JPanel(); pane.setLayout(gridbag); constraints.fill = GridBagConstraints.BOTH; constraints.anchor = GridBagConstraints.CENTER; // Begin Menu Set mb = new JMenuBar(); mGame = new JMenu("Game"); miEasy = new JMenuItem("Easy"); miEasy.addActionListener(this); miMiddle = new JMenuItem("Middle"); miMiddle.addActionListener(this); miHard = new JMenuItem("Hard"); miHard.addActionListener(this); miExit = new JMenuItem("Exit"); miExit.addActionListener(this); mGame.add(miEasy); mGame.add(miMiddle); mGame.add(miHard); mGame.addSeparator(); mGame.add(miExit); mb.add(mGame); mHelp = new JMenu("Help"); miAbout = new JMenuItem("About..."); mHelp.add(miAbout); miAbout.addActionListener(this); mb.add(mHelp); this.setJMenuBar(mb); // end of Menu Set // Control Panel controlPane = new JPanel(); bTest = new JButton(faceIcon[0]); bTest.setSize(26, 27); bTest.setMargin(space); bTest.addMouseListener(this); bTest.setPressedIcon(faceIcon[1]); mineCounter = new JCounter(numMine); timeCounter = new JCounter(); controlPane.add(mineCounter); controlPane.add(bTest); controlPane.add(timeCounter); buildConstraints(constraints, 0, 0, 10, 2, 100, 100); gridbag.setConstraints(controlPane, constraints); pane.add(controlPane); // Bottons mineButton = new JMineButton[10][10]; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { mineButton[i][j] = new JMineButton(i, j, myIcon); mineButton[i][j].addMouseListener(this); mineButton[i][j].setMargin(space); buildConstraints(constraints, j, i + 3, 1, 1, 100, 100); gridbag.setConstraints(mineButton[i][j], constraints); pane.add(mineButton[i][j]); } } // Content Pane setContentPane(pane); setLocation(200, 150); setVisible(true); // About Frame about = new AboutFrame("JMine About"); winFrame = new WinFrame("You win!"); } // Set the GUI objects positions void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; } // the methods to check if there were mines, to be nested void checkMine(int row, int col){ int i, j; i = row < 0 ? 0 : row; i = i > 9 ? 9 : i; j = col < 0 ? 0 : col; j = j > 9 ? 9 : j; //System.out.println("Check Mine row:"+i + ",col:" +j); if (mine.mine[i][j] == 9) { bomb(i, j); } else if (mine.mine[i][j] == 0 && mineButton[i][j].getClickFlag() == false) { mineButton[i][j].setClickFlag(true); showLabel(i, j); for (int ii = i - 1; ii <= i + 1; ii++) for (int jj = j - 1; jj <= j + 1; jj++) checkMine(ii, jj); } else { showLabel(i, j); mineButton[i][j].setClickFlag(true); } if (isWin()) { win(); } } private void clearAll(int row, int col){ int top, bottom, left, right; top = row - 1 > 0 ? row - 1 : 0; bottom = row + 1 < 10 ? row + 1 : 9; left = col - 1 > 0 ? col - 1 : 0; right = col + 1 < 10 ? col + 1 : 9; for (int i = top; i <= bottom; i++) { for (int j = left; j <= right; j++) { if (mineButton[i][j].getFlag() != 1) checkMine(i, j); } } } private void resetAll() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { mineButton[i][j].setFlag(0); mineButton[i][j].setClickFlag(false); mineButton[i][j].setIcon(mineStatus[0]); mineButton[i][j].setEnabled(true); mineButton[i][j].setVisible(true); } } } // to flag the mine you want to flag out void flagMine(int row, int col) { //System.out.println("Jerry Arrives here!"); int i, j; i = row < 0 ? 0 : row; i = i > 9 ? 9 : i; j = col < 0 ? 0 : col; j = j > 9 ? 9 : j; if (mineButton[i][j].getFlag() == 0) { numFlaged++; } else if (mineButton[i][j].getFlag() == 1) { numFlaged--; } mineCounter.resetCounter(numMine - numFlaged >= 0 ? numMine - numFlaged : 0); mineButton[i][j].setFlag((mineButton[i][j].getFlag() + 1) % 3); showFlag(i, j); if (isWin()) { win(); } } // show the numbers of the nearby mines void showLabel(int row, int col) { //System.out.println("ShowLabel row:" + row + ",col:" + col); int toShow; toShow = mine.mine[row][col]; if (toShow != 0) { mineButton[row][col].setIcon(mineNumIcon[toShow]); mineButton[row][col].setClickFlag(true); //mineButton[row][col].setEnabled(false); } else { //mineButton[row][col].setIcon(mineNumIcon[0]); //mineButton[row][col].setClickFlag(true); mineButton[row][col].setEnabled(false); } } // circle the flag with blank, flaged, questioned void showFlag(int row, int col) { mineButton[row][col] .setIcon(mineStatus[mineButton[row][col].getFlag()]); } // the mouse events listener methods public void mouseEntered(MouseEvent e) { //System.out.println("Jerry Test"); } // method to start the new game private void startNewGame(int num, int row, int col){ mine = new JMineArth(num, row, col); //mine.printMine(); gameStarted = true; timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask(){ public void run() { timeCounter.counterAdd(); //System.out.println(timeCounter.getCounterNum()); } },1000,1000); } public void setNewGame(int num) { resetAll(); numMine = num; numFlaged = 0; gameStarted = false; mineCounter.resetCounter(numMine); timeCounter.resetCounter(0); } // the event handle to deal with the mouse click public void mouseClicked(MouseEvent e) { if (e.getSource() == bTest) { setNewGame(numMine); return; } int row, col; row = ((JMineButton) e.getSource()).getRow(); col = ((JMineButton) e.getSource()).getCol(); if (!gameStarted) { startNewGame(numMine, row, col); } if (e.getModifiers() == (InputEvent.BUTTON1_MASK + InputEvent.BUTTON3_MASK)) { //System.out.println("HA"); clearAll(row, col); } if (!mineButton[row][col].getClickFlag()) { if (e.getModifiers() == InputEvent.BUTTON1_MASK) { //System.out.println("LeftButton"); if (mineButton[row][col].getFlag() == 1) { return; } else { checkMine(row, col); } } else if (e.getModifiers() == InputEvent.BUTTON3_MASK) { //System.out.println("RightButton"); flagMine(row, col); } else { //System.out.println("MiddleButton"); } } } public void mousePressed(MouseEvent e) { //System.out.println("Jerry Press"); } public void mouseReleased(MouseEvent e) { //System.out.println("Jerry Release"); } public void mouseExited(MouseEvent e) { //System.out.println("Jerry Exited"); } public void actionPerformed(ActionEvent e) { try { if (e.getSource() == miEasy) { setNewGame(12); return; } if (e.getSource() == miMiddle) { setNewGame(24); return; } if (e.getSource() == miHard) { setNewGame(36); return; } if (e.getSource() == miExit) { System.exit(0); } if (e.getSource() == miAbout) { about.setVisible(true); } } catch (Exception ie) { } } public static void main(String [] args) { JMine jmine = new JMine(); jmine.setVisible(true); } }
地雷分布图算法类
public class JMineArth { public int [][] mine; private boolean fMineSet; JMineArth(int mineNum, int row, int col) { mine = new int[10][10]; setMine(mineNum, row, col); setMineNum(); } private void setMine(int mineNum, int Outrow, int Outcol) { int col=0, row = 0, i=0; //Math.srand(now); while (i < mineNum) { col = (int)(Math.random()*100)%10; row = (int)(Math.random()*100)%10; if (mine[col][row]==0 && (row!=Outrow || col!=Outcol || Outrow==10 )) { mine[row][col]=9; i++; } } } private void setMineNum() { for ( int i=0 ; i <10; i++) { for (int j=0; j < 10; j++) { mine[i][j]=mine[i][j]==9?9:checkMineNum(i,j); } } fMineSet = true; } private int checkMineNum(int ii,int jj) { int top,bottom, left, right, count=0; top=ii-1>0?ii-1:0; bottom=ii+1<10?ii+1:9; left=jj-1>0?jj-1:0; right=jj+1<10?jj+1:9; for (int i=top; i<=bottom; i++) { for(int j=left; j<= right; j++) { if (mine[i][j]==9) count++; } } return(count); } public void printMine() { for (int i = 0; i < 10; i++) { for (int j=0; j < 10; j++) { System.out.print(this.mine[i][j] + " "); } System.out.println(); } } public static void main(String[] args) { JMineArth mine = new JMineArth(Integer.parseInt(args[0]),Integer.parseInt(args[1]),Integer.parseInt(args[2])); mine.printMine(); } }
在线扫雷游戏试玩地址:https://www.zhanid.com/tool/saolei.html
总结
本文详细介绍了如何使用Java语言实现一个经典的扫雷游戏。通过这个示例代码分享,我们不仅展示了游戏的基本规则和逻辑,还深入探讨了Java编程中的关键概念和技术细节。希望读者通过阅读这篇文章,不仅能掌握扫雷游戏的实现方法,还能在Java编程方面有所收获。无论是新手还是有一定经验的开发者,都能从中找到有价值的知识和技巧,激发对编程和游戏开发的兴趣。
本文来源于#小虚竹and掘金,由@蜜芽 整理发布。如若内容造成侵权/违法违规/事实不符,请联系本站客服处理!
该文章观点仅代表作者本人,不代表本站立场。本站不承担相关法律责任。
如若转载,请注明出处:https://www.zhanid.com/biancheng/1399.html