java实现扫雷+AI自动扫雷策略及实现

最近打算入门一下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
  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值