Java學習筆記(七):五子棋AI演算法
參考部落格:https://www.cnblogs.com/songdechiu/p/5768999.html
一、五子棋棋型分析
參考:http://game.onegreen.net/wzq/HTML/142336.html
最常見的基本棋型大體有以下幾種:連五,活四,衝四,活三,眠三,活二,眠二。
①連五:顧名思義,五顆同色棋子連在一起,不需要多講。
②活四:有兩個連五點(即有兩個點可以形成五),圖中白點即為連五點。
稍微思考一下就能發現活四出現的時候,如果對方單純過來防守的話,是已經無法阻止自己連五了。
③衝四:有一個連五點
如下面三圖,均為衝四棋型。圖中白點為連五點。
相對比活四來說,衝四的威脅性就小了很多,因為這個時候,對方只要跟著防守在那個唯一的連五點上,衝四就沒法形成連五。
④活三:可以形成活四的三
如下圖,代表兩種最基本的活三棋型。圖中白點為活四點。
活三棋型是我們進攻中最常見的一種,因為活三之後,如果對方不以理會,將可以下一手將活三變成活四,而我們知道活四是已經無法單純防守住了。所以,當我們面對活三的時候,需要非常謹慎對待。在自己沒有更好的進攻手段的情況下,需要對其進行防守,以防止其形成可怕的活四棋型。
其中圖2-7中間跳著一格的活三,也可以叫做跳活三。
⑤眠三:只能夠形成衝四的三
如下各圖,分別代表最基礎的六種眠三形狀。圖中白點代表衝四點。眠三的棋型與活三的棋型相比,危險係數下降不少,因為眠三棋型即使不去防守,下一手它也只能形成衝四,而對於單純的衝四棋型,我們知道,是可以防守住的。
如上所示,眠三的形狀是很豐富的。對於初學者,在下棋過程中,很容易忽略不常見的眠三形狀,例如圖2-13所示的眠三。
有新手學了活三眠三後,會提出疑問,說活三也可以形成衝四啊,那豈不是也可以叫眠三?
會提出這個問題,說明對眠三定義看得不夠仔細:眠三的的定義是,只能夠形成衝四的三。而活三可以形成眠三,但也能夠形成活四。
此外,在五子棋中,活四棋型比衝四棋型具有更大的優勢,所以,我們在既能夠形成活四又能夠形成衝四時,會選擇形成活四。
⑥活二:能夠形成活三的二
如下圖,是三種基本的活二棋型。圖中白點為活三點。
活二棋型看起來似乎很無害,因為他下一手棋才能形成活三,等形成活三,我們再防守也不遲。但其實活二棋型是非常重要的,尤其是在開局階段,我們形成較多的活二棋型的話,當我們將活二變成活三時,才能夠令自己的活三綿綿不絕微風裡,讓對手防不勝防。
⑦眠二:能夠形成眠三的二
圖中四個為最基本的眠二棋型,細心且喜歡思考的同學會根據眠三介紹中的圖2-13找到與下列四個基本眠二棋型都不一樣的眠二。圖中白點為眠三點。
二、五子棋打分機制
打分思路:
- 每次一個棋子,找出棋盤上全部棋子的旁邊位置,下圖打勾位置
- 把打勾的位置用一個point類的陣列target[]儲存起來
- 對target[]中的每個棋子評分
- 取target[]中的棋子各個方向的4個棋子,以橫向為例(取三角形位置):
- 根據以上得出八個方向的棋子分佈,做出評分(屬於哪一類)
評分規定:
綜合四個方向後:
棋型 | 分數 |
---|---|
成五(five) | +100000分 |
活四/雙眠四/眠四活(alive_4/highdie_4>1/highdie_4&alive_3) | +10000分 |
雙活三(alive_3>1) | +5000分 |
眠三活三(die_3&alive_3) | +1000分 |
眠四(highdie_4) | +500分 |
低階眠四(die_4) | +400分 |
單活三(alive_3) | +100分 |
跳活三(tiaoalive_3) | +90分 |
雙活二(alive_2>1) | +50分 |
活二(alive_2) | +10分 |
低階活二(lowalive_2) | +9分 |
眠三(die_3) | +5分 |
眠二(die_2) | +2分 |
初始值(無威脅的其他情況) | +1分 |
三、附錄程式碼
在上一篇雙人五子棋的基礎上新增一個AI判斷機制,棋盤和判斷方法(Check)、重繪函式等都不變 https://blog.csdn.net/qq_36804363/article/details/86733292
分八個方向判斷
可歸為橫縱左斜右斜四個方向,以黑棋子為例(評定黑棋子分數)
- 先用八個函式分別得出八個方向上除了黑色外的棋盤座標,此時得出的是最靠黑棋子的座標
- 得出座標後,再擴充,相當於以上的八個方向擴充到4個,以橫向為例,如下圖所示
- 再對應各種不同的棋型判斷棋子的位置是否符合條件
AIJudge:
package com.GobandAI;
import java.awt.Point;
import com.GobandAI.Checkerboard.Config;
/**
* 判斷是否能成5, 如果是機器方的話給予100000分,如果是人方的話給予100000 分;
* 判斷是否能成活4或者是雙死4或者是死4活3,如果是機器方的話給予10000分,如果是人方的話給予10000分;
* 判斷是否已成雙活3,如果是機器方的話給予5000分,如果是人方的話給予5000 分;
* 判斷是否成死3活3(高階),如果是機器方的話給予1000分,如果是人方的話給予1000 分;
* 判斷是否能成死4,如果是機器方的話給予500分,如果是人方的話給予500分;
* 判斷是否能成低階死4,如果是機器方的話給予400分,如果是人方的話給予400分;
* 判斷是否能成單活3,如果是機器方的話給予100分,如果是人方的話給予100分; 判斷是否能成跳活3,如果是機器方的話給予90分,如果是人方的話給予90分;
* 判斷是否能成雙活2,如果是機器方的話給予50分,如果是人方的話給予50分; 判斷是否能成活2,如果是機器方的話給予10分,如果是人方的話給予10分;
* 判斷是否能成低階活2,如果是機器方的話給予9分,如果是人方的話給予9分; 判斷是否能成死3,如果是機器方的話給予5分,如果是人方的話給予5分;
* 判斷是否能成死2,如果是機器方的話給予2分,如果是人方的話給予2分。
* 判斷是否其他情況(nothing),如果是機器方的話給予1分,如果是人方的話給予1分。 有棋子,則直接0分
*
* @author mo
*
*/
public class AIjudge {
private int five, alive_4, highdie_4, die_4, alive_3, die_3, alive_2, die_2, lowalive_2, tiaoalive_3;
public void Init() {
five = 0;
alive_4 = 0;
highdie_4 = 0;
die_4 = 0;
alive_3 = 0;
die_3 = 0;
alive_2 = 0;
die_2 = 0;
lowalive_2 = 0;
tiaoalive_3 = 0;
}
public Point getright(int[][] chesses, int x, int y) {// 右
Point count = new Point();
for (int i = x + 1; i < Config.columns; i++) {
if (chesses[i][y] != chesses[x][y]) {
count = new Point(i, y);
// System.out.println("右:"+count);
return count;
}
}
return count;
}
public Point getleft(int[][] chesses, int x, int y) {// 左
Point count = new Point();
for (int i = x - 1; i >= 0; i--) {
if (chesses[i][y] != chesses[x][y]) {
count = new Point(i, y);
return count;
}
}
return count;
}
public Point getup(int[][] chesses, int x, int y) {// 上
Point count = new Point();
for (int i = y; i >= 0; i--) {
if (chesses[x][i] != chesses[x][y]) {
count = new Point(x, i);
return count;
}
}
return count;
}
public Point getdown(int[][] chesses, int x, int y) {// 下
Point count = new Point();
for (int i = y + 1; i < Config.rows; i++) {
if (chesses[x][i] != chesses[x][y]) {
count = new Point(x, i);
return count;
}
}
return count;
}
public Point getSlashru(int[][] chesses, int x, int y) {// 右上
Point count = new Point();
for (int i = y - 1, j = x + 1; j < Config.rows && i >= 0; j++, i--) {
if (chesses[j][i] != chesses[x][y]) {
count = new Point(j, i);
return count;
}
}
return count;
}
public Point getSlashrd(int[][] chesses, int x, int y) {// 右下
Point count = new Point();
for (int i = y + 1, j = x + 1; j < Config.rows && i < Config.columns; j++, i++) {
if (chesses[j][i] != chesses[x][y]) {
count = new Point(j, i);
return count;
}
}
return count;
}
public Point getSlashlu(int[][] chesses, int x, int y) {// 左上
Point count = new Point();
for (int i = y, j = x; j >= 0 && i >= 0; j--, i--) {
if (chesses[j][i] != chesses[x][y]) {
count = new Point(j, i);
return count;
}
}
return count;
}
public Point getSlashld(int[][] chesses, int x, int y) {// 左下
Point count = new Point();
for (int i = y + 1, j = x - 1; j >= 0 && i < Config.columns; j--, i++) {
if (chesses[j][i] != chesses[x][y]) {
count = new Point(j, i);
return count;
}
}
return count;
}
public int judge(int[][] chesses, int x, int y, int data) {
this.Init();
chesses[x][y] = data;// 給個假設值!
Point index_r = getright(chesses, x, y);// 右
Point index_l = getleft(chesses, x, y);// 左
Point index_u = getup(chesses, x, y);// 上
Point index_d = getdown(chesses, x, y);// 下
Point index_ru = getSlashru(chesses, x, y);// 右上
Point index_rd = getSlashrd(chesses, x, y);// 右下
Point index_lu = getSlashlu(chesses, x, y);// 左上
Point index_ld = getSlashld(chesses, x, y);// 左下
int left = chesses[index_l.x][index_l.y];// 左
int left1 = 9, right1 = 9, left2 = 9, right2 = 9, left3 = 9, right3 = 9;
if (index_l.x > 0)
left1 = chesses[index_l.x - 1][index_l.y];
int right = chesses[index_r.x][index_r.y];// 右
if (index_r.x < Config.columns - 2)
right1 = chesses[index_r.x + 1][index_r.y];
if (index_l.x - 1 > 0)
left2 = chesses[index_l.x - 2][index_l.y];
if (index_r.x < Config.columns - 3)
right2 = chesses[index_r.x + 2][index_r.y];
if (index_l.x - 2 > 0)
left3 = chesses[index_l.x - 3][index_l.y];
if (index_r.x < Config.columns - 4)
right3 = chesses[index_r.x + 3][index_r.y];
// 縱向
int up = chesses[index_u.x][index_u.y];// 上
int up1 = 9, down1 = 9, up2 = 9, down2 = 9, up3 = 9, down3 = 9;
if (index_u.x > 0)
up1 = chesses[index_u.x - 1][index_u.y];
int down = chesses[index_d.x][index_d.y];// 1下
if (index_d.x < Config.rows - 2)
down1 = chesses[index_d.x + 1][index_d.y];
if (index_u.x - 1 > 0)
up2 = chesses[index_u.x - 2][index_u.y];
if (index_d.x < Config.rows - 3)
down2 = chesses[index_d.x + 2][index_d.y];
if (index_u.x - 2 > 0)
up3 = chesses[index_u.x - 3][index_u.y];
if (index_d.x < Config.rows - 4)
down3 = chesses[index_d.x + 3][index_d.y];
// 左斜線
int ld = chesses[index_ld.x][index_ld.y];// 左下
int ld1 = 9, ru1 = 9, ld2 = 9, ru2 = 9, ld3 = 9, ru3 = 9;
if (index_ld.x > 0 && index_ld.y < Config.rows - 2)// 1左下
ld1 = chesses[index_ld.x - 1][index_ld.y + 1];
int ru = chesses[index_ru.x][index_ru.y];// 右上
if (index_ru.x < Config.columns - 2 && index_ru.y > 0)// 右上
ru1 = chesses[index_ru.x + 1][index_ru.y - 1];
if (index_ld.x - 1 > 0 && index_ld.y < Config.rows - 3)// 2左下
ld2 = chesses[index_ld.x - 2][index_ld.y + 2];
if (index_ru.x < Config.columns - 3 && index_ru.y > 1)// 右上
ru2 = chesses[index_ru.x + 2][index_ru.y - 2];
if (index_ld.x - 2 > 0 && index_ld.y < Config.rows - 4)// 3左下
ld2 = chesses[index_ld.x - 3][index_ld.y + 3];
if (index_ru.x < Config.columns - 4 && index_ru.y > 2)// 右上
ru2 = chesses[index_ru.x + 3][index_ru.y - 3];
// 右斜線
int lu = chesses[index_lu.x][index_lu.y];// 右上
int lu1 = 9, rd1 = 9, lu2 = 9, rd2 = 9, lu3 = 9, rd3 = 9;
if (index_lu.x > 0 && index_lu.y > 0)// 1左上
lu1 = chesses[index_lu.x - 1][index_lu.y - 1];
int rd = chesses[index_rd.x][index_rd.y];// 左下
if (index_rd.x < Config.columns - 2 && index_rd.y < Config.rows - 2)// 右下
rd1 = chesses[index_rd.x + 1][index_rd.y + 1];
if (index_lu.x - 1 > 0 && index_lu.y > 1)// 2左上
lu2 = chesses[index_lu.x - 2][index_lu.y - 2];
if (index_rd.x < Config.columns - 3 && index_rd.y < Config.rows - 3)// 右下
rd2 = chesses[index_rd.x + 2][index_rd.y + 2];
if (index_lu.x - 2 > 0 && index_lu.y > 2)// 3左上
lu2 = chesses[index_lu.x - 3][index_lu.y - 3];
if (index_rd.x < Config.columns - 4 && index_rd.y < Config.rows - 4)// 右下
rd2 = chesses[index_rd.x + 3][index_rd.y + 3];
/**
* 五連珠
*/
if (Check.checkfive(chesses, x, y))// 成5
{
five++;
}
/**
* 四連珠
*/
if (Check.checkRow(chesses, x, y) == 4) {// 橫向四連珠
System.out.println("四連珠 <" + x + ", " + y + ">");
if (left == 0 && right == 0)// 活四
{
alive_4++;
} else if ((left == 0 && right == -data) || (left == -data && right == 0)) {
highdie_4++;
} // 死4
}
if (Check.checkColumn(chesses, x, y) == 4) {// 縱向四連珠
if (up == 0 && down == 0)// 活四
{
alive_4++;
} else if ((up == 0 && down == -data) || (up == -data && down == 0)) {
highdie_4++;
} // 眠4
}
if (Check.checkIncleft(chesses, x, y) == 4) {// 左斜線:左下右上
if (ld == 0 && ru == 0)// 活四
{
alive_4++;
} else if ((ld == 0 && ru == -data) || (ld == -data && ru == 0)) {
highdie_4++;
} // 眠4
}
if (Check.checkIncright(chesses, x, y) == 4) {// 右斜線:左上右下
if (lu == 0 && rd == 0)// 活四
{
alive_4++;
} else if ((lu == 0 && rd == -data) || (lu == -data && rd == 0)) {
highdie_4++;
} // 眠4
}
/**
* 三連珠
*/
if (Check.checkRow(chesses, x, y) == 3) {// 橫向三連珠
if (left == 0 && right == 0) {// 斷開處空
if (left1 == 0 || right1 == 0)// 活三
{
alive_3++;
}
if (left1 == data || right == data)// 死4
{
die_4++;
}
if (left1 == -data || right1 == -data)// 眠三
{
die_3++;
}
} else if (left == -data && right == 0) {// 左邊被攔
if (right1 == data)// 右邊隔一個有棋子,眠四
{
die_4++;
} else if (right1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
} else if (right == -data && left == 0) {// 右邊被攔
if (left1 == data)// 左邊隔一個棋子,眠四
{
die_4++;
} else if (left1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
}
}
if (Check.checkColumn(chesses, x, y) == 3) {// 縱向三連珠
if (up == 0 && down == 0) {// 斷開處空
if (up1 == 0 || down1 == 0)// 活三
{
alive_3++;
}
if (up1 == data || down == data)// 死4
{
die_4++;
}
if (up1 == -data || down1 == -data)// 眠三
{
die_3++;
}
} else if (up == -data && down == 0) {// 左邊被攔
if (down1 == data)// 右邊隔一個有棋子,眠四
{
die_4++;
} else if (down1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
} else if (down == -data && up == 0) {// 右邊被攔
if (up1 == data)// 左邊隔一個棋子,眠四
{
die_4++;
} else if (up1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
}
}
if (Check.checkIncleft(chesses, x, y) == 3) {// 左斜線三連珠 :左下+右上
if (ld == 0 && ru == 0) {// 斷開處空
if (ld1 == 0 || ru1 == 0)// 活三
{
alive_3++;
}
if (ld1 == data || ru == data)// 死4
{
die_4++;
}
if (ld1 == -data || ru1 == -data)// 眠三
{
die_3++;
}
} else if (ld == -data && ru == 0) {// 左邊被攔
if (ru1 == data)// 右邊隔一個有棋子,眠四
{
die_4++;
} else if (ru1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
} else if (ru == -data && ld == 0) {// 右邊被攔
if (ld1 == data)// 左邊隔一個棋子,眠四
{
die_4++;
} else if (ld1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
}
}
if (Check.checkIncright(chesses, x, y) == 3) {// 右斜三連珠:右下+左上
if (lu == 0 && rd == 0) {// 斷開處空
if (lu1 == 0 || rd1 == 0)// 活三
{
System.out.println(data + "<" + x + "," + y + ">右斜線活3 右斜線檢查" + Check.checkIncright(chesses, x, y)
+ "左斜線檢查:" + Check.checkIncleft(chesses, x, y));
System.out.println("<" + x + "," + y + ">" + "" + lu3 + "" + "live2:" + lu2 + " live3:" + lu1
+ " die3:" + lu + " low2:" + rd);
alive_3++;
}
if (lu1 == data || rd == data)// 死4
{
die_4++;
}
if (lu1 == -data || rd1 == -data)// 眠三
{
die_3++;
}
}
if (lu == -data && rd == 0) {// 左邊被攔
if (rd1 == data)// 右邊隔一個有棋子,眠四
{
die_4++;
} else if (rd1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
}
if (rd == -data && lu == 0) {// 右邊被攔
if (lu1 == data)// 左邊隔一個棋子,眠四
{
die_4++;
} else if (lu1 == 0)// 沒有放棋子為眠3
{
die_3++;
}
}
}
/**
* 二連珠
*/
if (Check.checkRow(chesses, x, y) == 2) {// 橫向二連珠
if (right == 0 && left == 0) {// 如果兩邊斷開位置都為空
// System.out.println("二連珠"+left2+" "+left1+" "+left+" "+right+"
// "+right1+" "+right2);
if ((right1 == 0 && right2 == data) || (left1 == 0 && left2 == data))// 第三棋子有一個為本色,眠3
{
die_3++;
} else if (right1 == 0 && left1 == 0)// 斷開第二個位置都為空,活2
{
// System.out.println("活二!");
alive_2++;
}
if ((right1 == data && right2 == 0) || (left1 == data && left2 == 0))
// 某一邊斷開第二個位置為本色,第三位置為空,跳活三
{
tiaoalive_3++;
}
if ((right1 == data && right2 == -data) || (left1 == data && left2 == -data))
// 某一邊斷開第二位置為本色,得三位置為他色,眠三
{
die_3++;
}
if ((right1 == data && right2 == data) || (left1 == data && left2 == data))
// 某一邊的12都為本色,眠四
{
die_4++;
}
} else if (right == 0 && left == -data) {// 右邊為空左邊被攔
if (right1 == data && right2 == data)// 右邊12都為本色,眠四
{
die_4++;
} else if (right1 == data || right2 == data)// 右2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (right1 == 0 && right2 == 0)// 右123都為空,眠2
{
die_2++;
}
} else if (left == 0 && right == -data) {// 左邊為空右邊被攔
if (left1 == data && left2 == data)// 左邊12都為本色,眠四
{
die_4++;
} else if (left1 == data || left2 == data)// 左2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (left1 == 0 && left2 == 0)// 左123為空,眠2
{
die_2++;
}
}
}
if (Check.checkColumn(chesses, x, y) == 2) {// 縱向二連珠
if (up == 0 && down == 0) {// 如果兩邊斷開位置都為空
if ((up1 == 0 && up2 == data) || (down1 == 0 && down2 == data))// 第三棋子有一個為本色,眠3
{
die_3++;
} else if (up1 == 0 && down1 == 0)// 斷開第二個位置都為空,活2
{
alive_2++;
}
if ((up1 == data && up2 == 0) || (down1 == data && down2 == 0))
// 某一邊斷開第二個位置為本色,第三位置為空,跳活三
{
tiaoalive_3++;
}
if ((up1 == data && up2 == -data) || (down1 == data && down2 == -data))
// 某一邊斷開第二位置為本色,得三位置為他色,眠三
{
die_3++;
}
if ((up1 == data && up2 == data) || (down1 == data && down2 == data))
// 某一邊的12都為本色,眠四
{
die_4++;
}
} else if (up == 0 && down == -data) {// 上邊為空下邊被攔
if (up1 == data && up2 == data)// 上邊12都為本色,眠四
{
die_4++;
} else if (up1 == data || up2 == data)// 上2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (up1 == 0 && up2 == 0)// 上123都為空,眠2
{
die_2++;
}
} else if (down == 0 && up == -data) {// 下邊為空上邊被攔
if (down1 == data && down2 == data)// 下邊12都為本色,眠四
{
die_4++;
} else if (down1 == data || down2 == data)// 下2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (down1 == 0 && down2 == 0)// 下123為空,眠2
{
die_2++;
}
}
}
if (Check.checkIncleft(chesses, x, y) == 2) {// 左斜線:左下ld+右上ru
if (ld == 0 && ru == 0) {// 如果兩邊斷開位置都為空
if ((ld1 == 0 && ld2 == data) || (ru1 == 0 && ru2 == data))// 第三棋子有一個為本色,眠3
{
die_3++;
} else if (ld1 == 0 && ru1 == 0)// 斷開第二個位置都為空,活2
{
alive_2++;
}
if ((ld1 == data && ld2 == 0) || (ru1 == data && ru2 == 0))
// 某一邊斷開第二個位置為本色,第三位置為空,跳活三
{
tiaoalive_3++;
}
if ((ld1 == data && ld2 == -data) || (ru1 == data && ru2 == -data))
// 某一邊斷開第二位置為本色,得三位置為他色,眠三
{
die_3++;
}
if ((ld1 == data && ld2 == data) || (ru1 == data && ru2 == data))
// 某一邊的12都為本色,眠四
{
die_4++;
}
} else if (ld == 0 && ru == -data) {// 左邊為空右邊被攔
if (ld1 == data && ld2 == data)// 左邊12都為本色,眠四
{
die_4++;
} else if (ld1 == data || ld2 == data)// 左2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (ld1 == 0 && ld2 == 0)// 左123都為空,眠2
{
die_2++;
}
} else if (ru == 0 && ld == -data) {// 右邊為空右邊被攔
if (ru1 == data && ru2 == data)// 右邊12都為本色,眠四
{
die_4++;
} else if (ru1 == data || ru2 == data)// 右2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (ru1 == 0 && ru2 == 0)// 右123為空,眠2
{
die_2++;
}
}
}
if (Check.checkIncright(chesses, x, y) == 2) {// 右斜線:左上lu+右下rd
if (lu == 0 && rd == 0) {// 如果兩邊斷開位置都為空
if ((lu1 == 0 && lu2 == data) || (rd1 == 0 && rd2 == data))// 第三棋子有一個為本色,眠3
{
die_3++;
} else if (lu1 == 0 && rd1 == 0)// 斷開第二個位置都為空,活2
{
// System.out.println("<"+x+","+y+"> 檢測到右斜線活二");
alive_2++;
}
if ((lu1 == data && lu2 == 0) || (rd1 == data && rd2 == 0))
// 某一邊斷開第二個位置為本色,第三位置為空,跳活三
{
tiaoalive_3++;
}
if ((lu1 == data && lu2 == -data) || (rd1 == data && rd2 == -data))
// 某一邊斷開第二位置為本色,得三位置為他色,眠三
{
die_3++;
}
if ((lu1 == data && lu2 == data) || (rd1 == data && rd2 == data))
// 某一邊的12都為本色,眠四
{
die_4++;
}
} else if (lu == 0 && rd == -data) {// 左邊為空右邊被攔
if (lu1 == data && lu2 == data)// 左邊12都為本色,眠四
{
die_4++;
} else if (lu1 == data || lu2 == data)// 左2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (lu1 == 0 && lu2 == 0)// 左123都為空,眠2
{
die_2++;
}
} else if (rd == 0 && lu == -data) {// 右邊為空左邊被攔
if (rd1 == data && rd2 == data)// 右邊12都為本色,眠四
{
die_4++;
} else if (rd1 == data || rd2 == data)// 右2只要有一個為自己的棋子,眠三
{
die_3++;
} else if (rd1 == 0 && rd2 == 0)// 右123為空,眠2
{
die_2++;
}
}
}
/**
* 1連珠
*/
if (Check.checkRow(chesses, x, y) == 1) {// 橫向1連
// 眠四情況01000
if ((right == 0 && right1 == data && right2 == data && right3 == data)
|| (left == 0 && left1 == data && left2 == data && left3 == data)) {
die_4++;
}
// 跳三101001
if ((right == 0 && left == 0 && left1 == data && left2 == data && left3 == 0)
|| (left == 0 && right == 0 && right1 == data && right2 == data && right3 == 0)) {
tiaoalive_3++;
}
// 眠三
if ((right == 0 && left == 0 && left1 == data && left2 == data && left3 == -data)
|| (right == 0 && left == 0 && right1 == data && right2 == data && right3 == -data))// 101002
{
die_3++;
} else if ((right == -data && left == 0 && left1 == data && left2 == data && left3 == 0)
|| (right == 0 && left == -data && right1 == data && right2 == data && right3 == 0))// 100102
{
die_3++;
} else if ((right == 0 && right1 == 0 && right2 == data && right3 == data)
|| (left == 0 && left1 == 0 && left2 == data && left3 == data))// 01100
{
die_3++;
} else if ((right == 0 && right1 == data && right2 == 0 && right3 == data)
|| (left == 0 && left1 == data && left2 == 0 && left3 == data))
// 活二
if ((left == 0 && right == 0 && left1 == data && left2 == 0 && left3 == 0)
|| (right == 0 && left == 0 && right1 == data && right2 == 0 && right3 == 0))
// 101011
{
lowalive_2++;
} else if ((left == 0 && right == 0 && right1 == 0 && right2 == data && right3 == 0) || (right == 0 && left == 0 && left1 == 0 && left2 == data && left3 == 0))
// 101101
{
lowalive_2++;
}
// 眠二
// 低眠2不考慮
}
if (Check.checkColumn(chesses, x, y) == 1) {// 縱向1連
// 眠四情況01000
if ((up == 0 && up1 == data && up2 == data && up3 == data)
|| (down == 0 && down1 == data && down2 == data && down3 == data)) {
die_4++;
}
// 跳三101001
if ((up == 0 && down == 0 && down1 == data && down2 == data && down3 == 0)
|| (down == 0 && up == 0 && up1 == data && up2 == data && up3 == 0)) {
tiaoalive_3++;
}
// 眠三
if ((up == 0 && down == 0 && down1 == data && down2 == data && down3 == -data)
|| (up == 0 && down == 0 && up1 == data && up2 == data && up3 == -data))// 101002
{
die_3++;
} else if ((up == -data && down == 0 && down1 == data && down2 == data && down3 == 0)
|| (up == 0 && down == -data && up1 == data && up2 == data && up3 == 0))// 100102
{
die_3++;
} else if ((up == 0 && up1 == 0 && up2 == data && up3 == data)
|| (down == 0 && down1 == 0 && down2 == data && down3 == data))// 01100
{
die_3++;
} else if ((up == 0 && up1 == data && up2 == 0 && up3 == data)
|| (down == 0 && down1 == data && down2 == 0 && down3 == data)) {
die_3++;
}
// 活二
if ((down == 0 && up == 0 && down1 == data && down2 == 0 && down3 == 0)
|| (up == 0 && down == 0 && up1 == data && up2 == 0 && up3 == 0))
// 101011
{
lowalive_2++;
} else if ((down == 0 && up == 0 && up1 == 0 && up2 == data && up3 == 0)
|| (up == 0 && down == 0 && down1 == 0 && down2 == data && down3 == 0))
// 101101
{
lowalive_2++;
}
// 眠二
// 低眠2不考慮
}
if (Check.checkIncleft(chesses, x, y) == 1) {// 左斜線:左下+右上
// 眠四情況01000
if ((ru == 0 && ru1 == data && ru2 == data && ru3 == data)
|| (ld == 0 && ld1 == data && ld2 == data && ld3 == data)) {
die_4++;
}
// 跳三101001
if ((ru == 0 && ld == 0 && ld1 == data && ld2 == data && ld3 == 0)
|| (ld == 0 && ru == 0 && ru1 == data && ru2 == data && ru3 == 0)) {
tiaoalive_3++;
}
// 眠三
if ((ru == 0 && ld == 0 && ld1 == data && ld2 == data && ld3 == -data)
|| (ru == 0 && ld == 0 && ru1 == data && ru2 == data && ru3 == -data))// 101002
{
die_3++;
} else if ((ru == -data && ld == 0 && ld1 == data && ld2 == data && ld3 == 0)
|| (ru == 0 && ld == -data && ru1 == data && ru2 == data && ru3 == 0))// 100102
{
die_3++;
} else if ((ru == 0 && ru1 == 0 && ru2 == data && ru3 == data)
|| (ld == 0 && ld1 == 0 && ld2 == data && ld3 == data))// 01100
{
die_3++;
} else if ((ru == 0 && ru1 == data && ru2 == 0 && ru3 == data)
|| (ld == 0 && ld1 == data && ld2 == 0 && ld3 == data)) {
die_3++;
}
// 活二
if ((ld == 0 && ru == 0 && ld1 == data && ld2 == 0 && ld3 == 0)
|| (ru == 0 && ld == 0 && ru1 == data && ru2 == 0 && ru3 == 0))
// 101011
{
lowalive_2++;
} else if ((ld == 0 && ru == 0 && ru1 == 0 && ru2 == data && ru3 == 0)
|| (ru == 0 && ld == 0 && ld1 == 0 && ld2 == data && ld3 == 0))
// 101101
{
lowalive_2++;
}
// 眠二
}
if (Check.checkIncright(chesses, x, y) == 1) {// 右斜線:右下rd+左上lu
// 眠四情況01000
if ((rd == 0 && rd1 == data && rd2 == data && rd3 == data)
|| (lu == 0 && lu1 == data && lu2 == data && lu3 == data)) {
die_4++;
}
// 跳三101001
if ((rd == 0 && lu == 0 && lu1 == data && lu2 == data && lu3 == 0)
|| (lu == 0 && rd == 0 && rd1 == data && rd2 == data && rd3 == 0)) {
tiaoalive_3++;
}
// 眠三
if ((rd == 0 && lu == 0 && lu1 == data && lu2 == data && lu3 == -data)
|| (rd == 0 && lu == 0 && rd1 == data && rd2 == data && rd3 == -data))// 101002
{
die_3++;
} else if ((rd == -data && lu == 0 && lu1 == data && lu2 == data && lu3 == 0)
|| (rd == 0 && lu == -data && rd1 == data && rd2 == data && rd3 == 0))// 100102
{
die_3++;
} else if ((rd == 0 && rd1 == 0 && rd2 == data && rd3 == data)
|| (lu == 0 && lu1 == 0 && lu2 == data && lu3 == data))// 01100
{
die_3++;
} else if ((rd == 0 && rd1 == data && rd2 == 0 && rd3 == data)
|| (lu == 0 && lu1 == data && lu2 == 0 && lu3 == data)) {
die_3++;
}
// 活二
if ((lu == 0 && rd == 0 && lu1 == data && lu2 == 0 && lu3 == 0)
|| (rd == 0 && lu == 0 && rd1 == data && rd2 == 0 && rd3 == 0))
// 101011
{
lowalive_2++;
} else if ((lu == 0 && rd == 0 && rd1 == 0 && rd2 == data && rd3 == 0)
|| (rd == 0 && lu == 0 && lu1 == 0 && lu2 == data && lu3 == 0))
// 101101
{
lowalive_2++;
}
// 眠二
}
chesses[x][y] = 0;// 檢查假設值之後返回
return this.getLevel();
}
public int getLevel() {
int count = 1;
if (five > 0)
count += 100000;// 贏
if (alive_4 > 0 || highdie_4 > 1 || (highdie_4 > 0 && alive_3 > 0))// 活4,雙死4,死4活3
count += 10000;
if (alive_3 > 1)// 雙活3
count += 5000;
if (die_3 > 0 && alive_3 > 0)// 死3活3
count += 1000;
if (highdie_4 > 0)// 死4
count += 500;
if (die_4 > 0)// 低階死4
count += 400;
if (alive_3 > 0)// 單活3
count += 100;
if (tiaoalive_3 > 0)// 跳活3
count += 90;
if (alive_2 > 1)// 雙活2
count += 50;
if (alive_2 > 0)// 活2
count += 10;
if (lowalive_2 > 0)// 低活2
count += 9;
if (die_3 > 0)// 死3
count += 5;
if (die_2 > 0)// 死2
count += 2;
// if()
return count;
}
}
在監聽器中新增人機對戰的模式:
- 人機模式要先找到target陣列
- 在target陣列中分別對黑白棋評分
- 機器人為白棋,取黑白棋中分數最高的點落子
package com.GobandAI;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import com.GobandAI.Checkerboard.Config;
import com.GobandAI.Repaint;
/**
* 五子棋監聽器
*
* @author mo
*
*/
public class DrawListener implements MouseListener, ActionListener {
private int count = 0, flag_start = 0, flag_winner = 0, flag_play = -1;
private Graphics g;
private Repaint[] rep;
private int de = 0;
private int[][] chesses;// 1黑 -1白
private int[][] back = new int[256][2];
private Checkerboard board;
private String name;
private JFrame finshjf = new JFrame();
private JTextArea txt = new JTextArea();
public void setGraphics(Graphics g) {
this.g = g;
}
/**
* 為了實現棋盤的重繪
*/
public void setCheckerboard(Checkerboard c) {
this.board = c;
txt = board.getEast();
}
public void setChesses(int[][] c) {
this.chesses = c;
}
/**
* 重繪陣列
*
* @param rep
*/
public void setrepaint(Repaint[] rep) {
this.rep = rep;
}
public void actionPerformed(ActionEvent e) {
name = e.getActionCommand();
if (name.equals("開始遊戲") || name.equals("重新開始")) {
board.clearChesses();
flag_start = 1;
flag_winner = 0;
count = 0;
finshjf.setVisible(false);
txt.append("遊戲開始" + "\n");
}
if (name.equals("返回棋局")) {
finshjf.setVisible(false);
txt.append("返回棋局" + "\n");
}
if (name.equals("悔棋")) {
if (count < 2)
txt.append("不能悔棋!" + "\n");
else txt.append("悔棋成功" + "\n");
this.rep[count - 1] = null;
this.rep[count - 2] = null;
chesses[back[count - 1][0]][back[count - 1][0]] = 0;
chesses[back[count - 1][0]][back[count - 1][1]] = 0;
chesses[back[count - 2][0]][back[count - 2][0]] = 0;
chesses[back[count - 2][0]][back[count - 2][1]] = 0;
count -= 2;
board.paint(board.getGraphics());
}
if (name.equals("玩家對戰")) {
flag_play = 0;
txt.append("選擇模式為:玩家對戰\n");
}
if (name.equals("人機對戰")) {
flag_play = 1;
txt.append("選擇模式為:人機對戰\n");
}
}
/**
* 滑鼠點選事件 放下棋子
*/
public void mouseClicked(MouseEvent e) {
int x0 = e.getX();
int y0 = e.getY();
/**
* 判斷按下是否有效
*/
if (flag_play == -1)
txt.append("請選擇對戰模式:人機/玩家\n");
if (flag_start == 0)
txt.append("請點選開始遊戲" + "\n");
if (flag_play == 0)
this.Player_against(x0, y0);
if (flag_play == 1)
this.Computer_against(x0, y0);
};
/**
* 玩家對抗
*
* @param x0
* 按下的座標
* @param y0
* 按下的座標
*/
public void Player_against(int x0, int y0) {
Image img_b = new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/黑棋.png").getImage();
Image img_w = new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/白棋.png").getImage();
if ((flag_start == 1)
&& ((x0 - Config.start) % Config.SIZE < Config.SIZE / 3
|| ((x0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)
&& ((y0 - Config.start) % Config.SIZE < Config.SIZE / 3)
|| (y0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)
&& (x0 > Config.SIZE * 2 / 3) && (y0 > Config.SIZE * 2 / 3)
&& (x0 < (Config.start + (Config.columns - 1) * Config.SIZE) - 5
&& y0 < (Config.start + (Config.rows - 1) * Config.SIZE) - 5)) {
/**
* x,y儲存的是畫筆需要繪製的介面座標
*/
int x = Config.start + Config.SIZE * ((x0 - Config.start) / Config.SIZE);
int y = Config.start + Config.SIZE * ((y0 - Config.start) / Config.SIZE);
if (((x0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)) {
x = Config.start + Config.SIZE * (1 + (x0 - Config.start) / Config.SIZE);
}
if (((y0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)) {
y = Config.start + Config.SIZE * (1 + (y0 - Config.start) / Config.SIZE);
}
/*
* x,y需減去start再除棋盤大小 對應棋盤陣列的索引
*/
int index_x = (x - Config.start) / Config.SIZE;
int index_y = (y - Config.start) / Config.SIZE;
if (chesses[index_x][index_y] == 0) {
System.out.println(index_x + " " + index_y);
if (count % 2 == 0) {
txt.append("當前為白棋" + "\n");
g.drawImage(img_b, x - Config.CHESS_SIZE / 2, y - Config.CHESS_SIZE / 2, null);
chesses[index_x][index_y] = 1;
back[count][0] = index_x;
back[count][1] = index_y;
if (Check.checkfive(chesses, index_x, index_y)) {
System.out.println("黑勝");
txt.append("遊戲結束" + "\n");
txt.append("黑棋勝利" + "\n");
flag_winner = 1;
}
} else {
txt.append("當前為黑棋" + "\n");
g.drawImage(img_w, x - Config.CHESS_SIZE / 2, y - Config.CHESS_SIZE / 2, null);
chesses[index_x][index_y] = -1;
back[count][0] = index_x;
back[count][1] = index_y;
if (Check.checkfive(chesses, index_x, index_y)) {
System.out.println("白勝");
txt.append("遊戲結束" + "\n");
txt.append("白棋勝利" + "\n");
flag_winner = -1;
}
}
Repaint r = new Repaint(x - Config.CHESS_SIZE / 2, y - Config.CHESS_SIZE / 2,
count % 2 == 0 ? img_b : img_w);
rep[de++] = r;
count++;
}
System.out.println("name:" + name);
if (flag_winner != 0) {
finshjf = this.finshShow();
finshjf.setVisible(true);
}
}
}
/**
* 人機對抗
*
* @param x0
* @param y0
*/
public void Computer_against(int x0, int y0) {
Image img_b = new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/黑棋.png").getImage();
Image img_w = new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/白棋.png").getImage();
if ((flag_start == 1)
&& ((x0 - Config.start) % Config.SIZE < Config.SIZE / 3
|| ((x0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)
&& ((y0 - Config.start) % Config.SIZE < Config.SIZE / 3)
|| (y0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)
&& (x0 > Config.SIZE * 2 / 3) && (y0 > Config.SIZE * 2 / 3)
&& (x0 < (Config.start + (Config.columns - 1) * Config.SIZE - 5)
&& y0 < (Config.start + (Config.rows - 1) * Config.SIZE) - 5)) {
// System.out.println(x0+" "+y0);
/**
* x,y儲存的是畫筆需要繪製的介面座標
*/
int x = Config.start + Config.SIZE * ((x0 - Config.start) / Config.SIZE);
int y = Config.start + Config.SIZE * ((y0 - Config.start) / Config.SIZE);
if (((x0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)) {
x = Config.start + Config.SIZE * (1 + (x0 - Config.start) / Config.SIZE);
}
if (((y0 - Config.start) % Config.SIZE > 2 * Config.SIZE / 3)) {
y = Config.start + Config.SIZE * (1 + (y0 - Config.start) / Config.SIZE);
}
/*
* x,y需減去start再除棋盤大小 對應棋盤陣列的索引
*/
int index_x = (x - Config.start) / Config.SIZE;
int index_y = (y - Config.start) / Config.SIZE;
if (chesses[index_x][index_y] == 0) {
txt.append("當前為白棋" + "\n");
chesses[index_x][index_y] = 1;
// System.out.println("黑"+chesses[index_x][index_y]);
back[count][0] = index_x;
back[count][1] = index_y;
System.out.println("黑 :" + index_x + " " + index_y);
count++;
g.drawImage(img_b, x - Config.CHESS_SIZE / 2, y - Config.CHESS_SIZE / 2, null);
Repaint r = new Repaint(x - Config.CHESS_SIZE / 2, y - Config.CHESS_SIZE / 2, img_b);
rep[de++] = r;
if (Check.checkfive(chesses, index_x, index_y)) {
System.out.println("黑勝");
txt.append("遊戲結束" + "\n");
txt.append("黑棋勝利" + "\n");
flag_winner = 1;
}
index_x = this.getTarget().x;
index_y = this.getTarget().y;
if (flag_winner == 0) {
// 輸出
System.out.println("白" + index_x + " " + index_y);
txt.append("當前為黑棋" + "\n");
g.drawImage(img_w, (index_x * Config.SIZE + Config.start) - Config.CHESS_SIZE / 2,
(index_y * Config.SIZE + Config.start) - Config.CHESS_SIZE / 2, null);
chesses[index_x][index_y] = -1;
back[count][0] = index_x;
back[count][1] = index_y;
count++;
r = new Repaint((index_x * Config.SIZE + Config.start) - Config.CHESS_SIZE / 2,
(index_y * Config.SIZE + Config.start) - Config.CHESS_SIZE / 2, img_w);
rep[de++] = r;
if (Check.checkfive(chesses, index_x, index_y)) {
System.out.println("白勝");
txt.append("遊戲結束" + "\n");
txt.append("白棋勝利" + "\n");
flag_winner = -1;
}
}
}
if (flag_winner != 0 || count == 225) {
finshjf = this.finshShow();
finshjf.setVisible(true);
}
}
}
/**
* 一方勝利後顯示
*/
public JFrame finshShow() {
flag_start = 0;
board.initchesses();
JFrame jf = new JFrame("Finsh Game!");
jf.setSize(200, 130);
jf.setDefaultCloseOperation(2);
// 關閉方法 :銷燬不結束
jf.setLocationRelativeTo(null);
// 居中顯示
jf.setLayout(new FlowLayout());
// 流式佈局
JButton yes = new JButton("重新開始");
JButton no = new JButton("返回棋局");
jf.add(yes);
jf.add(no);
yes.addActionListener(this);
no.addActionListener(this);
JLabel jl = new JLabel();
if (flag_winner == 1)
jl = new JLabel(" 黑棋勝利! ", new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/黑棋.png"), 0);
else if (flag_winner == -1)
jl = new JLabel(" 白棋勝利! ", new ImageIcon("D:/learning/mydemo/Javaworkspace/rect/src/com/goband/白棋.png"), 0);
else if (flag_winner == 0 && count == 225)
jl = new JLabel(" 平局! ");
jf.add(jl);
return jf;
}
public class Target {
public int x;
public int y;
public int score_b;
public int score_w;
public Target(int x, int y, int scoreb, int scorew) {
this.x = x;
this.y = y;
this.score_b = scoreb;
this.score_w = scorew;
}
public Target() {
}
}
/**
* 獲取人機評分點
*/
public Target[] getScore() {
Target[] target = new Target[Config.rows * Config.columns];
int index = 0;
AIjudge judge = new AIjudge();
for (int i = 0; i < count; i++) {
int x = back[i][0];
int y = back[i][1];
// System.out.println(chesses[x-1][y-1]+" "+chesses[x][y-1]+"
// "+chesses[x+1][y-1]);
// System.out.println(chesses[x-1][y]+" "+chesses[x][y]+"
// "+chesses[x+1][y]);
// System.out.println(chesses[x-1][y+1]+" "+chesses[x][y+1]+"
// "+chesses[x+1][y+1]);
if (x > 0) {
// 棋子左邊有效
// 正左
if (chesses[x - 1][y] == 0) {
Target t = new Target(x - 1, y, judge.judge(chesses, x - 1, y, 1),
judge.judge(chesses, x - 1, y, -1));
target[index++] = t;
}
}
if (x > 0 && y < Config.rows - 2) {
// 棋子下面有效,左下
if (chesses[x - 1][y + 1] == 0) {
Target t = new Target(x - 1, y + 1, judge.judge(chesses, x - 1, y + 1, 1),
judge.judge(chesses, x - 1, y + 1, -1));
target[index++] = t;
}
}
if (y < Config.rows - 2) {
// 正下
if (chesses[x][y + 1] == 0) {
Target t = new Target(x, y + 1, judge.judge(chesses, x, y + 1, 1),
judge.judge(chesses, x, y + 1, -1));
target[index++] = t;
}
}
if (y < Config.rows - 2 && x < Config.columns - 2) {
// 右下
if (chesses[x + 1][y + 1] == 0) {
Target t = new Target(x + 1, y + 1, judge.judge(chesses, x + 1, y + 1, 1),
judge.judge(chesses, x + 1, y + 1, -1));
target[index++] = t;
}
}
if (y > 0 && x > 0) {
// 左上有效
if (chesses[x - 1][y - 1] == 0) {
Target t = new Target(x - 1, y - 1, judge.judge(chesses, x - 1, y - 1, 1),
judge.judge(chesses, x - 1, y - 1, -1));
target[index++] = t;
}
}
if (y > 0 && x < Config.columns - 2) {// 右上
if (chesses[x + 1][y - 1] == 0) {
Target t = new Target(x + 1, y - 1, judge.judge(chesses, x + 1, y - 1, 1),
judge.judge(chesses, x + 1, y - 1, -1));
target[index++] = t;
}
}
if (x < Config.columns - 2) {
// 正右
if (chesses[x + 1][y] == 0) {
// System.out.println("right");
Target t = new Target(x + 1, y, judge.judge(chesses, x + 1, y, 1),
judge.judge(chesses, x + 1, y, -1));
target[index++] = t;
}
}
if (y > 0) {
// 正上
if (chesses[x][y - 1] == 0) {
// System.out.println("up");
Target t = new Target(x, y - 1, judge.judge(chesses, x, y - 1, 1),
judge.judge(chesses, x, y - 1, -1));
target[index++] = t;
}
}
}
return target;
}
// 評分類
public Target getTarget() {
Target[] t = getScore();
Target max_b = new Target();
Target max_w = new Target();
max_b.score_b = 0;
max_w.score_w = 0;
for (int i = 0; i < t.length; i++) {
if (t[i] != null) {
System.out.println("<" + t[i].x + ", " + t[i].y + "> " + t[i].score_b + " " + t[i].score_w);
if (t[i].score_b > max_b.score_b) {
max_b = t[i];
// System.out.println(max_b.score_b);
}
if (t[i].score_w > max_w.score_w) {
max_w = t[i];
// System.out.println(max_w.score_w);
}
}
}
if (max_b.score_b >= max_w.score_w)
return max_b;
if (max_b.score_b < max_w.score_w)
return max_w;
return null;
}
public void mousePressed(MouseEvent e) {
};
public void mouseReleased(MouseEvent e) {
};
public void mouseEntered(MouseEvent e) {
};
public void mouseExited(MouseEvent e) {
};
}
其他的部分跟雙人對戰沒有什麼差別,這個AI在判斷邊角的地方還可以更完善一點,現在先這樣吧,最後附一張效果圖:
相關文章
- Java學習筆記——陣列練習(七)Java筆記陣列
- Java學習筆記——第七天Java筆記
- AI學習筆記AI筆記
- HexMap學習筆記(七)——道路筆記
- Redis阻塞(學習筆記七)Redis筆記
- andeoid學習筆記七筆記
- Spss 學習筆記(七)SPSS筆記
- webpack學習筆記七:配置babelWeb筆記Babel
- angular學習筆記(七)-迭代1Angular筆記
- angular學習筆記(七)-迭代2Angular筆記
- angular學習筆記(七)-迭代3Angular筆記
- C++/C學習筆記(七)C++筆記
- java學習筆記Java筆記
- 《JAVA學習指南》學習筆記Java筆記
- java學習記錄第七週Java
- 演算法學習筆記演算法筆記
- Redis學習筆記(七) 資料庫Redis筆記資料庫
- ES6學習筆記(七)【class】筆記
- Laravel學習筆記七-建立部落格Laravel筆記
- Activiti 學習筆記七:連線(SequenceFlow)筆記
- OS學習筆記七:IO系統筆記
- Java 集合學習筆記Java筆記
- java學習筆記6Java筆記
- Java學習筆記--反射Java筆記反射
- java學習筆記啊Java筆記
- Java學習筆記二Java筆記
- Java學習筆記三Java筆記
- Java JNI 學習筆記Java筆記
- Java學習筆記4Java筆記
- Java學習筆記--sql與javaJava筆記SQL
- LMF演算法學習筆記演算法筆記
- 機器學習演算法學習筆記機器學習演算法筆記
- 匈牙利演算法學習筆記演算法筆記
- 學習筆記----KM演算法筆記演算法
- 學習筆記----RMQ演算法筆記MQ演算法
- EM演算法學習筆記演算法筆記
- Floyd演算法學習筆記演算法筆記
- Tarjan 演算法學習筆記演算法筆記