最近打算入门一下java,写个小程序练下手,由于平时没事喜欢玩几把扫雷,就写个AI玩玩吧。。
java实现扫雷游戏网上代码比较多,这里不多说了,主要记录一下自己实现的一个自动扫雷策略。
根据扫雷的规则:一个数字x意味着其所在格子旁边的8个格子中有x个雷。那么我一共为电脑设了3步策略;
第一步:存在局部解的情况,即一个数字x,周围的空格子数y,周围已经确定是雷的格子数z,x,y,z的数字关系满足一定条件可以推出旁边的空格子是雷还是空。
第二步:如果第一步无解,则考虑第二步。如果找不到局部解,我们就根据多个数字之间的关系来确定空格子是雷还是空,想让这些数字建立起关系的方式就是根据每个数字,将其周围的8个格子分别设一个未知数,如果是雷我们让解为1,如果是空解就为0,这样可以连立出一个线性方程组,那么只要解出这个线性方程组,高斯消元一下,就可以做出决策。注意这里出现多解是很有可能的事,这里有一个不可忽略的条件,任意未知数只能为0或1。
第三步:如果第二步无解,则考虑第三步。随便点一个。。。
当然,在做第三步决策之前,完全可以根据解的概率分布(相对随机来说)大概率的做出一个正确解,而不是完全随机点一个。但是水平有限,高级的话复杂度可能有点高,时间有限,就没细想了。
做了1000局的实验,初级胜率81%(1000/810),中级胜率81.2%(1000/812),高级23.8%(1000/238)。
附上所有class的代码。
class boomInitialization:
package HBoom;
import java.util.Random;
import HBoom.Station;
public class boomInitialization {
protected Station[][] Array;
protected int[] blockX;
protected int[] blockY;
protected static int blockNum;
protected static int currentBlockNum;
private static int blockAround;
private static int newX;
private static int newY;
public boomInitialization(int X, int Y, int N) {
blockNum = 0;
currentBlockNum = 0;
Array = new Station[X + 1][Y + 1];
blockX = new int[N];
blockY = new int[N];
blockNum = N;
for(int i = 1; i <= X; ++i) {
for(int j = 1; j <= Y; ++j) {
Array[i][j] = Station.zero;
}
}
Random blockCreator = new Random();
while(currentBlockNum < blockNum) {
newX = blockCreator.nextInt(X) + 1;
newY = blockCreator.nextInt(Y) + 1;
if(Judge(newX, newY)){
Array[newX][newY] = Station.block;
blockX[currentBlockNum] = newX;
blockY[currentBlockNum] = newY;
currentBlockNum++;
}
}
//counting numbers
for(int i = 1; i <= X; ++i) {
for(int j = 1; j <= Y; ++j) {
if(Array[i][j] != Station.block) {
blockAround = 0;
if(i - 1 >= 1 && j - 1 >= 1) {
if(Array[i - 1][j - 1] == Station.block) {
blockAround++;
}
}
if(i - 1 >= 1) {
if(Array[i - 1][j] == Station.block) {
blockAround++;
}
}
if(i - 1 >= 1 && j + 1 <= Y) {
if(Array[i - 1][j + 1] == Station.block) {
blockAround++;
}
}
if(j - 1 >= 1) {
if(Array[i][j - 1] == Station.block) {
blockAround++;
}
}
if(j + 1 <= Y) {
if(Array[i][j + 1] == Station.block) {
blockAround++;
}
}
if(i + 1 <= X && j - 1 >= 1) {
if(Array[i + 1][j - 1] == Station.block) {
blockAround++;
}
}
if(i + 1 <= X) {
if(Array[i + 1][j] == Station.block) {
blockAround++;
}
}
if(i + 1 <= X && j + 1 <= Y) {
if(Array[i + 1][j + 1] == Station.block) {
blockAround++;
}
}
switch (blockAround) {
case 0:
Array[i][j] = Station.zero;
break;
case 1:
Array[i][j] = Station.one;
break;
case 2:
Array[i][j] = Station.two;
break;
case 3:
Array[i][j] = Station.three;
break;
case 4:
Array[i][j] = Station.four;
break;
case 5:
Array[i][j] = Station.five;
break;
case 6:
Array[i][j] = Station.six;
break;
case 7:
Array[i][j] = Station.seven;
break;
}
}
}
}
}
private boolean Judge(int X, int Y) {
if(Array[X][Y] == Station.block) {
return false;
}
return true;
}
}
class HBoom:
package HBoom;
import java.util.Random;
public class HBoom {
public static void main(String[] args) {
mainWin HB = mainWin.getInstance();
}
}
class mainJPanel:
package HBoom;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import javax.swing.*;
import HBoom.boomInitialization;
import HBoom.Station;
public class mainJPanel extends JPanel{
private JPanel[][] m_panel;
private JLabel[][] m_label;
private JButton[][] m_button;
private JLabel[][] m_flag;
private JLabel[][] m_correctFlag;
private int X;
private int Y;
private int blockNum;
private boolean play;
private Station[][] Array;
private Station[][] currentArray;
private static boolean result;
public mainJPanel(Station[][] Array, int X, int Y, int N) {
this.X = X;
this.Y = Y;
this.Array = Array;
this.blockNum = N;
this.currentArray = new Station[X + 1][Y + 1];
this.play = true;
for(int i = 1; i <= X; ++i) {
for(int j = 1; j <= Y; ++j) {
this.currentArray[i][j] = Station.unknown;
}
}
this.setLayout(new GridLayout(X, Y, 0, 0));
m_panel = new JPanel[X + 1][Y + 1];
m_label = new JLabel[X + 1][Y + 1];
m_button = new JButton[X + 1][Y + 1];
m_flag = new JLabel[X + 1][Y + 1];
m_correctFlag = new JLabel[X + 1][Y + 1];
for(int i = 1; i <= X; ++i) {
for(int j = 1; j <= Y; ++j) {
m_panel[i][j] = new JPanel();
m_panel[i][j].setLayout(new CardLayout());
m_button[i][j] = ne