基本信息
源码名称:Java 实现扫雷游戏(MineSweeper)
源码大小:0.41M
文件格式:.zip
开发语言:Java
更新时间:2015-09-11
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300

本次赞助数额为: 2 元 
   源码介绍


package com.kerence.mine.mineGUI;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;

import com.kerence.mine.data_structure.MineMatrix;
import com.kerence.mine.mine_model.Strategy.MineMatrixSettable;
import com.kerence.mine.res.image.ImageIconFactory;

/**
 * 扫雷矩阵面板
 * 
 * @author Kerence
 * 
 */
public class JMineMatrixPanel extends JPanel
{
	private JMineSweeperFrame mineSweeperFrame;

	/**
	 * 得到一个JMineSweeperFrame的引用,这样才能对statusPanel进行操作
	 * 
	 * @param mineSweeperFrame
	 *            一个JMineSweeperFrame对象的引用
	 */
	public void addMineSweeperFrame(JMineSweeperFrame mineSweeperFrame)
	{
		this.mineSweeperFrame = mineSweeperFrame;
	}

	/**
	 * 雷块鼠标监听器
	 * 
	 * @author Kerence
	 * 
	 */
	private class BlockMouseListener extends MouseAdapter
	{
		/**
		 * 鼠标移入时进行的操作
		 */
		@Override
		public void mouseEntered(MouseEvent e)
		{
			currentMineBlock = ((JMineBlock) e.getSource());
			int row = currentMineBlock.getRow();
			int column = currentMineBlock.getColumn();
			if (button1Pressed && button3Pressed)
			{
				setAutoProbeIcons(row, column);
			} else
			{
				if (button1Pressed)
				{// 在鼠标左键按下的条件下

					if (isFlagged(row, column))
					{
						return;
					}
					if (isDigged(row, column))
					{
						return;
					} else
					{// 若没被挖则 显示空白
						currentMineBlock.setBlankPressed();
						return;
					}
				}
			}

		}

		/**
		 * 鼠标移出时进行的操作
		 */
		@Override
		public void mouseExited(MouseEvent e)
		{

			if (button3Pressed && button1Pressed)
			{// 两键同时被按下的情况
				// 显示出原图
				if (currentMineBlock != null)
				{
					int row = currentMineBlock.getRow();
					int column = currentMineBlock.getColumn();
					revertAutoProbeIcons(row, column);
				}
				currentMineBlock = null;
				return;
			}
			if (button3Pressed)
			{// 右键被按下
				currentMineBlock = null;
			} else
			{// 右键未被按下
				int row = currentMineBlock.getRow();
				int column = currentMineBlock.getColumn();

				if (button1Pressed)
				{// 左键按下 显示原图
					if (isFlagged(row, column))
					{
					} else if (!isDigged(row, column))
					{

						if (isRabotOn() && isMine(row, column))
						{
							currentMineBlock.setDot();
						} else
						{
							currentMineBlock.setBlank();
						}
					}
					currentMineBlock = null;
					return;
				}

				if (isDigged(row, column))
				{
					currentMineBlock = null;
					return;
				} else
				{
					refreshMineMatrixPanel();
				}
			}
			currentMineBlock = null;
		}

		/**
		 * 鼠标单击时进行的操作
		 */
		@Override
		public void mousePressed(MouseEvent e)
		{
			// 鼠标的操作有哪些 特别是鼠标按下的操作
			if (e.getButton() == MouseEvent.BUTTON1)
			{
				button1Pressed = true;
			} else if (e.getButton() == MouseEvent.BUTTON3)
			{
				button3Pressed = true;
			}

			// 得到被按下的块的行和列
			int row = currentMineBlock.getRow();
			int column = currentMineBlock.getColumn();
			// 左右键都按下,则探测
			if (button1Pressed && button3Pressed)
			{// 两键都被按下
				mineSweeperFrame.leftButtonPressedOnMineBlock();
				// TODO auto probe
				setAutoProbeIcons(row, column);
				// refreshMineMatrixPanel();
			} else if (button1Pressed && !button3Pressed)
			{// 左键按下,右键未按下
				mineSweeperFrame.leftButtonPressedOnMineBlock();
				if (isDigged(row, column))
				{
					return;
				} else if (isFlagged(row, column))
				{// 被置旗则也不变
					return;
				}
				jMineMatrix[row][column].setBlankPressed();
			} else if (button3Pressed && !button1Pressed)
			{// 右键被按下 左键未按下

				// 若被挖则无反应
				if (isDigged(row, column))
				{
					return;
				}
				// 未被挖则要判断是否被置旗 是否被置标记
				if (isFlagged(row, column))
				{// 若已放旗
					if (isMarkable())
					{// 可标记
						setUnFlagged(row, column);// 先取消旗
						setMarked(row, column);// 设为标记
					} else
					{// 不可标记
						setUnFlagged(row, column);// 取消旗
					}

				} else
				{// 若未放旗
					if (isMarked(row, column))
					{// 若被标记
						setUnMarked(row, column);// 设置为未标记
					} else
					{
						setFlagged(row, column);
					}

				}
				mineSweeperFrame.setLEDMineCountLeft(mineMatrix.getMineCount() - mineMatrix.getFlagCount());
				refreshMineMatrixPanel();
				return;
			}

		}

		/**
		 * 鼠标释放时进行的操作
		 */
		@Override
		public void mouseReleased(MouseEvent e)
		{// 它的源是鼠标按下时的组件。
			boolean button1Released = false, button3Released = false;
			if (e.getButton() == MouseEvent.BUTTON1)
			{
				button1Pressed = false;
				button1Released = true;
			} else if (e.getButton() == MouseEvent.BUTTON3)
			{
				button3Pressed = false;
				button3Released = true;
			}
			// 鼠标的操作有哪些 特别是鼠标放开的操作
			// 左键放开时
			// 右键按下
			// 这时要进行的操作是自动探测并挖雷 刷新一次界面
			// 鼠标释放事件汇总 左键放开 右键放开。
			if ((button1Released && button3Pressed)// 就是进行探测了。
					|| (button1Pressed && button3Released))
			{// 右键按下时 左键放开
				// 或者左键按下时右键放开

				if (currentMineBlock == null)
				{
					return;
				}
				int row = currentMineBlock.getRow();
				int column = currentMineBlock.getColumn();

				mineSweeperFrame.leftButtonReleasedOnMineBlock();// 对状态栏进行的操作
				// 恢复图形显示
				revertAutoProbeIcons(row, column);
				if (!isDigged(row, column))
				{// 如果没被挖过就不能自动探测
					return;
				}
				mineMatrix.autoDetectMine(currentMineBlock.getRow(), currentMineBlock.getColumn());
				if (mineMatrix.isGameOver())
				{
					// 找到所有雷并
					// mineMatrix.gameOver();// 进行gameOver的雷阵设置
					gameTerminates();
					button3Pressed = false;
					button1Pressed = false;
					mineSweeperFrame.gameOver();
				} else if (mineMatrix.isGameComplete())
				{
					mineMatrix.gameComplete();
					gameTerminates();
					button3Pressed = false;
					button1Pressed = false;
					mineSweeperFrame.gameComplete();
				}
				refreshMineMatrixPanel();// 刷新图形显示
				return;
			}

			// 左键放开
			// 挖雷 若已被挖开则不挖 刷新一次界面
			else if (button1Released && !button3Pressed)
			{// 右键未按下时左键放开挖雷
				mineSweeperFrame.leftButtonReleasedOnMineBlock();
				if (currentMineBlock == null)
				{
					return;
				}

				int row = currentMineBlock.getRow();
				int column = currentMineBlock.getColumn();
				if (mineMatrix.isDigged(row, column))
				{// 判断是否已经被挖开
					return;
				} else
				{// 没挖开就挖
					// 还要判断是否是第一挖
					if (mineMatrix.isFlagged(row, column))
					{// 要先判断是否放旗。
						// 是旗则不挖
						return;
					}
					if (!mineMatrix.hasGameCommenced())
					{// 如果未开局
						generateRandomMatrix(row, column);// 并生成雷阵列。
						mineMatrix.setGameCommenced(true);// 设置成开局
						activateStatusPanel();// 通知主窗口游戏开始。只是对状态栏进行设置而已
						// 而且这里的命名好像不好吧。应该换成activatestatuspanel
					}
					mineMatrix.digBlock(row, column);// 挖雷包括自动挖开周围的雷
					// 如果是雷则自动可以挖开所有的雷。
					// 判断是否挖的是雷

					if (isMine(row, column))
					{// 如果挖的是雷则释放所有监听器
						mineMatrix.setGameOver(true);
						gameTerminates(); // 释放所有雷区按钮的监听器
						mineSweeperFrame.gameOver();// 通知扫雷框架对状态进行设置

					} else if (mineMatrix.isGameComplete())
					{
						gameTerminates();
						mineMatrix.gameComplete();
						mineSweeperFrame.gameComplete();
					}
					refreshMineMatrixPanel();// 刷新界面
				}
			}
		}
	}

	/**
	 * 设置row行column列的雷为标记
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 */
	private void setMarked(int row, int column)
	{
		this.mineMatrix.setMarked(row, column);
	}

	/**
	 * 设置row行column列的雷为未标记
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 */
	private void setUnMarked(int row, int column)
	{
		this.mineMatrix.setUnMarked(row, column);

	}

	/**
	 * 返回是否可以标记
	 * 
	 * @return 要否标记的状态
	 */
	private boolean isMarkable()
	{
		return mineMatrix.isMarkable();
	}

	/**
	 * 激活状态栏
	 */
	private void activateStatusPanel()
	{
		mineSweeperFrame.gameCommences();
	}

	/**
	 * 设置自动探测状态下雷块周围图标的显示
	 * 
	 * @param row
	 *            雷块的行号
	 * @param column
	 *            雷块的列号
	 */
	private void setAutoProbeIcons(int row, int column)
	{// 自动探测时的图标显示
		// 将周围被标记的置为标记按下
		for (int i = -1; i < 2; i  )
		{
			for (int j = -1; j < 2; j  )
			{
				setAutoProbeIcon(row   i, column   j);
			}
		}
	}

	/**
	 * 设置自动探测状态下恢复雷块周围图标的显示
	 * 
	 * @param row
	 *            雷块的行号
	 * @param column
	 *            雷块的列号
	 */
	private void revertAutoProbeIcons(int row, int column)
	{// 自动探测时的图标显示
		// 将周围被标记的置为标记按下
		for (int i = -1; i < 2; i  )
		{
			for (int j = -1; j < 2; j  )
			{
				revertAutoProbeIcon(row   i, column   j);
			}
		}
	}

	/**
	 * 设置自动探测状态下该雷块的图标显示
	 * 
	 * @param row
	 *            雷块的行号
	 * @param column
	 *            雷块的列号
	 */
	private void setAutoProbeIcon(int row, int column)
	{// 自动探测时的图标显示
		if (row < 0 || row > this.getMatrixRowCount() - 1 || column < 0 || column > this.getMatrixColumnCount() - 1)
		{
			return;
		}
		// 将周围被标记的置为标记按下
		if (isMarked(row, column))
		{
			this.jMineMatrix[row][column].setMarkPressed();
			return;
		}
		// 将周围未被挖或者未被置旗不改变图案
		if (isDigged(row, column) || isFlagged(row, column))
		{
			return;
		}
		// 否则显示为按下
		this.jMineMatrix[row][column].setBlankPressed();
	}

	/**
	 * 恢复雷块的自动探测状态下的图标
	 * 
	 * @param row
	 *            雷块的和行号
	 * @param column
	 *            雷块的列号
	 */
	private void revertAutoProbeIcon(int row, int column)
	{// 自动探测时的图标显示
		if (row < 0 || row > this.getMatrixRowCount() - 1 || column < 0 || column > this.getMatrixColumnCount() - 1)
		{
			return;
		}
		// 将周围被标记的置为标记按下
		if (isMarked(row, column))
		{
			this.jMineMatrix[row][column].setAsk();
			return;
		}
		// 将周围未被挖或者未被置旗的 置为按下
		if (isDigged(row, column) || isFlagged(row, column))
		{
			return;
		}
		// 否则显示为空白
		if (isRabotOn() && isMine(row, column))
		{
			this.jMineMatrix[row][column].setDot();
			return;
		}
		this.jMineMatrix[row][column].setBlank();
	}

	MouseListener blockMouseListener = new BlockMouseListener();
	private boolean button1Pressed;
	private boolean button3Pressed;
	private JMineBlock currentMineBlock;

	private JMineBlock[][] jMineMatrix;

	private MineMatrix mineMatrix = new MineMatrix();

	/**
	 * 构造方法,设置边界,背景色等。
	 */
	public JMineMatrixPanel()
	{

		Border b1 = BorderFactory.createCompoundBorder(new BevelBorder(BevelBorder.LOWERED), new BevelBorder(BevelBorder.LOWERED));
		Border b2 = BorderFactory.createCompoundBorder(new EmptyBorder(5, 5, 5, 5), b1);
		setBorder(b2);
		setBackground(Color.LIGHT_GRAY);

	}

	/**
	 * 重置游戏
	 */
	public void resetGame()
	{// 重置游戏
		this.resetMatrixPanel();

	}

	/**
	 * 游戏结束
	 */
	private void gameTerminates()
	{
		// 要做哪些操作
		// 1.让所有的点击雷区事件都没有响应, 即释放所有监听器

		for (int row = 0; row < this.getMatrixRowCount(); row  )
		{
			for (int column = 0; column < this.getMatrixColumnCount(); column  )
			{
				jMineMatrix[row][column].removeMouseListener(blockMouseListener);

			}
		}
	}

	/**
	 * 生成随机布雷的矩阵 其中指定位置不能是雷
	 * 
	 * @param specifiedRow
	 *            指定的雷块行号
	 * @param specifiedColumn
	 *            指定的雷块列号
	 */
	public void generateRandomMatrix(int specifiedRow, int specifiedColumn)
	{
		mineMatrix.generateRandomMatrix(specifiedRow, specifiedColumn);
	}

	/**
	 * 得到当前鼠当前指向的雷块的列号
	 * 
	 * @return 列号
	 */
	public int getCurrentBlockColumn()
	{
		return currentMineBlock.getColumn();
	}

	/**
	 * 得到当前鼠当前指向的雷块的行号
	 * 
	 * @return 行号
	 */
	public int getCurrentBlockRow()
	{
		return currentMineBlock.getRow();
	}

	/**
	 * 得到矩阵列数
	 * 
	 * @return 列数
	 */
	public int getMatrixColumnCount()
	{
		return this.mineMatrix.getMatrixColumnCount();
	}

	/**
	 * 得到矩阵行数
	 * 
	 * @return 行数
	 */
	public int getMatrixRowCount()
	{
		return this.mineMatrix.getMatrixRowCount();
	}

	/**
	 * 得到矩阵中雷的个数
	 * 
	 * @return 雷个数
	 */
	public int getMineCount()
	{
		return this.mineMatrix.getMineCount();
	}

	/**
	 * 得到某个雷块周围的雷的个数
	 * 
	 * @return 周围雷的个数
	 */
	public int getMineCountAround(int row, int column)
	{
		return this.mineMatrix.getMineCountAround(row, column);
	}

	/**
	 * 返回某个位置的雷块是否被挖
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 * @return 被挖的状态
	 */
	public boolean isDigged(int row, int column)
	{
		return this.mineMatrix.isDigged(row, column);
	}

	/**
	 * 返回某个位置的雷块是否被置旗
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 * @return 被置旗的状态
	 */
	public boolean isFlagged(int row, int column)
	{
		return this.mineMatrix.isFlagged(row, column);
	}

	/**
	 * 返回某个位置的雷块是否被标记
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 * @return 被标记的态
	 */
	public boolean isMarked(int row, int column)
	{
		return mineMatrix.isMarked(row, column);
	}

	/**
	 * 返回某个位置的雷块是否是雷
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 * @return 是否是雷的状态
	 */
	public boolean isMine(int row, int column)
	{
		return this.mineMatrix.isMine(row, column);
	}

	/**
	 * 刷新矩阵面板,即雷阵上的雷状态发生变化时调用这个方法,刷新界面
	 */
	public void refreshMineMatrixPanel()
	{
		int row = this.getMatrixRowCount();
		int column = this.getMatrixColumnCount();
		for (int r = 0; r < row; r  )
		{
			for (int c = 0; c < column; c  )
			{
				if (this.isDigged(r, c))
				{// 被挖过
					if (this.isMine(r, c))
					{// 是雷
						// 被挖是雷 则显示出红雷
						this.jMineMatrix[r][c].setRedMine();

					} else
					{// 如果不是雷则显示出数字
						// 设置正确数字 被挖是雷无标记
						int count = this.getMineCountAround(r, c);
						this.jMineMatrix[r][c].setNumber(count);
					}
				} else
				{// 没被挖过则 显示是否放置旗 和标记

					if (isFlagged(r, c) && !isMine(r, c) && mineMatrix.isGameOver())
					{// 没被挖过 被置旗 不是雷
						jMineMatrix[r][c].setWrongMine();
						continue;
					}
					if (!isFlagged(r, c) && isMine(r, c) && mineMatrix.isGameOver())
					{// 游戏结束是雷而且没被置旗
						jMineMatrix[r][c].setMine();
						continue;
					}
					if (isFlagged(r, c))
					{// 未挖过,是旗
						jMineMatrix[r][c].setFlag();
						continue;
					}
					if (isMarked(r, c))
					{// 没被挖过 被置标记
						jMineMatrix[r][c].setAsk();
						continue;

					}
					if (isRabotOn() && isMine(r, c))
					{// 开启作弊而且又是雷
						jMineMatrix[r][c].setDot();
						continue;
					}
					// 以上情况都不是,则显示出空白
					jMineMatrix[r][c].setBlank();
				}
			}
		}
	}

	/**
	 * 返回外挂是否开启
	 * 
	 * @return 外挂状态
	 */
	private boolean isRabotOn()
	{
		return this.mineMatrix.isRatbotOn();
	}

	/**
	 * 返回外挂是否开启
	 * 
	 * @return 外挂状态
	 */
	protected void setDigged(int row, int column)
	{
		this.mineMatrix.setDigged(row, column);
	}

	/**
	 * 设置某个位置的雷块被标记
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 */
	public void setFlagged(int row, int column)
	{
		this.mineMatrix.setFlagged(row, column);
	}

	/**
	 * 更改游戏模式
	 * 
	 * @param mineMatrixSettable
	 *            游戏模式对象引用
	 */
	public void setMineMatrix(MineMatrixSettable mineMatrixSettable)
	{
		mineMatrixSettable.setMineMatrix(mineMatrix);
		mineMatrix.setMineMatrixSettable(mineMatrixSettable);
		int row = this.getMatrixRowCount();
		int column = this.getMatrixColumnCount();
		jMineMatrix = new JMineBlock[row][column];
		resetMatrixPanel();

	}

	/**
	 * 重置矩阵面板 当游戏模式改变时调用它生成新的雷阵列
	 */
	private void resetMatrixPanel()
	{
		resetMineMatrixLabel();// 重置雷标的数量
		mineMatrix.resetMatrix();// 重置底层雷阵
	}

	/**
	 * 得到游戏模式
	 * 
	 * @return 游戏模式描述的字符串
	 */
	public String getGameMode()
	{
		return this.mineMatrix.getGameMode();
	}

	/**
	 * 重置雷阵列图标 将之前所有的雷块图标都清除然后重新生成雷块图标对象
	 * 
	 */
	private void resetMineMatrixLabel()
	{// 重置雷阵的图标数量。
		int row = this.getMatrixRowCount();
		int column = this.getMatrixColumnCount();
		this.setLayout(new GridLayout(row, column));
		this.removeAll();
		this.mineMatrix.setGameCommenced(false);
		for (int r = 0; r < row; r  )
		{
			for (int c = 0; c < column; c  )
			{
				this.jMineMatrix[r][c] = new JMineBlock(ImageIconFactory.getBlank());
				jMineMatrix[r][c].setRow(r);
				jMineMatrix[r][c].setColumn(c);
				this.jMineMatrix[r][c].addMouseListener(this.blockMouseListener);
				this.add(jMineMatrix[r][c]);

			}
		}
	}

	/**
	 * 取消某个位置的雷块的置旗状态
	 * 
	 * @param row
	 *            行号
	 * @param column
	 *            列号
	 */
	public void setUnFlagged(int row, int column)
	{
		this.mineMatrix.setUnFlagged(row, column);

	}

	/**
	 * 得到当前模式雷阵的列数
	 * 
	 */
	public int getColumnCount()
	{
		return this.mineMatrix.getColumn();
	}

	/**
	 * 得到当前模式雷阵的行数
	 * 
	 */
	public int getRowCount()
	{
		return this.mineMatrix.getRow();
	}

	/**
	 * 设置是否可以标记
	 * 
	 * @param b
	 *            可否标记的状态
	 */
	public void setMarkable(boolean b)
	{
		this.mineMatrix.setMarkable(b);
	}

	/**
	 * 设置外挂状态
	 * 
	 * @param b
	 *            外挂状态
	 */
	public void setRabot(boolean b)
	{
		this.mineMatrix.setRabot(b);
	}

}