📄 minepanel.java
字号:
/*
* MinePanel.java 1.0 2003-6-15
*
* Copyleft (c) 2003 RatKing.
*/
package jmine;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.border.*;
/**
* 总面板,包括上侧的笑脸按钮面板和下侧的雷区面板
*/
public class MinePanel extends JPanel implements MouseListener {
private JMine jmine;
public static final int ONE_SECOND = 1000; // 1秒 = 1000毫秒
public static final int LOW_LEVEL = 0; // 初级
public static final int MIDDLE_LEVEL = 1; // 中级
public static final int HIGH_LEVEL = 2; // 高级
public static final int CUSTOM_LEVEL = 3; // 自定义...
public static final int READY = 0; // 准备就绪
public static final int PLAY = 1; // 开始游戏
public static final int PAUSE = 2; // 暂停游戏
public static final int WIN = 3; // 胜利结束
public static final int LOSE = 4; // 失败结束
private int gameLevel = LOW_LEVEL; // 难度级别
private int mineRows = 0; // 雷区高度
private int mineColumns = 0; // 雷区宽度
private int totalMines = 0; // 地雷总数
public boolean isMark = true; // 标记
public boolean isColor = true; // 颜色
public boolean isSound = true; // 声音
private int state = READY; // 系统运行状态
/**
* 是否鼠标中键按下
* 当鼠标中键按下,或鼠标左右键同时按下时,为true
* 当释放了鼠标中键,或鼠标左右键同时按下后释放任意一个,则为false
*/
private boolean isMiddlePressed = false;
/** 开始按钮面板 */
JPanel startPanel = new JPanel();
/** 雷区面板 */
JPanel mineField = new JPanel();
GridLayout gridLayout = new GridLayout();
Border raisedbevel = BorderFactory.createRaisedBevelBorder();
Border loweredbevel = BorderFactory.createLoweredBevelBorder();
Border margin1 = new EmptyBorder(6,6,6,6);
Border margin2 = new EmptyBorder(4,6,4,6);
BorderLayout borderLayout = new BorderLayout();
public FaceButton faceButton; // 笑脸按钮
public MineButton[][] mineButton; // 雷区按钮
public Counter remainMines; // 剩余地雷数
public Counter totalTime; // 所用时间(秒数)
public Timer timer; // 计时器
public MinePanel(JMine jmine) {
this(jmine, LOW_LEVEL);
}
public MinePanel(JMine jmine, int gameLevel) {
this.jmine = jmine;
init();
setGameLevel(gameLevel);
}
/** 面板初始化,组装面板,制定布局与边框 */
public void init() {
// 设置面板的边框
this.setBorder(new CompoundBorder(raisedbevel, margin1));
startPanel.setBorder(new CompoundBorder(loweredbevel, margin2));
mineField.setBorder(loweredbevel);
// 设置面板的布局
borderLayout.setVgap(6); // 设置总面板中开始面板与地雷面板之间的间距
this.setLayout(borderLayout);
mineField.setLayout(gridLayout);
startPanel.setLayout(new BoxLayout(startPanel, BoxLayout.X_AXIS));
// 组装开始按钮
faceButton = new FaceButton(jmine);
remainMines = new Counter(jmine, totalMines);
totalTime = new Counter(jmine, 0);
totalTime.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// 若按下中键,或同时按下鼠标左键和右键,则暂停计时
if ((e.getButton() == MouseEvent.BUTTON2
|| (e.getModifiersEx() & (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK))
== (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK))) {
if (timer.isRunning()) {
timer.stop();
//state = PAUSE;
}
else if (state == PLAY) {
timer.start();
}
}
}
});
startPanel.add(remainMines);
startPanel.add(Box.createHorizontalGlue());
startPanel.add(faceButton);
startPanel.add(Box.createHorizontalGlue());
startPanel.add(totalTime);
faceButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
replay();
}
});
// 定义时钟及其事件处理方法
timer = new Timer(ONE_SECOND, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
totalTime.increase(); // “计时器”每增加1秒,“所用时间”就也增加1秒
if (isSound) {
Toolkit.getDefaultToolkit().beep();
}
}
});
// 组装总面板
this.add(startPanel, BorderLayout.NORTH);
this.add(mineField, BorderLayout.CENTER);
this.addMouseListener(this);
} // init()
public int getGameLevel() {
return gameLevel;
}
public void setGameLevel(int gameLevel) {
this.gameLevel = gameLevel;
if (gameLevel == LOW_LEVEL) {
reset(9, 9, 10);
}
else if (gameLevel == MIDDLE_LEVEL) {
reset(16, 16, 40);
}
else if (gameLevel == HIGH_LEVEL) {
reset(16, 30, 99);
}
}
public void setGameLevel(int mineRows, int mineColumns, int totalMines) {
gameLevel = CUSTOM_LEVEL;
reset(mineRows, mineColumns, totalMines);
}
public void replay() {
reset(mineRows, mineColumns, totalMines);
}
/**
* 系统重置
*/
private void reset(int mineRows, int mineColumns, int totalMines) {
state = READY;
timer.stop();
remainMines.setNumber(totalMines);
faceButton.setIconStyle(FaceButton.FACE_SMILE);
totalTime.setNumber(0);
// 是否雷区大小发生改变
boolean isChanged = false;
if (this.mineRows != mineRows
|| this.mineColumns != mineColumns
|| this.totalMines != totalMines) {
isChanged = true;
this.mineRows = mineRows;
this.mineColumns = mineColumns;
this.totalMines = totalMines;
}
if (isChanged) {
// 清除雷区所有地雷按钮
mineField.removeAll();
// 重置mineField面板中GridLayout布局的高度与宽度
gridLayout.setRows(mineRows); // 设置地雷的行数
gridLayout.setColumns(mineColumns); // 设置地雷的列数
// 生成地雷按钮,并组装到地雷面板中
mineButton = new MineButton[mineRows][mineColumns];
for (int i = 0; i < mineRows; i++) {
for (int j = 0; j < mineColumns; j++) {
mineButton[i][j] = new MineButton(jmine, i, j);
mineButton[i][j].addMouseListener(this);
mineField.add(mineButton[i][j]);
}
}
}
// 重置所有地雷按钮为初始状态
for (int i = 0; i < mineRows; i++) {
for (int j = 0; j < mineColumns; j++) {
mineButton[i][j].setMine(false);
mineButton[i][j].setIconStyle(MineButton.ICON_NULL);
}
}
// 随机分布地雷
Random random = new Random();
int k = 0;
while (k < totalMines) {
int r = random.nextInt(mineRows);
int c = random.nextInt(mineColumns);
if (!mineButton[r][c].isMine()) {
mineButton[r][c].setMine(true);
k++;
}
}
validate(); // 使改动生效
}
public int getMineRows() {
return mineRows;
}
public void setMineRows(int mineRows) {
this.mineRows = mineRows;
}
public int getMineColumns() {
return mineColumns;
}
public void setMineColumns(int mineColumns) {
this.mineColumns = mineColumns;
}
public int getTotalMines() {
return totalMines;
}
public void setTotalMines(int totalMines) {
this.totalMines = totalMines;
}
// 定义鼠标事件处理方法
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
if (state != READY && state != PLAY)
return;
faceButton.setIconStyle(FaceButton.FACE_O);
Object object = e.getSource();
if (!(object instanceof MineButton))
return;
int button = e.getButton();
int modifiers = e.getModifiers();
int modifiersEx = e.getModifiersEx();
MineButton mb = (MineButton) object;
// 按钮呈凹下的样子
if (mb.getIconStyle() == MineButton.ICON_NULL
|| mb.getIconStyle() == MineButton.ICON_MARK) {
mb.setBorderDown();
}
// 若仅按下鼠标右键,且左键未按下
if (button == MouseEvent.BUTTON3
&& (modifiersEx & InputEvent.BUTTON1_DOWN_MASK)
!= InputEvent.BUTTON1_DOWN_MASK) {
// 处理插上小红旗过程
if (mb.getIconStyle() == MineButton.ICON_NULL) {
mb.setIconStyle(MineButton.ICON_FLAG);
remainMines.decrease();
if (checkWinning()) {
doWin();
}
}
else if (mb.getIconStyle() == MineButton.ICON_FLAG) {
if (isMark) {
mb.setIconStyle(MineButton.ICON_MARK);
}
else {
mb.setIconStyle(MineButton.ICON_NULL);
}
remainMines.increase();
}
else if (mb.getIconStyle() == MineButton.ICON_MARK) {
mb.setIconStyle(MineButton.ICON_NULL);
}
return;
}
// 若按下中键,或同时按下鼠标左键和右键
if (button == MouseEvent.BUTTON2
|| (modifiersEx & (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK))
== (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK)) {
isMiddlePressed = true;
doDownAround(mb);
}
}
public void mouseReleased(MouseEvent e) {
if (state != READY && state != PLAY)
return;
faceButton.setIconStyle(FaceButton.FACE_SMILE);
Object object = e.getSource();
if (!(object instanceof MineButton))
return;
MineButton mb = (MineButton) object;
int button = e.getButton();
int modifiers = e.getModifiers();
int modifiersEx = e.getModifiersEx();
// 如果在地雷按钮外部释放鼠标,则把该鼠标释放事件传输到鼠标所在的按钮
if (!mb.contains(e.getX(), e.getY())) {
int x = e.getX();
int y = e.getY();
int width = mb.getSize().width;
int height = mb.getSize().height;
int row = mb.getRow();
int column = mb.getColumn();
//System.out.println("Debug: row = " + row + ", column = " + column + ", e = " + e);
if (y > 0)
row += y / height;
else
row -= -y / height + 1;
if (x > 0)
column += x / width;
else
column -= -x / width + 1;
if (row >= 0 && column >= 0 && row < mineRows && column < mineColumns) {
//System.out.println("Debug2: row = " + row + ", column = " + column
// + ", e = " + SwingUtilities.convertMouseEvent(mb, e, mineButton[row][column]));
mineButton[row][column].dispatchEvent(SwingUtilities.convertMouseEvent(mb, e, mineButton[row][column]));
}
return;
}
// 若释放了左键,且此时右键未按下
if (button == MouseEvent.BUTTON1 && !isMiddlePressed
&& ((modifiersEx & InputEvent.BUTTON3_DOWN_MASK) != InputEvent.BUTTON3_DOWN_MASK)) {
treadMineButton(mb);
}
// 若释放了中键,或释放了左右键同时按下后的任何一个
if (isMiddlePressed || button == MouseEvent.BUTTON2
|| (button == MouseEvent.BUTTON1
&& (modifiersEx & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK)
|| (button == MouseEvent.BUTTON3
&& (modifiersEx & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK)) {
isMiddlePressed = false;
doDoubleDownReleased(mb);
}
}
public void mouseEntered(MouseEvent e) {
if (state != READY && state != PLAY)
return;
Object object = e.getSource();
int modifiersEx = e.getModifiersEx();
if (!(object instanceof MineButton))
return;
MineButton mb = (MineButton) object;
// 若按下了鼠标左键、或中键,或同时按下了左右键
if ((modifiersEx & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK
|| (modifiersEx & InputEvent.BUTTON2_DOWN_MASK) == InputEvent.BUTTON2_DOWN_MASK
|| (modifiersEx & (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK))
== (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK)) {
// 按钮呈凹下的样子
if (mb.getIconStyle() == MineButton.ICON_NULL
|| mb.getIconStyle() == MineButton.ICON_MARK) {
mb.setBorderDown();
}
}
// 若按下了鼠标中键,或同时按下了鼠标左键和右键
if ((modifiersEx & InputEvent.BUTTON2_DOWN_MASK) == InputEvent.BUTTON2_DOWN_MASK
||(modifiersEx & (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK))
== (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK)) {
// 周围按钮呈凹下的样子
doDownAround(mb);
}
}
public void mouseExited(MouseEvent e) {
if (state != READY && state != PLAY)
return;
Object object = e.getSource();
int modifiersEx = e.getModifiersEx();
if (!(object instanceof MineButton))
return;
MineButton mb = (MineButton) object;
// 按钮呈凸出的样子
if (mb.getIconStyle() == MineButton.ICON_NULL
|| mb.getIconStyle() == MineButton.ICON_MARK) {
mb.setBorderUp();
}
// 若按下了鼠标中键,或同时按下了鼠标左键和右键
if ((modifiersEx & InputEvent.BUTTON2_DOWN_MASK) == InputEvent.BUTTON2_DOWN_MASK
||(modifiersEx & (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK))
== (InputEvent.BUTTON1_DOWN_MASK | InputEvent.BUTTON3_DOWN_MASK)) {
// 周围按钮呈凸出的样子
doUpAround(mb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -