9.8.7 扩展方向调整 我们注意到,四个方向对于推断结果不太友好,展开形状是锯齿形,可玩性有限 因此我们把四个方向的改成八个方向: private final int [][] direction = new int [][]{{ - 1 , -
9.8.7 扩展方向调整
我们注意到,四个方向对于推断结果不太友好,展开形状是锯齿形,可玩性有限
因此我们把四个方向的改成八个方向:
private final int[][] direction = new int[][]{{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};private void dfs(int i, int j){
if(i<0 || i >= row || j < 0 || j >= col || visited[i][j] || hasSweeper[i][j])
return;
visited[i][j] = true;
JButton b = posSweeper.get(i).get(j);
b.setEnabled(false);
--last;
int sweepCnt = getSweepCnt(i,j);
if(sweepCnt>0){
b.setText(""+sweepCnt);
return;
}
for(int x = 0; x < 8; x++){
int l = i+direction[x][0];
int c = j+direction[x][1];
dfs(l,c);
}
}
效果:
边角锯齿消失
9.8.8 菜单栏
有时候玩到一半太难了,想重来,需要退出键
JMenuBar menuBar = new JMenuBar();JMenu operator = new JMenu("操作");
restartMenu = new JMenuItem("重新开始");
exitMenu = new JMenuItem("退出");
operator.add(restartMenu);
operator.add(exitMenu);
menuBar.add(operator);
setJMenuBar(menuBar);
restartMenu.addActionListener(this);
exitMenu.addActionListener(this);
当前类实现ActionListener接口,同时重写抽象方法:
@Overridepublic void actionPerformed(ActionEvent e) {
if(e.getSource() == restartMenu){
init();
}else if(e.getSource() == exitMenu){
System.exit(0);
}
}
全部代码:
import javax.swing.*;import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
public class Main {
public static void main(String[] args) {
Main solution = new Main();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MineSweeperFrame MineSweeperFrame = new MineSweeperFrame();
MineSweeperFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MineSweeperFrame.setVisible(true);
}
});
}
}
class MineSweeperFrame extends JFrame implements ActionListener {
public static final int W = 500;
public static final int H = 500;
Map<JButton,int[]> sweeperPos = new HashMap<>();
Map<Integer,Map<Integer,JButton>> posSweeper = new HashMap<>();
boolean[][] hasSweeper;
boolean[][] visited;
int sweepCnt = 10;
int row = 10;
int col = 10;
int last = row*col;
private final int[][] direction = new int[][]{{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
List<int[]> allSweeps = new ArrayList<>();
private JMenuItem restartMenu;
private JMenuItem exitMenu;
Random r = new Random();
public MineSweeperFrame(){
setTitle("扫雷游戏");
setSize(W,H);
setLayout(new GridLayout(row,col));
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
JButton button = new JButton();
add(button);
sweeperPos.put(button,new int[]{i,j});
button.addMouseListener(new Sweeper());
int[] xy = sweeperPos.get(button);
posSweeper.putIfAbsent(xy[0],new HashMap<>());
posSweeper.get(xy[0]).put(xy[1],button);
}
}
init();
JMenuBar menuBar = new JMenuBar();
JMenu operator = new JMenu("操作");
restartMenu = new JMenuItem("重新开始");
exitMenu = new JMenuItem("退出");
operator.add(restartMenu);
operator.add(exitMenu);
menuBar.add(operator);
setJMenuBar(menuBar);
restartMenu.addActionListener(this);
exitMenu.addActionListener(this);
}
private void init(){
last = 100;
for(JButton button:sweeperPos.keySet()){
button.setEnabled(true);
button.setIcon(null);
button.setText("");
}
hasSweeper = new boolean[row][col];
visited = new boolean[row][col];
allSweeps.clear();
setSweeps();
}
private void setSweeps(){
int x = 0;
int y = 0;
int total = row*col;
for(int i = 0; i < sweepCnt; i++){
do{
int pos = r.nextInt(total);
x = pos/col;
y = pos%col;
}while (hasSweeper[x][y]);
hasSweeper[x][y] = true;
allSweeps.add(new int[]{x,y});
}
//输出,检查效果用
for(int i = 0; i < row; i++){
System.out.println(Arrays.toString(hasSweeper[i]));
}
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == restartMenu){
init();
}else if(e.getSource() == exitMenu){
System.exit(0);
}
}
class Sweeper extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
int c = e.getButton();
JButton b = (JButton) e.getSource();
if (c == MouseEvent.BUTTON1){ //左键
int[] pos = sweeperPos.get(b);
int i = pos[0];
int j = pos[1];
if(hasSweeper[i][j]){
for(int [] sweepPos:allSweeps){
posSweeper.get(sweepPos[0]).get(sweepPos[1]).setIcon(new ImageIcon("src/resource/p1.png"));
}
int selection = JOptionPane.showConfirmDialog(MineSweeperFrame.this,"你输了!","结果",
JOptionPane.DEFAULT_OPTION);
init();
}else {
dfs(i,j);
if(last == sweepCnt){
int selection = JOptionPane.showConfirmDialog(MineSweeperFrame.this,"你赢了!太棒了!","结果",
JOptionPane.DEFAULT_OPTION);
init();
}
}
}else if(c==MouseEvent.BUTTON3){//右键
if(b.getIcon()==null)
b.setIcon(new ImageIcon("src/resource/flag.png"));
else
b.setIcon(null);
}
}
}
private void dfs(int i, int j){
if(i<0 || i >= row || j < 0 || j >= col || visited[i][j] || hasSweeper[i][j])
return;
visited[i][j] = true;
JButton b = posSweeper.get(i).get(j);
b.setEnabled(false);
--last;
int sweepCnt = getSweepCnt(i,j);
if(sweepCnt>0){
b.setText(""+sweepCnt);
return;
}
for(int x = 0; x < 8; x++){
int l = i+direction[x][0];
int c = j+direction[x][1];
dfs(l,c);
}
}
private int getSweepCnt(int x, int y){
int cnt = 0;
for(int i = x-1; i <= x+1; i++){
for(int j = y-1; j <= y+1; j++){
if(i==x&&y==j) continue;
if(i<0 || i >= row || j < 0 || j >= col) continue;
if(hasSweeper[i][j]){
++cnt;
}
}
}
return cnt;
}
}
效果:
至此,整个扫雷小项目就写完了,感兴趣的同学可以继续写,如添加计时器,增加表情,设置不同难度
相关内容:选择 《Java核心技术 卷1》查找相关笔记
评论