package com.what21.chess;
/**
*
* @ClassName: Computer
*
* @Description: TODO(人机对战的算法alphaBeta1()是人机对战是计算出来每个点的权值
* 取最大的的值作为下棋点,getSame()是用来判断输赢的接口)
*
* @author 但求心安
*
* @date 2016年12月8日 下午7:53:00
*
*
*/
public class Computer {
// q代表棋子 O代表空 先设置权值
private static int Q2O = 1;
private static int Q2 = 10;
private static int Q3O = 10;
private static int Q3 = 100;
private static int Q4O = 100;
private static int Q4 = 2000;
private static int Q5 = 50000;
private static int level = 1;
private int a, b;
static public int num[][] = new int[15][15];
int c[][] = new int[2][2];// 记录i,j的起始位置
private int troub1 = 0, troub2 = 0, t1, t2;
/**
*
* @Title: trouble
*
* @Description: TODO// 困难模式:模拟五步下子
*
* @param 设定文件
*
* @return void 返回类型
*
* @throws
*/
public void trouble()// 困难模式:模拟五步下子
{
level = 3;
}
/**
*
* @Title: trouble1
*
* @Description: TODO// 中等模式
*
* @param 设定文件
*
* @return void 返回类型
*
* @throws
*/
public void trouble1()// 中等模式
{
level = 2;
}
/**
*
* @Title: easy
*
* @Description: TODO// 简单模式:模拟三步下子
*
* @param 设定文件
*
* @return void 返回类型
*
* @throws
*/
public void easy()// 简单模式:模拟三步下子
{
level = 1;
}
/**
* @Title: copyChess
* @Description: TODO 复制当前棋盘
* @param @param num1 设定文件
* @return void 返回类型
* @throws
*/
public void copyChess(int num1[][])// 复制当前棋盘
{
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++)
num[i][j] = num1[i][j];
}
/**
* @Title: generator
* @Description: TODO// 剪枝有邻居的定义是:想个两步以内至少有一个不为空的点即可
// 。比如 b[7,7] 有一个子,那么 b[6,7]是他的邻居,b[5,7] 也是,但是 b[4,7] 就不是,因为相隔了三步
* @param @param i
* @param @param j
* @param @return CheckBoard
* @return boolean 返回类型
* @throws
*/
boolean generator(int i, int j)
{
int min_i, min_j, max_i, max_j;
boolean k = false;
min_i = i - 2 >= 0 ? i - 2 : 0;
max_i = i + 2 <= 14 ? i + 2 : 0;
min_j = j - 2 >= 0 ? j - 2 : 14;
max_j = j + 2 <= 14 ? j + 2 : 14;
for (i = min_i; i <= max_i; i++) {
for (j = min_j; j <= max_j; j++)
if (num[i][j] != 0) {
k = true;
break;
}
}
return k;
}
/**
* @ClassName: struct
* @Description: TODO// 启发式搜索的struct
* @author 但求心安
* @date 2016年12月8日 下午7:57:32
*
*/
class struct
{
int i;
int j;
int value = 0;
}
/**
* @Title: alphaBeta1
* @Description: TODO// 模式选择
* @param @param chess
* @param @param alpha
* @param @param beta
* @param @param i
* @param @param j
* @param @return CheckBoard
* @return int 返回类型
* @throws
*/
public int alphaBeta1(int chess, int alpha, int beta, int i, int j)// 模式选择
{
if (level == 3)
return alphaBeta(1, 7, alpha, beta, i, j);
else if (level == 1)
return alphaBeta(1, 3, alpha, beta, i, j);
else
return alphaBeta(1, 5, alpha, beta, i, j);
}
/**
* @Title: alphaBeta
* @Description: TODO
* 启发式搜索就是找最优的点有了打分之后,我们就可以按照 分数高低进行排序了。具体实现的时候,是根据按照 成五,活四,双三,活三,其他
* 的顺序来排序的。 这个难度也比较高,我就按着这个顺序排序,取最优的五个进行下一步循环,大大减少了基数m可以搜索到第六步,
* alphaBeta剪枝;极大极小搜索,人工智能第一步 模拟五步下子
* @param @param chess
* @param @param depth
* @param @param alpha
* @param @param beta
* @param @param i
* @param @param j
* @param @return 设定文件
* @return int 返回类型
* @throws
*/
private int alphaBeta(int chess, int depth, int alpha, int beta, int i,
int j)
{
int best;// 最优值
if (getQuan(i, j, chess % 2 + 1) >= Q5)// 五子连珠
{
// System.out.println((chess%2+1)+" "+(getComputerQuan()-getPeopleQuan()));
int k=depth%2==1?depth*Q5:-depth*Q5;
return getComputerQuan() - getPeopleQuan()+k;// 电脑的权值减去人的权值,为了避免电脑戏弄人,越快赢越好
//return getComputerQuan() - getPeopleQuan();// 电脑的权值减去人的权值
} else if (depth == 0)// depth为0 ,搜索的尽头
{
return getComputerQuan() - getPeopleQuan();
} else {
struct bestson[] = new struct[225];// 寻找最优的五个节点
int cnt = 0;
if (chess == 2)// 电脑下子
{
int now;// 一个记录当前值的数,
for (i = 0; i <= 14; i++)
for (j = 0; j <= 14; j++) {
if (num[i][j] == 0) {
if (alpha >= beta)
return alpha;// alpha剪枝
else if (generator(i, j) == true) { // 相邻剪枝
num[i][j] = 2;
// now=getQuan(i,j,chess);
now = getQuan(i, j, 1) + getQuan(i, j, 2);
num[i][j] = 0;
bestson[cnt] = new struct();// 入队
bestson[cnt].i = i;
bestson[cnt].j = j;
bestson[cnt++].value = now;
}
}
}
struct t = new struct();
for (i = 0; i < cnt; i++)
// 冒泡排序
for (j = i + 1; j < cnt; j++)
if (bestson[i].value < bestson[j].value) {
t = bestson[i];
bestson[i] = bestson[j];
bestson[j] = t;
}
cnt = cnt < 5 ? cnt : 5;
for (i = 0; i < cnt; i++)// 启发式搜索,取前五
{
if (alpha >= beta)
return alpha;// alpha剪枝
num[bestson[i].i][bestson[i].j] = 2;
now = alphaBeta(1, depth - 1, alpha, beta, bestson[i].i,
bestson[i].j);
if (now > alpha)
alpha = now;
num[bestson[i].i][bestson[i].j] = 0;
}
best = alpha;
} else {// 人下子
int now;
cnt = 0;
for (i = 0; i <= 14; i++)
for (j = 0; j <= 14; j++) {
if (num[i][j] == 0) {
if (alpha >= beta)
return beta;// beat剪枝
else if (generator(i, j) == true) {// 相邻剪枝
num[i][j] = 1;
now = getQuan(i, j, 1) + getQuan(i, j, 2);
num[i][j] = 0;
bestson[cnt] = new struct();// 入队
bestson[cnt].i = i;
bestson[cnt].j = j;
bestson[cnt++].value = now;
}
}
}
struct t = new struct();
for (i = 0; i < cnt; i++)
// 冒泡排序
for (j = i + 1; j < cnt; j++)
if (bestson[i].value < bestson[j].value) {
t = bestson[i];
bestson[i] = bestson[j];
bestson[j] = t;
}
cnt = cnt < 5 ? cnt : 5;
for (i = 0; i < cnt; i++)// 启发式搜索,取前五
{
if (alpha >= beta)
return beta;// beat剪枝
num[bestson[i].i][bestson[i].j] = 1;
now = alphaBeta(2, depth - 1, alpha, beta, bestson[i].i,
bestson[i].j);
if (now < beta)
beta = now;
num[bestson[i].i][bestson[i].j] = 0;
// if(getQuan(i,j,1)>=Q5)break;
}
best = beta;
}
}
return best;
}
/**
* @Title: getPeopleQuan
* @Description: TODO// 目前棋盘人的权值
* @param @return 设定文件
* @return int 返回类型
* @throws
*/
private int getPeopleQuan()// 目前棋盘人的权值
{
int sum = 0;
for (int i = 0; i < 14; i++) {
for (int j = 0; j <= 14; j++)
if (num[i][j] == 1)
sum += getQuan(i, j, 1);
}
return sum;
}
/**
* @Title: getComputerQuan
* @Description: TODO// 目前棋盘电脑的权值
* @param @return 设定文件
* @return int 返回类型
* @throws
*/
private int getComputerQuan()
{
int sum = 0;
for (int i = 0; i < 14; i++) {
for (int j = 0; j <= 14; j++)
if (num[i][j] == 2)
sum += getQuan(i, j, 2);
}
return sum;
}
/**
* @Title: getQuan
* @Description: TODO// 每个位置的权值
* @param @param i
* @param @param j
* @param @param chess
* @param @re