扫雷小游戏_java 扫雷小游戏 - CSDN
精华内容
参与话题
  • JAVA简单实现扫雷小游戏 这两天学校外面来人教java基础,学习一下,自己试着做了一个扫雷小游戏,记录一下子学习过程。(我觉得自己不是很懂类和对象),敲出来的代码结构混乱,希望路过的大虾不吝啬的留下些代码...

    JAVA简单实现扫雷小游戏

    这两天学校外面来人教java基础,学习一下,自己试着做了一个扫雷小游戏,记录一下子学习过程。(我觉得自己不是很懂类和对象,基础没怎么看),敲出来的代码结构混乱,希望路过的大虾不吝啬的留下些代码改进的意见或是编写代码要注意的地方,感谢U•ェ•*U

    效果图

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    我的敲代码过程(想到什么敲什么)

    搭界面

    这里用到的变量都是需要在多个地方使用的,所以我定义成了全局变量

    // 使用到的变量
    	private int matrix = 9; // matrix*matrix 矩阵,规定了页面上的按钮数量
    	private int mineNum = 10; // 雷的数量
    	private int[][] counts = new int[matrix][matrix]; // 按钮下对应的雷数
    	private Color clickedColor = Color.LIGHT_GRAY; // 已经被点击的按钮的颜色
    	private Color bombColor = Color.yellow; // 雷爆炸的颜色
    	private Color mineColor = Color.white; // 布雷区默认的颜色
    	// 使用到的全局控件
    	private JFrame jf = new JFrame("扫雷小游戏");    //创建一个JFrame对象,存放整个窗体
    	private JPanel jp = new JPanel(); // 创建JPanel对象,中间容器,先存放其中,再存放到窗体中
    	private TestTimer testTimer =new TestTimer();
    	private Timer tme =new Timer(1000,testTimer);
    	private int tmeCount = 0;
    	private JLabel gameTime = new JLabel("00"); // 游戏时间
    	private JButton[][] buttons = new JButton[matrix][matrix]; // 页面上的按钮组(游戏主体)
    

    从效果图中可以看出我把窗体分成了两个部分,头部的菜单区域和游戏主题区域

    1. 头部菜单区域
     private void addTopMenu() {
            JLabel levelLabel = new JLabel("游戏等级"); // 游戏等级
        	gameTime.setBackground(Color.yellow); // 设置标签颜色
        	gameTime.setOpaque(true); // 是否不透明,不设没颜色。。。。
        	JButton resetButton = new JButton("新对局"); // 重置按钮
        	resetButton.addActionListener(new ResetGame());
        	String[] listData = new String[]{"9x9,10", "16x16,30", "30x30,99"};
        	JComboBox<String> gameLevel= new JComboBox<String>(listData);    //创建JComboBox
        	gameLevel.addItemListener(new ItemListener() {
        		 @Override
                 public void itemStateChanged(ItemEvent e) {
                     if (e.getStateChange() == ItemEvent.SELECTED) {
                         // 下拉框选项
                         if (e.getItem() == "9x9,10") {
                        	 matrix = 9;
                        	 mineNum = 10;
                         } else if (e.getItem() == "16x16,30") {
                        	 matrix = 16;
                        	 mineNum = 30;
                         } else if (e.getItem() == "30x30,99") {
                        	 matrix = 30;
                        	 mineNum = 99;
                         }
                     }
                 }
        	});
        	JPanel topMenu = new JPanel(); 
        	topMenu.add(levelLabel); 
        	topMenu.add(gameLevel); 
        	topMenu.add(gameTime); 
        	topMenu.add(resetButton); 
        	jf.add(topMenu, BorderLayout.NORTH);
        }
    
    1. 游戏主体(雷区)
    private void addButtons() {
        	// 先清空雷区
        	jp.removeAll();
        	jp.setLayout(new GridLayout(matrix,matrix,0,0)); // 采用网格布局
        	buttons = new JButton[matrix][matrix];
        	// 添加按钮组
        	for(int i=0;i<matrix;i++) {
        		for(int j=0;j<matrix;j++) {
        			JButton button = new JButton();
            		button.setBackground(mineColor);
            		button.setOpaque(true); //设置颜色的必选项
            		button.setMargin(new Insets(0, 0, 0, 0)); //设置按钮边距
            		button.addMouseListener(new MouseListener() {
            			public void mouseReleased(MouseEvent e)
            			{
            				//System.out.println("mouseReleased---鼠标放开事件");
            			}
            			public void mousePressed(MouseEvent e)
            			{
            				//System.out.println("mousePressed---鼠标按下事件");
            			} 
            			public void mouseExited(MouseEvent e)
            			{
            				//System.out.println("mouseExited---鼠标移出按钮区域");
            			}
            			public void mouseEntered(MouseEvent e)
            			{
            				//System.out.println("mouseEntered---鼠标移入按钮区域");
            			}
            			public void mouseClicked(MouseEvent e)
            			{
            				if(e.getButton()==e.BUTTON1 && ((JButton)e.getSource()).isEnabled() == true && ((JButton)e.getSource()).getText() != "?")
            				{
            					//System.out.println("鼠标左点击事件");
            					// 游戏主体按钮的事件触发
        						tme.start(); // 计时开始
        						boolean flag = true; // 标记是否需要判断游戏成功
        						JButton button = (JButton)e.getSource();
        						for (int i=0;i<matrix;i++) {
        							for (int j=0;j<matrix;j++) {
        								if (buttons[i][j] == button) {
        									if (counts[i][j] == 99) {
        										// 踩雷了,游戏结束
        										gameOver();
        										flag = false;
        										break;
        									}
        									if (counts[i][j] == 0) {
        										// 是0,调用递归方法,寻找周围所有的0
        										isZero(i,j);
        										break;
        									}
        									// 显示具体的数字
        									buttons[i][j].setBackground(clickedColor);
        									buttons[i][j].setText(String.valueOf(counts[i][j]));
        								}
            						}
        						}
        						// 检查是否找出了所有的非雷区域
        						if (flag) {
        							isEnd();
        						}
            				}
            				if(e.getButton()==e.BUTTON3)
            				{
            					//System.out.println("鼠标右点击事件");
            					if (((JButton)e.getSource()).getText() == "" && ((JButton)e.getSource()).getBackground() == mineColor) {
            						((JButton)e.getSource()).setText("?");
            					} else {
            						if (((JButton)e.getSource()).getText() == "?") {
                						((JButton)e.getSource()).setText("");
                					}
            					}
            				}
            				if(e.getButton()==e.BUTTON2)
            				{
            					// 预加载周围八个的内容
            					JButton button = (JButton)e.getSource();
        						for (int i=0;i<matrix;i++) {
        							for (int j=0;j<matrix;j++) {
        								if (buttons[i][j] == button) {
        									// 找到当前被点击的按钮
        									if(buttons[i][j].getBackground() == clickedColor) {
        										// 只能是已经显示了的按钮
        										// 查看周围八个格子的内容,如果有“?”,就显示剩余格子的内容
        										int count = 0; // 周围“?”的数量,判断是否需要显示周围内容
        										if (i>0   && j>0 && 			buttons[i-1][j-1].getText() == "?") count++;
        						    			if (i>0   && 					buttons[i-1][j].getText() == "?" ) count++;
        						    			if (i>0   && j<matrix-1 && 		buttons[i-1][j+1].getText() == "?") count++;
        						    			if (j>0   && 					buttons[i][j-1].getText() == "?" ) count++;
        						    			if (j<matrix-1 && 				buttons[i][j+1].getText() == "?" ) count++;
        						    			if (i<matrix-1 && j>0 && 		buttons[i+1][j-1].getText() == "?" ) count++;
        						    			if (i<matrix-1 && 				buttons[i+1][j].getText() == "?" ) count++;
        						    			if (j<matrix-1 && i<matrix-1 &&	buttons[i+1][j+1].getText() == "?" ) count++;
        						    			//
        						    			// 当周围标记了雷的数量与当前按钮上的值一样,就展开周围内容
        						    			if(count == Integer.valueOf(buttons[i][j].getText())) {
        						    				// 显示周围八个内容,是雷就结束游戏,不是就展开
        						    				if (i>0 && j>0 && 				buttons[i-1][j-1].getBackground() == mineColor && buttons[i-1][j-1].getText() != "?") {if (counts[i-1][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i-1,j-1);}}
            						    			if (i>0 && 						buttons[i-1][j].getBackground() == mineColor && 	buttons[i-1][j].getText() != "?") 	{if (counts[i-1][j] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i-1,j);}}
            						    			if (i>0 && j<matrix-1 && 		buttons[i-1][j+1].getBackground() == mineColor && buttons[i-1][j+1].getText() != "?") {if (counts[i-1][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i-1,j+1);}}
            						    			if (j>0 && 						buttons[i][j-1].getBackground() == mineColor && 	buttons[i][j-1].getText() != "?") 	{if (counts[i][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i,j-1);}}
            						    			if (j<matrix-1 && 				buttons[i][j+1].getBackground() == mineColor && 	buttons[i][j+1].getText() != "?") 	{if (counts[i][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i,j+1);}}
            						    			if (i<matrix-1 && j>0 && 		buttons[i+1][j-1].getBackground() == mineColor && buttons[i+1][j-1].getText() != "?") {if (counts[i+1][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i+1,j-1);}}
            						    			if (i<matrix-1 && 				buttons[i+1][j].getBackground() == mineColor && 	buttons[i+1][j].getText() != "?") 	{if (counts[i+1][j] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i+1,j);}}
            						    			if (j<matrix-1 && i<matrix-1 &&	buttons[i+1][j+1].getBackground() == mineColor && buttons[i+1][j+1].getText() != "?") {if (counts[i+1][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i+1,j+1);}}
        						    			}
        									}
        								}
        							}
        						}
            				}
            			}
            		});
            		buttons[i][j] = button;
            		jp.add(button);
        		}
        	}
        	jf.add(jp, BorderLayout.CENTER); // 将JPanel中间容器添加到JFrame窗体中
        }
    

    游戏逻辑方法

    1. burieMine() 埋雷
     private void burieMine () {
        	// 先清空所有的雷
        	counts = new int[matrix][matrix];
        	// 埋雷
        	for(int i=0;i<mineNum;i++) {
        		Random r = new Random(); // 随机获取一个位置
        		int x = r.nextInt(matrix);
        		int y = r.nextInt(matrix);
        		if (counts[x][y] == 99) {
        			// 如果已经设置为雷,就跳过
        			i--;
        			continue;
        		}
        		counts[x][y] = 99; // 99表示是雷
        	}
        }
    
    1. mineCount() 统计对应按钮下周围雷的数量
    private void mineCount () {
        	// 统计雷的数量
        	// 判断方法:寻找九宫格中目标周围8个的内容
        	int num; // 用来统计目标周围雷的数量
        	for(int i=0;i<matrix;i++) {
        		for(int j=0;j<matrix;j++) {
        			if (counts[i][j] == 99) continue; // 如果是雷就跳过
        			num = 0;		
    //    			(i-1,j-1)  (i-1,j)  (i-1,j+1)
    //    			(i,j-1)    (i,j)    (i, j+1)
    //    			(i+1,j-1)  (i+1,j)	(i+1,j+1)
        			// 防止数组下标越界
        			if (i>0   && j>0 && 			counts[i-1][j-1] == 99) num++;
        			if (i>0   && 					counts[i-1][j] == 99 ) num++;
        			if (i>0   && j<matrix-1 && 			counts[i-1][j+1] == 99) num++;
        			if (j>0   && 					counts[i][j-1] == 99) num++;
        			if (j<matrix-1 && 				counts[i][j+1] == 99) num++;
        			if (i<matrix-1 && j>0 && 		counts[i+1][j-1] == 99) num++;
        			if (i<matrix-1 && 				counts[i+1][j] == 99) num++;
        			if (j<matrix-1 && i<matrix-1 &&	counts[i+1][j+1] == 99) num++;
        			counts[i][j] = num; // 赋值到目标位置			
        		}
        	}
        }
    
    1. gameOver() 游戏结束
    private void gameOver() {
    		tme.stop();
    		// 游戏结束,显示所有内容
    		for (int i=0;i<matrix;i++) {
    			for (int j=0;j<matrix;j++) {
    				if (counts[i][j] == 99) { // 如果是雷就显示雷
    					buttons[i][j].setText("雷");
    					buttons[i][j].setBackground(bombColor);
    				} else {
    					if (counts[i][j] == 0) { // 如果是0就显示为空
    						buttons[i][j].setText("");
    					} else {
    						buttons[i][j].setText(String.valueOf(counts[i][j]));
    					}
    					buttons[i][j].setBackground(clickedColor);
    				}
    				buttons[i][j].setEnabled(false); // 设置按钮不可用
    			}
    		}
    		String msg = "坚持了" + String.valueOf(tmeCount) + "秒";
    		JOptionPane.showMessageDialog(jf, msg, "游戏结束", JOptionPane.ERROR_MESSAGE);
    	}
    
    1. isZero(int i, int j) // 如果是0也就是空(即周围没有雷),就打开周围不是雷的按钮
    private void isZero(int i, int j) {
        	// 递归实现寻找周围的0,
        	// 结束条件:1.已经被点击(或显示)的按钮(按钮颜色改变为了橙色了的按钮)
        	//			2.遇到了雷
        	//			3.遇到了数字
        	if (buttons[i][j].getBackground() == clickedColor) return;
        	if (counts[i][j] == 0) {
        		buttons[i][j].setText("");
        		buttons[i][j].setBackground(clickedColor);
        		isEnd();
        	} else {
        		if (counts[i][j] == 99) {
        			return;
        		} else {
        			buttons[i][j].setText(String.valueOf(counts[i][j]));
            		buttons[i][j].setBackground(clickedColor);
            		isEnd();
            		return;
        		}	
        	}
        	// 查看目标周围八格
        	if (i>0   && j>0 ) isZero(i-1,j-1);
    		if (i>0) isZero(i-1,j);
    		if (i>0   && j<matrix-1 ) isZero(i-1,j+1);
    		if (j>0) isZero(i,j-1);
    		if (j<matrix-1) isZero(i,j+1);
    		if (i<matrix-1 && j>0) isZero(i+1,j-1);
    		if (i<matrix-1)  isZero(i+1,j);
    		if (j<matrix-1 && i<matrix-1) isZero(i+1,j+1);
        }
    
    1. isEnd() 判断是否找出了所有的非雷单位,判断方式:页面已点击的按钮的数量 = 雷区按钮总数量 - 雷的数量
    private void isEnd() {
        	// 游戏完成,找出了所有的非雷单位
        	int count = 0;// 计数器,记录共有多少个被选出的单位
        	for(int i=0;i<matrix;i++) {
        		for(int j=0;j<matrix;j++) {
        			if(buttons[i][j].getBackground() == clickedColor) {
        				count++;
        			}
        		}
        	}
        	if (count == matrix*matrix - mineNum) {
        		// 成功找出所有的非雷
        		tme.stop();
        		for(int i=0;i<matrix;i++) {
    	    		for(int j=0;j<matrix;j++) {
    	    			buttons[i][j].setEnabled(false);
    	    		}
    	    	}
        		String msg = "共用时" + String.valueOf(tmeCount) + "秒";
    			JOptionPane.showMessageDialog(jf, msg, "你赢了", JOptionPane.PLAIN_MESSAGE);
        	}
        }
    
    1. init() 游戏初始化方法,重置游戏就是调用此方法
    private void init() {
        	// 重绘窗体
        	jf.repaint();
        	// 绘制雷区
        	addButtons();
        	burieMine();
        	mineCount();
        	jf.setVisible(true); // 设置窗体可见,不写看不见
        	tmeCount = 0;
        	gameTime.setText("00");
        	tme.stop();
        }
    

    鼠标事件(左键,滚轮,右键)

    button.addMouseListener(new MouseListener() {
            			public void mouseReleased(MouseEvent e)
            			{
            				//System.out.println("mouseReleased---鼠标放开事件");
            			}
            			public void mousePressed(MouseEvent e)
            			{
            				System.out.println("w");
            				//System.out.println("mousePressed---鼠标按下事件");
            			} 
            			public void mouseExited(MouseEvent e)
            			{
            				//System.out.println("mouseExited---鼠标移出按钮区域");
            			}
            			public void mouseEntered(MouseEvent e)
            			{
            				//System.out.println("mouseEntered---鼠标移入按钮区域");
            			}
            			public void mouseClicked(MouseEvent e)
            			{
            				if(e.getButton()==MouseEvent.BUTTON1 && ((JButton)e.getSource()).isEnabled() == true && ((JButton)e.getSource()).getText() != "?")
            				{
            					//System.out.println("鼠标左点击事件");
            					// 游戏主体按钮的事件触发
        						tme.start(); // 计时开始
        						boolean flag = true; // 标记是否需要判断游戏成功
        						JButton button = (JButton)e.getSource();
        						for (int i=0;i<matrix;i++) {
        							for (int j=0;j<matrix;j++) {
        								if (buttons[i][j] == button) {
        									if (counts[i][j] == 99) {
        										// 踩雷了,游戏结束
        										gameOver();
        										flag = false;
        										break;
        									}
        									if (counts[i][j] == 0) {
        										// 是0,调用递归方法,寻找周围所有的0
        										isZero(i,j);
        										break;
        									}
        									// 显示具体的数字
        									buttons[i][j].setBackground(clickedColor);
        									buttons[i][j].setText(String.valueOf(counts[i][j]));
        								}
            						}
        						}
        						// 检查是否找出了所有的非雷区域
        						if (flag) {
        							isEnd();
        						}
            				}
            				if(e.getButton() == MouseEvent.BUTTON3)
            				{
            					//System.out.println("鼠标右点击事件");
            					if (((JButton)e.getSource()).getText() == "" && ((JButton)e.getSource()).getBackground() == mineColor) {
            						((JButton)e.getSource()).setText("?");
            					} else {
            						if (((JButton)e.getSource()).getText() == "?") {
                						((JButton)e.getSource()).setText("");
                					}
            					}
            				}
            				if(e.getButton()==MouseEvent.BUTTON2)
            				{
            					// 预加载周围八个的内容
            					JButton button = (JButton)e.getSource();
        						for (int i=0;i<matrix;i++) {
        							for (int j=0;j<matrix;j++) {
        								if (buttons[i][j] == button) {
        									// 找到当前被点击的按钮
        									if(buttons[i][j].getBackground() == clickedColor) {
        										// 只能是已经显示了的按钮
        										// 查看周围八个格子的内容,如果有“?”,就显示剩余格子的内容
        										int count = 0; // 周围“?”的数量,判断是否需要显示周围内容
        										if (i>0   && j>0 && 			buttons[i-1][j-1].getText() == "?") count++;
        						    			if (i>0   && 					buttons[i-1][j].getText() == "?" ) count++;
        						    			if (i>0   && j<matrix-1 && 		buttons[i-1][j+1].getText() == "?") count++;
        						    			if (j>0   && 					buttons[i][j-1].getText() == "?" ) count++;
        						    			if (j<matrix-1 && 				buttons[i][j+1].getText() == "?" ) count++;
        						    			if (i<matrix-1 && j>0 && 		buttons[i+1][j-1].getText() == "?" ) count++;
        						    			if (i<matrix-1 && 				buttons[i+1][j].getText() == "?" ) count++;
        						    			if (j<matrix-1 && i<matrix-1 &&	buttons[i+1][j+1].getText() == "?" ) count++;
        						    			//
        						    			// 当周围标记了雷的数量与当前按钮上的值一样,就展开周围内容
        						    			if(count == Integer.valueOf(buttons[i][j].getText())) {
        						    				// 显示周围八个内容,是雷就结束游戏,不是就展开
        						    				if (i>0 && j>0 && 				buttons[i-1][j-1].getBackground() == mineColor && buttons[i-1][j-1].getText() != "?") {if (counts[i-1][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i-1,j-1);}}
            						    			if (i>0 && 						buttons[i-1][j].getBackground() == mineColor && 	buttons[i-1][j].getText() != "?") 	{if (counts[i-1][j] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i-1,j);}}
            						    			if (i>0 && j<matrix-1 && 		buttons[i-1][j+1].getBackground() == mineColor && buttons[i-1][j+1].getText() != "?") {if (counts[i-1][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i-1,j+1);}}
            						    			if (j>0 && 						buttons[i][j-1].getBackground() == mineColor && 	buttons[i][j-1].getText() != "?") 	{if (counts[i][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i,j-1);}}
            						    			if (j<matrix-1 && 				buttons[i][j+1].getBackground() == mineColor && 	buttons[i][j+1].getText() != "?") 	{if (counts[i][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i,j+1);}}
            						    			if (i<matrix-1 && j>0 && 		buttons[i+1][j-1].getBackground() == mineColor && buttons[i+1][j-1].getText() != "?") {if (counts[i+1][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i+1,j-1);}}
            						    			if (i<matrix-1 && 				buttons[i+1][j].getBackground() == mineColor && 	buttons[i+1][j].getText() != "?") 	{if (counts[i+1][j] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i+1,j);}}
            						    			if (j<matrix-1 && i<matrix-1 &&	buttons[i+1][j+1].getBackground() == mineColor && buttons[i+1][j+1].getText() != "?") {if (counts[i+1][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i+1,j+1);}}
        						    			}
        									}
        								}
        							}
        						}
            				}
            			}
            		});
    

    程序源代码

    package demo;
    
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JButton;
    import javax.swing.JPanel;
    import javax.swing.JComboBox;
    import javax.swing.JOptionPane;
    import javax.swing.Timer;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.EventListener;
    import java.util.Random;
    	
    public class MineClearance {
    	// 使用到的变量
        int matrix = 9; // matrix*matrix 矩阵,规定了页面上的按钮数量
        int mineNum = 10; // 雷的数量
        int[][] counts = new int[matrix][matrix]; // 按钮下对应的雷数
        Color clickedColor = Color.LIGHT_GRAY; // 已经被点击的按钮的颜色
        Color bombColor = Color.yellow; // 雷爆炸的颜色
        Color mineColor = Color.white; // 布雷区默认的颜色
    	// 使用到的全局控件
    	private JFrame jf = new JFrame("扫雷小游戏");    //创建一个JFrame对象,存放整个窗体
    	private JPanel jp = new JPanel(); // 创建JPanel对象,中间容器,先存放其中,再存放到窗体中
    	private TestTimer testTimer =new TestTimer();
    	private Timer tme =new Timer(1000,testTimer);
    	private int tmeCount = 0;
    	private JLabel gameTime = new JLabel("00"); // 游戏时间
    	private JButton[][] buttons = new JButton[matrix][matrix]; // 页面上的按钮组(游戏主体)
        public MineClearance() {
        	// 页面布局
        	jf.setLayout(new BorderLayout()); //设置边框布局
        	jp.setLayout(new GridLayout(matrix,matrix,0,0)); // 采用网格布局
        	jf.setBounds(300, 100, 600, 650);    //设置窗口大小和位置
        	//----头部菜单-----
        	addTopMenu();
        	//----绘制雷区-----
        	init();
        }
        private void addTopMenu() {
            JLabel levelLabel = new JLabel("游戏等级"); // 游戏等级
        	gameTime.setBackground(Color.yellow); // 设置标签颜色
        	gameTime.setOpaque(true); // 是否不透明,不设没颜色。。。。
        	JButton resetButton = new JButton("新对局"); // 重置按钮
        	resetButton.addActionListener(new ResetGame());
        	String[] listData = new String[]{"9x9,10", "16x16,30", "30x30,99"};
        	JComboBox<String> gameLevel= new JComboBox<String>(listData);    //创建JComboBox
        	gameLevel.addItemListener(new ItemListener() {
        		 @Override
                 public void itemStateChanged(ItemEvent e) {
                     if (e.getStateChange() == ItemEvent.SELECTED) {
                         // 下拉框选项
                         if (e.getItem() == "9x9,10") {
                        	 matrix = 9;
                        	 mineNum = 10;
                         } else if (e.getItem() == "16x16,30") {
                        	 matrix = 16;
                        	 mineNum = 30;
                         } else if (e.getItem() == "30x30,99") {
                        	 matrix = 30;
                        	 mineNum = 99;
                         }
                     }
                 }
        	});
        	JPanel topMenu = new JPanel(); 
        	topMenu.add(levelLabel); 
        	topMenu.add(gameLevel); 
        	topMenu.add(gameTime); 
        	topMenu.add(resetButton); 
        	jf.add(topMenu, BorderLayout.NORTH);
        }
        private void addButtons() {
        	// 先清空雷区
        	jp.removeAll();
        	jp.setLayout(new GridLayout(matrix,matrix,0,0)); // 采用网格布局
        	buttons = new JButton[matrix][matrix];
        	// 添加按钮组
        	for(int i=0;i<matrix;i++) {
        		for(int j=0;j<matrix;j++) {
        			JButton button = new JButton();
            		button.setBackground(mineColor);
            		button.setOpaque(true); //设置颜色的必选项
            		button.setMargin(new Insets(0, 0, 0, 0)); //设置按钮边距
            		button.addMouseListener(new MouseListener() {
            			public void mouseReleased(MouseEvent e)
            			{
            				//System.out.println("mouseReleased---鼠标放开事件");
            			}
            			public void mousePressed(MouseEvent e)
            			{
            				//System.out.println("mousePressed---鼠标按下事件");
            			} 
            			public void mouseExited(MouseEvent e)
            			{
            				//System.out.println("mouseExited---鼠标移出按钮区域");
            			}
            			public void mouseEntered(MouseEvent e)
            			{
            				//System.out.println("mouseEntered---鼠标移入按钮区域");
            			}
            			public void mouseClicked(MouseEvent e)
            			{
            				if(e.getButton()==e.BUTTON1 && ((JButton)e.getSource()).isEnabled() == true && ((JButton)e.getSource()).getText() != "?")
            				{
            					//System.out.println("鼠标左点击事件");
            					// 游戏主体按钮的事件触发
        						tme.start(); // 计时开始
        						boolean flag = true; // 标记是否需要判断游戏成功
        						JButton button = (JButton)e.getSource();
        						for (int i=0;i<matrix;i++) {
        							for (int j=0;j<matrix;j++) {
        								if (buttons[i][j] == button) {
        									if (counts[i][j] == 99) {
        										// 踩雷了,游戏结束
        										gameOver();
        										flag = false;
        										break;
        									}
        									if (counts[i][j] == 0) {
        										// 是0,调用递归方法,寻找周围所有的0
        										isZero(i,j);
        										break;
        									}
        									// 显示具体的数字
        									buttons[i][j].setBackground(clickedColor);
        									buttons[i][j].setText(String.valueOf(counts[i][j]));
        								}
            						}
        						}
        						// 检查是否找出了所有的非雷区域
        						if (flag) {
        							isEnd();
        						}
            				}
            				if(e.getButton()==e.BUTTON3)
            				{
            					//System.out.println("鼠标右点击事件");
            					if (((JButton)e.getSource()).getText() == "" && ((JButton)e.getSource()).getBackground() == mineColor) {
            						((JButton)e.getSource()).setText("?");
            					} else {
            						if (((JButton)e.getSource()).getText() == "?") {
                						((JButton)e.getSource()).setText("");
                					}
            					}
            				}
            				if(e.getButton()==e.BUTTON2)
            				{
            					// 预加载周围八个的内容
            					JButton button = (JButton)e.getSource();
        						for (int i=0;i<matrix;i++) {
        							for (int j=0;j<matrix;j++) {
        								if (buttons[i][j] == button) {
        									// 找到当前被点击的按钮
        									if(buttons[i][j].getBackground() == clickedColor) {
        										// 只能是已经显示了的按钮
        										// 查看周围八个格子的内容,如果有“?”,就显示剩余格子的内容
        										int count = 0; // 周围“?”的数量,判断是否需要显示周围内容
        										if (i>0   && j>0 && 			buttons[i-1][j-1].getText() == "?") count++;
        						    			if (i>0   && 					buttons[i-1][j].getText() == "?" ) count++;
        						    			if (i>0   && j<matrix-1 && 		buttons[i-1][j+1].getText() == "?") count++;
        						    			if (j>0   && 					buttons[i][j-1].getText() == "?" ) count++;
        						    			if (j<matrix-1 && 				buttons[i][j+1].getText() == "?" ) count++;
        						    			if (i<matrix-1 && j>0 && 		buttons[i+1][j-1].getText() == "?" ) count++;
        						    			if (i<matrix-1 && 				buttons[i+1][j].getText() == "?" ) count++;
        						    			if (j<matrix-1 && i<matrix-1 &&	buttons[i+1][j+1].getText() == "?" ) count++;
        						    			//
        						    			// 当周围标记了雷的数量与当前按钮上的值一样,就展开周围内容
        						    			if(count == Integer.valueOf(buttons[i][j].getText())) {
        						    				// 显示周围八个内容,是雷就结束游戏,不是就展开
        						    				if (i>0 && j>0 && 				buttons[i-1][j-1].getBackground() == mineColor && buttons[i-1][j-1].getText() != "?") {if (counts[i-1][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i-1,j-1);}}
            						    			if (i>0 && 						buttons[i-1][j].getBackground() == mineColor && 	buttons[i-1][j].getText() != "?") 	{if (counts[i-1][j] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i-1,j);}}
            						    			if (i>0 && j<matrix-1 && 		buttons[i-1][j+1].getBackground() == mineColor && buttons[i-1][j+1].getText() != "?") {if (counts[i-1][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i-1,j+1);}}
            						    			if (j>0 && 						buttons[i][j-1].getBackground() == mineColor && 	buttons[i][j-1].getText() != "?") 	{if (counts[i][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i,j-1);}}
            						    			if (j<matrix-1 && 				buttons[i][j+1].getBackground() == mineColor && 	buttons[i][j+1].getText() != "?") 	{if (counts[i][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i,j+1);}}
            						    			if (i<matrix-1 && j>0 && 		buttons[i+1][j-1].getBackground() == mineColor && buttons[i+1][j-1].getText() != "?") {if (counts[i+1][j-1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i+1,j-1);}}
            						    			if (i<matrix-1 && 				buttons[i+1][j].getBackground() == mineColor && 	buttons[i+1][j].getText() != "?") 	{if (counts[i+1][j] == 99) {/*如果是雷,游戏结束*/gameOver();} 		else {/*递归展开内容*/isZero(i+1,j);}}
            						    			if (j<matrix-1 && i<matrix-1 &&	buttons[i+1][j+1].getBackground() == mineColor && buttons[i+1][j+1].getText() != "?") {if (counts[i+1][j+1] == 99) {/*如果是雷,游戏结束*/gameOver();} 	else {/*递归展开内容*/isZero(i+1,j+1);}}
        						    			}
        									}
        								}
        							}
        						}
            				}
            			}
            		});
            		buttons[i][j] = button;
            		jp.add(button);
        		}
        	}
        	jf.add(jp, BorderLayout.CENTER); // 将JPanel中间容器添加到JFrame窗体中
        }
        private void burieMine () {
        	// 先清空所有的雷
        	counts = new int[matrix][matrix];
        	// 埋雷
        	for(int i=0;i<mineNum;i++) {
        		Random r = new Random(); // 随机获取一个位置
        		int x = r.nextInt(matrix);
        		int y = r.nextInt(matrix);
        		if (counts[x][y] == 99) {
        			// 如果已经设置为雷,就跳过
        			i--;
        			continue;
        		}
        		counts[x][y] = 99; // 99表示是雷
        	}
        }
        private void mineCount () {
        	// 统计雷的数量
        	// 判断方法:寻找九宫格中目标周围8个的内容
        	int num; // 用来统计目标周围雷的数量
        	for(int i=0;i<matrix;i++) {
        		for(int j=0;j<matrix;j++) {
        			if (counts[i][j] == 99) continue; // 如果是雷就跳过
        			num = 0;		
    //    			(i-1,j-1)  (i-1,j)  (i-1,j+1)
    //    			(i,j-1)    (i,j)    (i, j+1)
    //    			(i+1,j-1)  (i+1,j)	(i+1,j+1)
        			// 防止数组下标越界
        			if (i>0   && j>0 && 			counts[i-1][j-1] == 99) num++;
        			if (i>0   && 					counts[i-1][j] == 99 ) num++;
        			if (i>0   && j<matrix-1 && 			counts[i-1][j+1] == 99) num++;
        			if (j>0   && 					counts[i][j-1] == 99) num++;
        			if (j<matrix-1 && 				counts[i][j+1] == 99) num++;
        			if (i<matrix-1 && j>0 && 		counts[i+1][j-1] == 99) num++;
        			if (i<matrix-1 && 				counts[i+1][j] == 99) num++;
        			if (j<matrix-1 && i<matrix-1 &&	counts[i+1][j+1] == 99) num++;
        			counts[i][j] = num; // 赋值到目标位置			
        		}
        	}
        }
    	private void gameOver() {
    		tme.stop();
    		// 游戏结束,显示所有内容
    		for (int i=0;i<matrix;i++) {
    			for (int j=0;j<matrix;j++) {
    				if (counts[i][j] == 99) { // 如果是雷就显示雷
    					buttons[i][j].setText("雷");
    					buttons[i][j].setBackground(bombColor);
    				} else {
    					if (counts[i][j] == 0) { // 如果是0就显示为空
    						buttons[i][j].setText("");
    					} else {
    						buttons[i][j].setText(String.valueOf(counts[i][j]));
    					}
    					buttons[i][j].setBackground(clickedColor);
    				}
    				buttons[i][j].setEnabled(false); // 设置按钮不可用
    			}
    		}
    		String msg = "坚持了" + String.valueOf(tmeCount) + "秒";
    		JOptionPane.showMessageDialog(jf, msg, "游戏结束", JOptionPane.ERROR_MESSAGE);
    	}
        private void init() {
        	// 重绘窗体
        	jf.repaint();
        	// 绘制雷区
        	addButtons();
        	burieMine();
        	mineCount();
        	jf.setVisible(true); // 设置窗体可见,不写看不见
        	tmeCount = 0;
        	gameTime.setText("00");
        	tme.stop();
        }
        private void isZero(int i, int j) {
        	// 递归实现寻找周围的0,
        	// 结束条件:1.已经被点击(或显示)的按钮(按钮颜色改变为了橙色了的按钮)
        	//			2.遇到了雷
        	//			3.遇到了数字
        	if (buttons[i][j].getBackground() == clickedColor) return;
        	if (counts[i][j] == 0) {
        		buttons[i][j].setText("");
        		buttons[i][j].setBackground(clickedColor);
        		isEnd();
        	} else {
        		if (counts[i][j] == 99) {
        			return;
        		} else {
        			buttons[i][j].setText(String.valueOf(counts[i][j]));
            		buttons[i][j].setBackground(clickedColor);
            		isEnd();
            		return;
        		}	
        	}
        	// 查看目标周围八格
        	if (i>0   && j>0 ) isZero(i-1,j-1);
    		if (i>0) isZero(i-1,j);
    		if (i>0   && j<matrix-1 ) isZero(i-1,j+1);
    		if (j>0) isZero(i,j-1);
    		if (j<matrix-1) isZero(i,j+1);
    		if (i<matrix-1 && j>0) isZero(i+1,j-1);
    		if (i<matrix-1)  isZero(i+1,j);
    		if (j<matrix-1 && i<matrix-1) isZero(i+1,j+1);
        }
        private void isEnd() {
        	// 游戏完成,找出了所有的非雷单位
        	int count = 0;// 计数器,记录共有多少个被选出的单位
        	for(int i=0;i<matrix;i++) {
        		for(int j=0;j<matrix;j++) {
        			if(buttons[i][j].getBackground() == clickedColor) {
        				count++;
        			}
        		}
        	}
        	if (count == matrix*matrix - mineNum) {
        		// 成功找出所有的非雷
        		tme.stop();
        		for(int i=0;i<matrix;i++) {
    	    		for(int j=0;j<matrix;j++) {
    	    			buttons[i][j].setEnabled(false);
    	    		}
    	    	}
        		String msg = "共用时" + String.valueOf(tmeCount) + "秒";
    			JOptionPane.showMessageDialog(jf, msg, "你赢了", JOptionPane.PLAIN_MESSAGE);
        	}
        }
        public static void main(String[] args) {
    		new MineClearance();
    	}
        class ResetGame implements ActionListener{
        	// 重置游戏
        	public void actionPerformed(ActionEvent event){
        		init();
        	}
        }
        class TestTimer implements ActionListener{
        	public void actionPerformed(ActionEvent e){
        		tmeCount++;
        		String s;
        		if (tmeCount < 10) {
        			s =  "0" + String.valueOf(tmeCount);
        		}
        		else {
        			s =  String.valueOf(tmeCount);
        		}
        		gameTime.setText(s);
        	}
        } 
    }
    
    
    展开全文
  • 扫雷小游戏 完整源码

    2020-07-29 14:20:27
    模仿Windows自带的扫雷游戏,界面和功能基本一致,c/c++开发,在MFC下实现。附件包含可执行文件和完整源码。
  • 扫雷小游戏-改进

    千次阅读 2012-09-19 14:13:32
    改进了点功能,能够显示周围雷的个数。直接看代码: # -*- coding: utf-8 -*- ... @note: 实现扫雷游戏(2012-9-18) 测试环境:python3.2.2 ''' import sys import random import string class Mine

    改进了点功能,能够显示周围雷的个数。直接看代码:

    # -*- coding: utf-8 -*-
    '''@author: YeahMan_Nic
       @version: 2.0
       @note: 实现扫雷游戏(2012-9-18)
              测试环境:python3.2.2
    '''
    import sys
    import random
    import string
    
    class MineSweeping():
        '''扫雷主程序
        '''
        def __init__(self):
            '''初始化函式
            ''' 
            self.ROW = 8
            self.LINE = 8
            self.SCORE = 0 #扫雷得分 
            self.MineNum = 15 #地雷总数
            self.xy_list=   [[0,0,0,0,0,0,0,0],
                             [0,0,0,0,0,0,0,0],
                             [0,0,0,0,0,0,0,0],
                             [0,0,0,0,0,0,0,0],
                             [0,0,0,0,0,0,0,0],
                             [0,0,0,0,0,0,0,0],
                             [0,0,0,0,0,0,0,0],
                             [0,0,0,0,0,0,0,0]]
            
                       
        def searchRound(self, x, y):
            count = 0
            if x - 1 >= 0 and y - 1 >= 0 and self.xy_list[x - 1][y - 1] == 1:
                count = count + 1
            if x - 1 >= 0 and self.xy_list[x - 1][y] == 1:
                count = count + 1
            if x - 1 >= 0 and y + 1 < 8 and self.xy_list[x - 1][y + 1] == 1:
                count = count + 1
            if y - 1 >= 0 and self.xy_list[x][y - 1] == 1:
                count = count + 1
            if y + 1 < 8 and self.xy_list[x][y + 1] == 1:
                count = count + 1
            if x + 1 < 8 and y - 1 >= 0 and self.xy_list[x + 1][y - 1] == 1:
                count = count + 1
            if x + 1 < 8 and self.xy_list[x + 1][y] == 1:
                count = count + 1
            if x + 1 < 8 and y + 1 < 8 and self.xy_list[x + 1][y + 1] == 1:
                count = count + 1
            return count      
    
        def iniData(self):
            '''x,y坐标初始状态值函数
               0-没有地雷;1-有地雷
            '''
    
             #游戏开始前所有数值归零
            for l in range(self.LINE):
                for r in range(self.ROW):
                    self.xy_list[l][r]= 0
            
            Max = self.MineNum
            for x in range(self.LINE):
                for y in range(self.ROW):
                    if 0 > Max:
                        self.xy_list[x][y]= 0
                    else:
                        #为了增加地雷分布范围,选择0到4随机数
                        if 1 == random.randint(0,4): 
                            self.xy_list[x][y]= 1
                            Max = Max - 1
                            
        
        def getX(self):
            '''获得x坐标值
               @return : 返回x坐标值
               @type : int
            '''
            sys.stdout.write('X=')
            xRet = input()
            while xRet=='' or (False == self.isNumber(xRet))\
                 or 0 > int(xRet) or int(xRet)>self.ROW:
                print('Wrong number!(please input 0-7)')
                sys.stdout.write('X=')
                xRet = input()
            return int(xRet)
            
            
        def getY(self):
            '''获得y坐标值
               @return : 返回y坐标值
               @type : int
            '''
            sys.stdout.write('Y=')
            yRet = input()
            while yRet=='' or (False == self.isNumber(yRet))\
                 or 0>int(yRet) or int(yRet)>self.LINE:
                print('Wrong number!(please input 0-7)') 
                sys.stdout.write('Y=')
                yRet = input()
            return int(yRet)
        
        
        def isNumber(self,strVal):
            '''检查是否数值
                当然,也可以利用正则表达式
               @param : 需检查的字符串 
               @type : str
            ''' 
            
            nums = string.digits
            for i in strVal:
                if i not in nums:
                    return False
            return True
        
    
        def checkMine(self,xPos,yPos):
            '''检查输入坐标是否有雷
               0-没有地雷;1-有地雷;2-已经清扫
               @param 1: x坐标
               @type : int
               @param 2: y坐标
               @type : int
               @return : 0-没有地雷;1-有地雷;2-已经清扫
               @rtype : int
            ''' 
    
            if 0 == self.xy_list[xPos][yPos]:
                self.xy_list[xPos][yPos] = 2
                return 0
            elif 2 == self.xy_list[xPos][yPos]:
                return 2
            else:
                return 1
            
                    
        def play(self):
            '''游戏运行函数
            '''
    
            self.display(1)
            self.SCORE = 0
            self.iniData()
            #print self.xy_list
            
            while(1):
                x = self.getX() 
                y = self.getY()
                while(2 == self.checkMine(x,y)):
                    print('values of x,y had inputed,please input new values!')
                    x = self.getX()
                    y = self.getY()
                if 1 == self.checkMine(x,y):
                    self.end()
                    break
                else:
                    self.display(2)
                   #self.SCORE = self.SCORE + 1
                    
                
        def end(self):
            '''游戏结束函数
            '''
            
            self.display(3)
            print ('+======================+')
            print ('+      Game Over       +')
            print ('+======================+')
            print ('   Your score is: %d    '%self.SCORE)
            
    
      
        
        def display(self,kind):
            '''图形输出函数
               @param:1-初始;2-运行;3-结束
               @type:int
            '''
            
            if kind==1:
                print ('+======================+')
                print ('+      Game Start      +')
                print ('+======================+')
                print ('*-----------------*')
                for i in range(self.LINE):
                    print ('| 1 1 1 1 1 1 1 1 |')
                print ('*-----------------*')
                print ('Please input values of x,y(0-7):')
            elif kind==2:
    
                self.SCORE = self.SCORE + 1
                print ('*-----------------*')
                for i in range(self.LINE):
                    sys.stdout.write('| ')
                    for k in range(self.ROW):
                        if 2 == self.xy_list[i][k]:
                            count = self.searchRound(i, k)
                            strCount = '%d' %count
                            sys.stdout.write(strCount + ' ')
                        else:
                            sys.stdout.write('? ')
                    print('|')
                print('*-----------------*')
                print('Please input values of x,y(0-7):')           
            else:
                #输出所有的地雷与已经清扫位置
                print('*-----------------*')
                for i in range(self.LINE):
                    sys.stdout.write('| ')
                    for k in range(self.ROW):
                        if 2 == self.xy_list[i][k]:
                            count = self.searchRound(i, k)
                            strCount = '%d' %count
                            sys.stdout.write(strCount + ' ')
                        elif 1== self.xy_list[i][k]:
                            sys.stdout.write('X ')
                        else:
                            count = self.searchRound(i, k)
                            strCount = '%d' %count
                            sys.stdout.write(strCount + ' ')
                    print('|')
                print('*-----------------*')
    
    
    if __name__ == '__main__':
        '''自测试
        '''
    
        ms = MineSweeping()
        while(1):
            ms.play()
            print('\n----------------------------------------------')
            print('Quit game press \'q\',otherwise press other key!')
            print('----------------------------------------------')
            inputVal = input()
            if 'q' == inputVal:
                break
    


    展开全文
  • JVAV图形界面实现的扫雷小游戏,界面和功能仿照windows自带的小游戏
  • 在练习了几十个小短句,和其他小项目之后,我开始了第一个比较大的,也比较经典的小游戏——扫雷 首先需要分析,制作这个小项目所需要的大致流程 开始游戏, ...

    在练习了几十个小短句,和其他小项目之后,我开始了第一个比较大的,也比较经典的小游戏——扫雷

    首先需要分析,制作这个小项目所需要的大致流程

    1. 开始游戏
    2. 初始化棋盘
    3. 给地图中增加雷
    4. 用户交互,输入坐标,判断坐标是否有雷
    5. 胜利/失败

    一,开始游戏

    我们可以通过switch选择语句来让玩家开始游戏,并通过printf函数来让可视化界面尽量美观

    int n;
    	printf("如果你要开始游戏,请输入1\n");
    	scanf("%d", &n);
    	
    	switch (n)
    	{
    	case 1:game(); break;
    	default:printf("Thanks your play");
    		break;
    	}

    二,初始化棋盘

    我们准备写一个可改变棋盘大小的游戏,因此我们可以将数组的变量在头文件中定义,长和宽都定义为9,但这个时候就有问题了,我们很难确定边界的坐标周围有多少个‘雷’,因此我们实际的棋盘大小要更大一些,但呈现在玩家面前的只有中间那一块的棋盘。

    #define len 9
    #define tall 9
    #define lens len+2
    #define talls tall+2

    首先,我们需要两个数组分别作为玩家可视化的界面和棋盘资料,并将一个全部置0,另一个则全部置*作为用户可视化的界面,并将其打印出来

    char game1[lens][talls];
    char game2[lens][lens];
    void Init_news(char a[lens][talls],char n)//初始化全场为一个数符
    {
    	for (int i = 0; i < lens; i++)
    	{
    		for (int j = 0; j < talls; j++)
    		{
    			a[i][j] = n;
    			//printf("%d", a[i][j]);
    		}
    		//printf("\n");
    	}
    }
    void Print_Init(char a[lens][talls])//打印棋盘
    {
    	for (int i = 0; i < 10;i++)
    	{
    		printf("%d ", i);
    	}
    	printf("\n");
    	for (int i = 1; i <= len; i++)
    	{
    		printf("%d ", i);
    		for (int j = 1; j <= tall; j++)
    		{
    			printf("%c ", a[i][j]);
    		}
    		printf("\n");
    	}
    }

    三,给地图中增加地雷

    我们需要随机给地图中增加地雷数量,可以将地雷数量设置为n,n可以改变

    
    void Product_Mine(char a[lens][talls],int Num)//为地图里初始化地雷
    {
    	int m =0, n =0;
    	while (Num--) 
    	{	
    		n = rand() % len + 1;
    		m = rand() % tall + 1;
    		a[n][m] = '1';//1的意思为有雷	
    	}
    
    }

    四,用户交互,输入坐标

    由于我们已经将棋盘全部置0,地雷置1,因此只需要将其周围的1加起来,数字大小即为周围地雷数量

    int Sum_Mine(char a[lens][talls], int n, int m)
    {
    	if (a[n][m] == '1')
    	{
    		printf("GAME OVER!即将为您开始下一局游戏\n");
    		main();
    	}
    	int sum = 0;
    	for (int i = -1; i < 2; i++)
    	{
    		for (int j = -1; j < 2; j++)
    		{
    			sum = sum + a[n + i][m + j] - '0';
    
    		}
    	}
    	return sum;
    }

    五,胜利/失败

    怎么确定胜利或者失败呢?当棋盘总格子-地雷数量=排雷次数。此时地图上全都是地雷,此时胜利。

    如果输入的坐标和地雷坐标一致时,此时失败。

    当然,如果一次猜完之后,接下来又要猜的话需要循环,则应该将本函数置于死循环之中。

    void Guess_Number(char a[lens][talls], char b[lens][talls],int t)
    {
    	int n,m,i;
    	printf("请输入你所要排查的坐标:");
    	scanf("%d %d", &n, &m);
    	printf("\n");
    	i = Sum_Mine(a, n, m);
    	Change_Map(b, i,n,m);
    	t++;
    	Print_Init(b);
    	if (t == 71)
    	{
    		printf("You win!!\n 即将为您开始下一局游戏\n");
    		main();
    	}
    }

    以上就是我这次小小的实践的收获和结果

    ps题外话,后续优化的一些思路

    当我这个程序运行时,一次只会判断一个坐标,设想一下,如果点一个坐标,便能让他周围的空格子都呈现出来其数字,玩起来应该会更轻松一点吧

    展开全文
  • 扫雷小游戏

    千次阅读 2018-10-21 21:12:53
     用C语言实现扫雷小游戏。 要求  1、第一步不能被炸死。  2、输入一个坐标,可以展开一片。 思路  先给出一个头文件game.c,是我们自定义的一个头文件,里面有我们在写扫雷程序里面所需要的所有头文件、...

    描述

        用C语言实现扫雷小游戏。

    要求

        1、第一步不能被炸死。

        2、输入一个坐标,可以展开一片。

    思路

        先给出一个头文件game.c,是我们自定义的一个头文件,里面有我们在写扫雷程序里面所需要的所有头文件、常量还有所有函数的声明。

    game.h

    #define _CRT_SECURE_NO_WARNINGS 1
    
    #ifndef __GAME_H__
    #define __GAME_H__
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    #define ROW 9
    #define COL 9
    #define ROWS (ROW+2)
    #define COLS (COL+2)
    #define EASY_MODE 10
    
    
    int book[ROWS][COLS];
    
    void DisplayBoard(char board[ROWS][COLS], int row, int col);
    void Init(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
    void setMine(char mine[ROWS][COLS], int row, int col);
    int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
    int GetCount(char mine[ROWS][COLS], int x, int y);
    void SafeMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
    void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
    int CountShow(char show[ROWS][COLS], int row, int col);
    
    #endif //__GAME_H__

    接下来就是我整个程序的设计思路!!!!

        1、首先最重要的是先写主函数(main()),然后根据主函数的需要来设计自定义函数。

    int main(void)
    {
    	int i = 0;
    	int j = 0;
    	int input = 0;
    
    	srand((unsigned int)time(NULL));
    
    	//调用菜单函数,打印游戏菜单
    	menu();
    
    	do
    	{
    		printf("请输入您要选的选项:");
    		scanf("%d", &input);
    		switch (input)
    		{
    			case 1:
    				game();
    				break;
    			case 0:
    				printf("退出游戏!\n");
    				break;
    			default:
    				printf("输入错误!请重新输入!\n");
    				break;
    		}
    
    	} while (input);
    
    	system("pause");
    	return 0;
    }

        因为这个游戏不能只玩一次就退出了,选择权在玩家手里,所以我们需要一个循环来判断玩家还想不想玩。

        2、然后根据主函数的需要,我们先写一个菜单函数,这个函数很简单,只需要输出就好,菜单的样子也是根据你的喜好来设计。

    void menu()
    {
    	printf("***********************************\n");
    	printf("*******        1. play      *******\n");
    	printf("*******        0. exit      *******\n");
    	printf("***********************************\n");
    }

        3、接下来我们需要game()函数啦,在这个函数里我们将要实现扫雷游戏的全部内容,也是一样,我们在这个函数里先写一个大的框架,需要什么函数我们先写下名字,然后再根据我们的需要去在game.c里设计所有我们需要的自定义函数。首先需要两个数组,分别为mine[][] 和 show[][] 用来记录扫雷盘,mine数组用来存哪里是地雷,哪里不是地雷。show数组用来给玩家显示玩游戏的过程。

        扫雷的面板是9X9,但是我们要给数组11X11,因为在算某个坐标的周围有多少个地雷的时候我们需要扫描他周围8个格子,目前我的水平,还做不到让它根据实际情况去扫描,所以我给二维数组多定义一圈,让它们初始化跟内圈一样为‘0’,这样扫描的时候就不算那些格子了。所以,我们需要初始化函数,还有打印的函数,不打印怎么玩!!!!!

        其次,我们要一个函数来随机摆放地雷的位置,那么就有了setMine函数。这里说一下,因为随机所以需要rand()库函数,但是调用rand之前,要在main里面写一句

    	srand((unsigned int)time(NULL));

        要不然rand的随机值每次开始都一样。

        因为第一步不能炸死,我们就需要设计SaveMove函数,第一步走完,要判断一下玩家赢了没有,说不定就一个地雷呢!随便走一步,多数情况就赢了!所以需要一个CountShow函数来算现在show数组里还有多少个‘*’,如果‘*’跟地雷的数目一样,那么玩家就赢了呀!

        如果第一步没有赢,那就往下走,因为往往需要多次才能赢,我们就设计一个循环实现,先来个死循环while(1),赢了或者输了跳出去就行了嘛!

        再来一个FindMine函数,来判断玩家踩到地雷了没有,踩到了就返回1,没踩到就返回0 。

        如果 没踩到就继续判断一个赢了没有呀!

        那么如果没有赢也没有输,那就再打印一遍show 数组,让玩家继续玩下去,当然是修改后的show数组!

    void game()
    {
    	int is = 0;
    
    	//mine 数组存储雷的位置 0 为空,1 为雷
    	char mine[ROWS][COLS] = { 0 };
    	//show 数组存储游戏盘,并且在每次点击后显示周围雷的个数
    	char show[ROWS][COLS] = { 0 };
    	
    	//初始化mine 数组所有元素为'0',show 数组所有元素为'*'
    	Init(mine, show, ROWS, COLS);
    	
    	//设置地雷
    	setMine(mine, ROWS, COLS);
    
    	//打印mine 数组
    	DisplayBoard(mine, ROWS, COLS);
    
    	printf("\n");
    	printf("-------------------------\n");
    	printf("\n");
    
    	//打印游戏面板
    	DisplayBoard(show, ROWS, COLS);
    	//第一步不被炸死
    	SafeMove(mine, show, ROWS, COLS);
    
    	//如果面板上剩下的'*' 与地雷的总数相同时,玩家赢
    	if (CountShow(show, ROWS, COLS) == EASY_MODE)
    	{
    		printf("-------------------------\n");
    		DisplayBoard(mine, ROWS, COLS);
    		printf("恭喜你!你赢了!\n");
    		return;
    	}
    	
    	/*DisplayBoard(mine, ROWS, COLS);
    	printf("\n");
    	printf("-------------------------\n");
    	printf("\n");*/
    	DisplayBoard(show, ROWS, COLS);
    	
    
    	while (1)
    	{
    		//判断玩家选择的坐标是不是地雷,若是则返回1,若不是则展开附近地雷信息
    		is = FindMine(mine, show, ROWS, COLS);
    		//如果面板上剩下的'*' 与地雷的总数相同时,玩家赢
    		if (CountShow(show, ROWS, COLS) == EASY_MODE)
    		{
    			printf("-------------------------\n");
    			DisplayBoard(mine, ROWS, COLS);
    			printf("恭喜你!你赢了!\n");
    			break;
    		}
    		
    		if (is == 1)
    		{
    			printf("BOOM!!!!!!!!!!\n");
    			printf("很遗憾,你被炸死了!\n");
    			DisplayBoard(mine, ROWS, COLS);
    			break;
    		}
    
    	/*	DisplayBoard(mine, ROWS, COLS);
    		printf("\n");
    		printf("-------------------------\n");
    		printf("\n");*/
    		DisplayBoard(show, ROWS, COLS);
    
    	}
    }

        在注释掉的显示mine数组的部分,是调试的时候我们需要知道地雷在哪里,我们才能实现我们想要的结果,当然,如果你聪明绝顶,那就当我刚才放了个屁。

        4、接下来我们要开始写game()函数里面所需要的函数了,就像刚才所说的,最基本的就是初始化和打印函数了,这个没有什么难的,不过初始化函数里用到了memset()库函数,这个函数参数依次是,(需要修改的内存起始地址, 需要修改为的字符 , 字符的个数是多少)

    void Init(char board[ROWS][COLS],   int row, int col, char ch)
    {
    	memset(&board[0][0], ch, row*col*sizeof(board[0][0]));
    }
    
    void DisplayBoard(char board[ROWS][COLS], int row, int col)
    {
    	int i = 0;
    	int j = 0;
    
    	//打印横坐标
    	printf("0 ");
    	for (i = 1; i < row - 1; i++)
    	{
    		printf("%d ", i);
    	}
    	printf("\n");
    
    	for (i = 1; i < row - 1; i++)
    	{
    		printf("%d ", i);
    		
    		for (j = 1; j < col - 1; j++)
    		{
    			printf("%c ", board[i][j]);
    		}
    		printf("\n");
    		
    	}
    }

        5、下来就是设置地雷的函数。需要注意的点已经在第3点里面提到了!

    void setMine(char mine[ROWS][COLS], int row, int col)
    {
    	int x = 0;
    	int y = 0;
    	int count = EASY_MODE;
    
    
    	while (count)
    	{
    		//我们需要9个数字,如果%10产生的是0~8, 9个数字
    		//但是我们需要1~9,所以先%9产生8个数字,再加1就好
    		x = rand() % 9 + 1;
    		y = rand() % 9 + 1;
    		if (mine[x][y] == '0')
    		{
    			mine[x][y] = '1';
    			count--;
    		}
    	}
    }

        6、下来就是第一步不能被炸死这个函数SaveMove。

     

    void SafeMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    {
    	int x = 0;
    	int y = 0;
    	int flag = 1;
    	int count = 0;
    	char ch = 0;
    
    	while (1)
    	{
    		printf("请输入您要选择的坐标:");
    		scanf("%d%d", &x, &y);
    
    		if (x < 1 && x > COL && y < 1 && y > ROW)
    		{
    			printf("您输入的坐标超过当前地图,请重新输入!\n");
    			continue;
    		}
    
    		if (mine[x][y] == '1')
    		{
    			//如果玩家输入的坐标是1,则强行把这个坐标改为0
    			mine[x][y] = '0';
    			char ch = GetCount(mine, x, y);
    			show[x][y] = ch + '0';
    			book[x][y] = 1;
    			open(mine, show, x, y);
    			//将一个地雷改为了空地,则需要再随机填一个雷
    			while (flag)
    			{
    				x = rand() % 9 + 1;
    				y = rand() % 9 + 1;
    				if (mine[x][y] == '0')
    				{
    					mine[x][y] = '1';
    					flag--;
    					break;
    				}
    			}break;
    		}
    		else if (mine[x][y] == '0')
    		{
    			char ch = GetCount(mine, x, y);
    			show[x][y] = ch + '0';
    			book[x][y] = 1;
    			open(mine, show, x, y);
    			break;
    		}
    
    	}
    
    }

    7、第一步走完,需要判断一下玩家赢了没有,说不定就是那么腻害!怎么判断赢了没有呀!往前翻!!!不认真看!

        所以需要一个CountShow函数来算现在show数组里还有多少个‘*’,如果‘*’跟地雷的数目一样,那么玩家就赢了呀!

    int CountShow(char show[ROWS][COLS], int row, int col)//判断剩余未知区域的个数,个数为雷数时玩家赢
    {
    	int count = 0;
    	int i = 0;
    	int j = 0;
    	for (i = 1; i < row - 1; i++)
    	{
    		for (j = 1; j < col - 1; j++)
    		{
    			if (show[i][j] == '*')
    			{
    				count++;
    			}
    		}
    
    	}
    	return count;
    }

    8、第一步走完了,那么就要走下一步了,我们就有了FindMine函数,用来判断玩家走的是不是地雷所在的位置。

    //踩到雷返回1,没有踩到雷返回0
    int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    {
    	int x = 0;
    	int y = 0;
    	int count = 0;
    
    	
    	printf("请输入您选择的坐标:");
    	scanf("%d%d", &x, &y);
    
    	if (x < 1 && x > COL && y < 1 && y > ROW)
    	{
    		printf("您输入的坐标超过当前地图,请重新输入!\n");
    			
    	}
    	else
    	{
    		if (mine[x][y] == '0')
    		{
    			char ch = GetCount(mine, x, y);
    			show[x][y] = ch + '0';
    			book[x][y] = 1;
    			open(mine, show, x, y);
    			if (CountShow(show, row, col) == EASY_MODE)
    			{
    				return 0;
    			}
    		}
    		else if (mine[x][y] == '1')
    		{
    			return 1;
    		}
    
    	}
    	return 0;
    }

        9、接下来,最重要的一步!!!!!!!!

        如果我们选择一个坐标,那个坐标不是地雷,我们就要像别人家的扫雷一样,去展开一片没有雷的区域。那么这个区域什么时候是个头呢,那就是要被提示附近有地雷的数字包围起来!

        这个函数用到了深度优先算法,里面有递归所以要好好看。

        注意:next数组用来存放一组上下左右移动的方向。

                   tx和ty用来存放下一步的坐标

        而且这个函数里用到了算周围有几个地雷的函数,GetCount函数一并附在下面!

    //用深度优先搜索来对面板展开
    void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
    {
    	
    	int tx = 0;
    	int ty = 0;
    	int k = 0;
    	//定义next数组,用来对四个方向进行搜索
    	int next[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
    
    	//在展开的时候如果GetCount函数返回的不是0,则给show数组赋返回的值
    	if (GetCount(mine, x, y) != 0)
    	{
    		show[x][y] = GetCount(mine, x, y) + '0';
    	}
    	//如果是0,给show数组那个位置赋空格
    	else if (GetCount(mine, x, y) == 0)
    	{
    		show[x][y] = ' ';
    	}
    	
    	for (k = 0; k <= 3; k++)
    	{
    		tx = x + next[k][0];
    		ty = y + next[k][1];
    
    		if (tx < 1 || tx > ROW || ty < 1 || ty > COL)
    		{
    			continue;
    		}
    		if (mine[tx][ty] == '0' && book[tx][ty] == 0 && GetCount(mine, tx, ty) < 1)
    		{
    			
    			book[tx][ty] = 1;
    			open(mine, show, tx, ty);
    		
    		}
    		//这一步很关键,是展开时遇到数字停下来的一步
    		if (mine[tx][ty] == '0' && book[tx][ty] == 0 && GetCount(mine, tx, ty) > 0)
    		{
    			show[tx][ty] = GetCount(mine, tx, ty) + '0';
    			continue;
    		}
    		
    	}
    	return;
    }
    
    //统计面板上剩下的'*'
    int CountShow(char show[ROWS][COLS], int row, int col)//判断剩余未知区域的个数,个数为雷数时玩家赢
    {
    	int count = 0;
    	int i = 0;
    	int j = 0;
    	for (i = 1; i < row - 1; i++)
    	{
    		for (j = 1; j < col - 1; j++)
    		{
    			if (show[i][j] == '*')
    			{
    				count++;
    			}
    		}
    
    	}
    	return count;
    }
    int GetCount(char mine[ROWS][COLS], int x, int y)
    {
    	int count = 0;
    	//分别对(x,y)坐标周围8个格子进行判断,如果是雷则count + 1
    	//最后返回count就是(x,y)周围的地雷个数
    	if (mine[x - 1][y] == '1')
    		count++;
    	if (mine[x - 1][y - 1] == '1')
    		count++;
    	if (mine[x][y - 1] == '1')
    		count++;
    	if (mine[x + 1][y - 1] == '1')
    		count++;
    	if (mine[x + 1][y] == '1')
    		count++;
    	if (mine[x + 1][y + 1] == '1')
    		count++;
    	if (mine[x][y + 1] == '1')
    		count++;
    	if (mine[x - 1][y + 1] == '1')
    		count++;
    
    	return count;
    }

    源代码

    game.h

    #define _CRT_SECURE_NO_WARNINGS 1
    
    #ifndef __GAME_H__
    #define __GAME_H__
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    
    #define ROW 9
    #define COL 9
    #define ROWS (ROW+2)
    #define COLS (COL+2)
    #define EASY_MODE 10
    
    
    int book[ROWS][COLS];
    
    void DisplayBoard(char board[ROWS][COLS], int row, int col);
    void Init(char board[ROWS][COLS],  int row, int col, char ch);
    void setMine(char mine[ROWS][COLS], int row, int col);
    int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
    int GetCount(char mine[ROWS][COLS], int x, int y);
    void SafeMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
    void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
    int CountShow(char show[ROWS][COLS], int row, int col);
    
    #endif //__GAME_H_

    test.c

    #define _CRT_SECURE_NO_WARNINGS 1
    
    #include "game.h"
    
    /*
    * 实现扫雷游戏的测试
    * 要求:
    * 1、第一步不能炸死
    * 2、点开一个若不是雷,则可以展开一片
    * 郭文峰
    * 2018/10/19
    */
    
    void menu()
    {
    	printf("***********************************\n");
    	printf("*******        1. play      *******\n");
    	printf("*******        0. exit      *******\n");
    	printf("***********************************\n");
    }
    
    void game()
    {
    	int is = 0;
    
    	//mine 数组存储雷的位置 0 为空,1 为雷
    	char mine[ROWS][COLS] = { 0 };
    	//show 数组存储游戏盘,并且在每次点击后显示周围雷的个数
    	char show[ROWS][COLS] = { 0 };
    	
    	//初始化mine 数组所有元素为'0',show 数组所有元素为'*'
    	//Init(mine, show, ROWS, COLS);
    	Init(mine, ROWS, COLS, '0');
    	Init(show, ROWS, COLS, '*');
    
    	//设置地雷
    	setMine(mine, ROWS, COLS);
    
    	//打印mine 数组
    	DisplayBoard(mine, ROWS, COLS);
    
    	printf("\n");
    	printf("-------------------------\n");
    	printf("\n");
    
    	//打印游戏面板
    	DisplayBoard(show, ROWS, COLS);
    	//第一步不被炸死
    	SafeMove(mine, show, ROWS, COLS);
    
    	//如果面板上剩下的'*' 与地雷的总数相同时,玩家赢
    	if (CountShow(show, ROWS, COLS) == EASY_MODE)
    	{
    		printf("-------------------------\n");
    		DisplayBoard(mine, ROWS, COLS);
    		printf("恭喜你!你赢了!\n");
    		return;
    	}
    	
    	/*DisplayBoard(mine, ROWS, COLS);
    	printf("\n");
    	printf("-------------------------\n");
    	printf("\n");*/
    	DisplayBoard(show, ROWS, COLS);
    	
    
    	while (1)
    	{
    		//判断玩家选择的坐标是不是地雷,若是则返回1,若不是则展开附近地雷信息
    		is = FindMine(mine, show, ROWS, COLS);
    		//如果面板上剩下的'*' 与地雷的总数相同时,玩家赢
    		if (CountShow(show, ROWS, COLS) == EASY_MODE)
    		{
    			printf("-------------------------\n");
    			DisplayBoard(mine, ROWS, COLS);
    			printf("恭喜你!你赢了!\n");
    			break;
    		}
    		
    		if (is == 1)
    		{
    			printf("BOOM!!!!!!!!!!\n");
    			printf("很遗憾,你被炸死了!\n");
    			DisplayBoard(mine, ROWS, COLS);
    			break;
    		}
    
    	/*	DisplayBoard(mine, ROWS, COLS);
    		printf("\n");
    		printf("-------------------------\n");
    		printf("\n");*/
    		DisplayBoard(show, ROWS, COLS);
    
    	}
    }
    
    
    int main(void)
    {
    	int i = 0;
    	int j = 0;
    	int input = 0;
    
    	srand((unsigned int)time(NULL));
    
    	//调用菜单函数,打印游戏菜单
    	menu();
    
    	do
    	{
    		printf("请输入您要选的选项:");
    		scanf("%d", &input);
    		switch (input)
    		{
    			case 1:
    				game();
    				break;
    			case 0:
    				printf("退出游戏!\n");
    				break;
    			default:
    				printf("输入错误!请重新输入!\n");
    				break;
    		}
    
    	} while (input);
    
    	system("pause");
    	return 0;
    }

    game.c

    #define _CRT_SECURE_NO_WARNINGS 1
    
    #include "game.h"
    
    void Init(char board[ROWS][COLS],   int row, int col, char ch)
    {
    	memset(&board[0][0], ch, row*col*sizeof(board[0][0]));
    }
    
    void DisplayBoard(char board[ROWS][COLS], int row, int col)
    {
    	int i = 0;
    	int j = 0;
    
    	//打印横坐标
    	printf("0 ");
    	for (i = 1; i < row - 1; i++)
    	{
    		printf("%d ", i);
    	}
    	printf("\n");
    
    	for (i = 1; i < row - 1; i++)
    	{
    		printf("%d ", i);
    		
    		for (j = 1; j < col - 1; j++)
    		{
    			printf("%c ", board[i][j]);
    		}
    		printf("\n");
    		
    	}
    }
    
    void setMine(char mine[ROWS][COLS], int row, int col)
    {
    	int x = 0;
    	int y = 0;
    	int count = EASY_MODE;
    
    
    	while (count)
    	{
    		//我们需要9个数字,如果%10产生的是0~8, 9个数字
    		//但是我们需要1~9,所以先%9产生8个数字,再加1就好
    		x = rand() % 9 + 1;
    		y = rand() % 9 + 1;
    		if (mine[x][y] == '0')
    		{
    			mine[x][y] = '1';
    			count--;
    		}
    	}
    }
    
    //踩到雷返回1,没有踩到雷返回0
    int FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    {
    	int x = 0;
    	int y = 0;
    	int count = 0;
    
    	
    	printf("请输入您选择的坐标:");
    	scanf("%d%d", &x, &y);
    
    	if (x < 1 && x > COL && y < 1 && y > ROW)
    	{
    		printf("您输入的坐标超过当前地图,请重新输入!\n");
    			
    	}
    	else
    	{
    		if (mine[x][y] == '0')
    		{
    			char ch = GetCount(mine, x, y);
    			show[x][y] = ch + '0';
    			book[x][y] = 1;
    			open(mine, show, x, y);
    			if (CountShow(show, row, col) == EASY_MODE)
    			{
    				return 0;
    			}
    		}
    		else if (mine[x][y] == '1')
    		{
    			return 1;
    		}
    
    	}
    	return 0;
    }
    
    int GetCount(char mine[ROWS][COLS], int x, int y)
    {
    	int count = 0;
    	//分别对(x,y)坐标周围8个格子进行判断,如果是雷则count + 1
    	//最后返回count就是(x,y)周围的地雷个数
    	if (mine[x - 1][y] == '1')
    		count++;
    	if (mine[x - 1][y - 1] == '1')
    		count++;
    	if (mine[x][y - 1] == '1')
    		count++;
    	if (mine[x + 1][y - 1] == '1')
    		count++;
    	if (mine[x + 1][y] == '1')
    		count++;
    	if (mine[x + 1][y + 1] == '1')
    		count++;
    	if (mine[x][y + 1] == '1')
    		count++;
    	if (mine[x - 1][y + 1] == '1')
    		count++;
    
    	return count;
    }
    
    //SafeMove函数是保证玩家输入第一个坐标时不被炸死
    void SafeMove(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    {
    	int x = 0;
    	int y = 0;
    	int flag = 1;
    	int count = 0;
    	char ch = 0;
    
    	while (1)
    	{
    		printf("请输入您要选择的坐标:");
    		scanf("%d%d", &x, &y);
    
    		if (x < 1 && x > COL && y < 1 && y > ROW)
    		{
    			printf("您输入的坐标超过当前地图,请重新输入!\n");
    			continue;
    		}
    
    		if (mine[x][y] == '1')
    		{
    			//如果玩家输入的坐标是1,则强行把这个坐标改为0
    			mine[x][y] = '0';
    			char ch = GetCount(mine, x, y);
    			show[x][y] = ch + '0';
    			book[x][y] = 1;
    			open(mine, show, x, y);
    			//将一个地雷改为了空地,则需要再随机填一个雷
    			while (flag)
    			{
    				x = rand() % 9 + 1;
    				y = rand() % 9 + 1;
    				if (mine[x][y] == '0')
    				{
    					mine[x][y] = '1';
    					flag--;
    					break;
    				}
    			}break;
    		}
    		else if (mine[x][y] == '0')
    		{
    			char ch = GetCount(mine, x, y);
    			show[x][y] = ch + '0';
    			book[x][y] = 1;
    			open(mine, show, x, y);
    			break;
    		}
    
    	}
    
    }
    
    //用深度优先搜索来对面板展开
    void open(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
    {
    	
    	int tx = 0;
    	int ty = 0;
    	int k = 0;
    	//定义next数组,用来对四个方向进行搜索
    	int next[4][2] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
    
    	//在展开的时候如果GetCount函数返回的不是0,则给show数组赋返回的值
    	if (GetCount(mine, x, y) != 0)
    	{
    		show[x][y] = GetCount(mine, x, y) + '0';
    	}
    	//如果是0,给show数组那个位置赋空格
    	else if (GetCount(mine, x, y) == 0)
    	{
    		show[x][y] = ' ';
    	}
    	
    	for (k = 0; k <= 3; k++)
    	{
    		tx = x + next[k][0];
    		ty = y + next[k][1];
    
    		if (tx < 1 || tx > ROW || ty < 1 || ty > COL)
    		{
    			continue;
    		}
    		if (mine[tx][ty] == '0' && book[tx][ty] == 0 && GetCount(mine, tx, ty) < 1)
    		{
    			
    			book[tx][ty] = 1;
    			open(mine, show, tx, ty);
    		
    		}
    		//这一步很关键,是展开时遇到数字停下来的一步
    		if (mine[tx][ty] == '0' && book[tx][ty] == 0 && GetCount(mine, tx, ty) > 0)
    		{
    			show[tx][ty] = GetCount(mine, tx, ty) + '0';
    			continue;
    		}
    		
    	}
    	return;
    }
    
    //统计面板上剩下的'*'
    int CountShow(char show[ROWS][COLS], int row, int col)//判断剩余未知区域的个数,个数为雷数时玩家赢
    {
    	int count = 0;
    	int i = 0;
    	int j = 0;
    	for (i = 1; i < row - 1; i++)
    	{
    		for (j = 1; j < col - 1; j++)
    		{
    			if (show[i][j] == '*')
    			{
    				count++;
    			}
    		}
    
    	}
    	return count;
    }
    

    总结:

        这个程序难的地方就是你要有一个清晰的思路,知道你需要干什么,所以这里我是先写大的框架,然后我需要用到什么,我再去写什么,一点一点的去完成。

        还有写程序的时候遇到难题就是再展开这一块,还好之前看的算法书起了作用,这里安利一本叫《啊哈!算法》的书,里面很可爱的讲了各种算法,推荐新手去看,绝对能看懂!

    展开全文
  • 纯js实现扫雷小游戏

    千次阅读 2018-10-07 10:24:28
    项目地址:https://github.com/zhuyuzhu/sweep-mine git地址:https://github.com/zhuyuzhu/sweep-mine.git (1)html代码: &lt;!DOCTYPE html&gt; &lt;html lang="...g...
  • 扫雷小游戏简单实现

    2018-10-07 20:22:07
    头文件 game.h #ifndef __GAME_H_ #define __GAME_H_ #include &lt;time.h&gt; #include &lt;stdlib.h&gt; #include &lt;stdio.h&gt; #include &...#define ROWS RO...
  • Java语言实现的扫雷游戏(一)

    万次阅读 多人点赞 2018-12-13 11:48:14
    Java类库中提供了用于GUI的swing开发工具包,我们可以利用swing设计出一些简单的经典小游戏,如扫雷,推箱子,俄罗斯方块等.接下来我就简单分享一下用Java设计扫雷游戏的思路与过程.  首先,我们要设计出扫雷的窗口界面...
  • VB6实现简单的扫雷小游戏

    万次阅读 2018-12-01 08:32:24
    VB实现简单的扫雷小游戏扫雷这个小游戏可谓是简单又好玩,百万不腻,不知道有没有小伙伴跟博主一样脑热的曾经扫过一整个屏幕的雷。。。今天呢,博主在这里总结一下自己做扫雷小游戏的主要过程以及主要思路,当然实际...
  • 扫雷游戏设计原理

    千次阅读 2011-07-20 11:26:34
    扫雷游戏设计原理:扫雷游戏分为几个步骤,由于比较多,所以在这里先列出来:第一步,使用二维数组表示地图;第二步,随机生成几个地雷;第三步,点击方格的反应,计算每个非雷区方格点开后的数字;第四步,当方格...
  • 扫雷外挂(扫雷辅助程序)

    千次阅读 2019-06-25 08:56:58
    主要分为以下三部分【定位窗口】【将扫雷界面转化为矩阵存储】【程序模拟人玩扫雷】。 通过扫雷程序的名称定位到具体程序的具体进程ID。 通过进程ID定位到窗口句柄。 在所有的窗口句柄中删选出主窗口。并可以获得...
  • 某人果然在下课前没能把扫雷代码编写完成,在逃课于宿舍奋斗几节课之后,扫雷小游戏逐渐成形,吊丝满足地笑了,整理好代码,习惯性地打开csdn论坛,准备发布一个帖子《[原创]C#实现的控制台扫雷小游戏,适合入门者...
  • 实现windows扫雷游戏初级的所有功能 扫雷尺寸99 方格 每个方格尺寸3030 游戏初始化时,随机分布10个地雷 当左键点击雷区任意方格时,则游戏开始 鼠标左键点击为翻开方格,为雷则游戏失败,非雷则显示其周围一圈地雷...
  • 如何开发一个扫雷小游戏

    千次阅读 2016-11-28 17:08:48
    本文介绍如何用C#开发一个扫雷小游戏
  • 基于Qt的扫雷游戏(附源码)

    千次阅读 2018-09-30 13:19:41
    基于Qt的扫雷游戏(附源码) 本人码农一枚,平日工作涉及面太窄,写代码也没有根据自己想法写来的开心。故周末挤出闲碎时间做些简单的内容来保持手感,先挑了个比较简单的扫雷游戏作为日后漫长之路的起步。此代码...
  • 上次发过一个俄罗斯方块的游戏源码,由于是通过Easy X实现的,但是很多和我一样的新手,一开始不知道Easy X是什么,到时源码拿过去之后,运行报错,我这次发的扫雷, 也是通过Easy X实现,Easy X是很多和我一样的...
  • JavaScript扫雷游戏,仿Windows扫雷

    千次阅读 2013-10-06 23:23:18
    javascript版仿windows扫雷游戏,单个HTML文件。 CSDN下载:http://download.csdn.net/source/1513308 在线试玩:http://jsgame.net/mine-cxp/ Javascript版扫雷v2.1 (13K) By: 无心 2006年12月 qq: 3092869 简述: ...
  • 做好以后,总觉得这种控制台的界面看着不舒服,自己又会一些GUI界面的知识,然后就做了个这么个小游戏.(本程序全部源代码已上传,需要的可以去下载) 编程最重要的是思路,让我们先把思路理清楚: 首先是了解一下扫雷规则...
  • C++ 扫雷小游戏实现(小白入门 + 详细解析)

    万次阅读 多人点赞 2020-06-13 22:15:39
    扫雷小游戏具体实现 寒假的时候作为一个接触C语言一个学期的咸鱼,笔者尝试挑战了贪吃蛇的编写 不过当时的笔者在编写过程中仍然大量借助了其他各路大佬的思路与算法 时至暑假,笔者决定编写扫雷小游戏,并且全程...
1 2 3 4 5 ... 20
收藏数 4,987
精华内容 1,994
关键字:

扫雷小游戏