java象棋ai偽代碼 開源象棋 AI

象棋軟件如何開發(fā)的?

先弄明白數(shù)據(jù)的結構:

創(chuàng)新互聯(lián)建站主營濟寧網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,成都app軟件開發(fā)公司,濟寧h5成都微信小程序搭建,濟寧網(wǎng)站營銷推廣歡迎濟寧等地區(qū)企業(yè)咨詢

MantisChessDef.h里的東西一定要先看一下, 否則會摸不到頭腦的。

還有棋盤坐標:

象棋棋盤大小9x10,為了便于編程,規(guī)定棋盤每條邊留有一個元素的邊界。

這樣棋盤大?。òㄟ吔纾┳兂?1x12。棋盤x坐標軸向右,y軸向下。

黑棋永遠在上方,在標準開局時左上角的黑車坐標是(1,1)。

局面用這三個變量表示:

static POINT g_pointChessman[32]; //棋子坐標

static int g_iChessmanMap[11][12]; //棋位狀態(tài)

static int g_iSide; //輪到哪方走

智能部分有幾個函數(shù)的前三個參數(shù)就是這個東西, 應該不難理解吧?

---------------------------------------------------------------------------------------

search函數(shù):

先說明一下, 經(jīng)常有朋友問我要原理, 但我公開源代碼是給大家一個參考, 而不是什么教程,所以我不想說那些理論的東西。

基本原理是α-β搜索, 很多人工智能的教科書上都有講到, 沒看過的的趕快去找一本來啃一啃;

雖然這些書上的文字大多晦澀難懂,但畢竟講得明明白白。

沒有書的朋友請發(fā)揮一下主觀能動性, 去找一找,不要來問我要, 因為我也沒有。

我在這里只分析一下search函數(shù):

弄懂α-β搜索后來看看這個博弈樹, 看怎么編程實現(xiàn)它。

先規(guī)定一下, 我們用一個整數(shù)表示局面的好壞.

這個數(shù)越大說明局面對 "走棋方" 越有利,0表示雙方實力相等。

1a( 1) ┬ 2a(-1) ┬ 3a(-1)

│ └ 3b( 1)

└ 2b(-5) ┬ 3c( 2)

├ 3d(-4)

└ 3e( 5)

分析一下這棵樹,有這么個特點: 父結點的值 = -MAX(子結點的值)

我們還知道1、每個結點對應一個局面。2、底層的結點的值是"估"出來的。

于是我們可以寫出偽代碼了:

偽代碼: 搜索一個結點下的分支, 得到這個結點的值。

參數(shù): 局面,搜索深度

返回值:結點的值

int search(局面,int depth)

{

if(depth!=0)//不是底層結點

{

枚舉出所有子結點(列出所有走法);

int count=子結點數(shù);

int maxvalue= -∞;

for(int i=0;icount;i++)//遍歷所有結點

{

算出子結點局面;

maxvalue=max(maxvalue,search(子結點局面,depth-1));

}

return -maxvalue;

}

else //是底層結點

{

return 估計值;

}

}

這就是搜索算法的框架, 用到了遞歸。

MantisChess的智能部分函數(shù)都在MantisChessThink.cpp里, 其中search是搜索, 跟上面的這個search差不多,我把它copy出來注釋一下:

int Search(int tmap[11][12],POINT tmanposition[32],int tside,int man, POINT point,int upmax,int depth)

{

//前面的三個參數(shù)就是局面。

//man 和point 是走法,用來計算本結點的局面。 這里是把計算局面放在函數(shù)的開頭,跟上面的偽代碼不太一樣。

//upmax: up - 上一層, max - 最大值, 這是α-β的剪枝用到的東西, 后面再講。

//depth: 搜索深度

int ate,cur,maxvalue,curvalue,xs,ys;

int count;

//#####################這一段是計算本結點的局面#########################################

ate=32;

//移動棋子:

xs=tmanposition[man].x;ys=tmanposition[man].y; //原坐標

if (SideOfMan[tmap[point.x][point.y]]==!tside) //目標點有對方的棋子

{

ate=tmap[point.x][point.y]; //記錄下被吃掉的棋子

if(ate==0 || ate==16)

{

return 9999;

}

tmanposition[ate].x=0; //目標點的棋子被吃掉

}

tmap[point.x][point.y]=man; //這兩行是:

tmap[xs][ys]=32; //在map上的移動

tmanposition[man]=point;

tside=!tside;

//####################################################################################

depth--;

if(depth0) //不是底層結點

{

int chessman[125];

POINT targetpoint[125];

if(EnumList(tmap,tmanposition,tside,chessman,targetpoint,count)) //枚舉出所有子結點(列出所有走法)

{

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//這里是剪枝(不是α-β剪枝), 原理是在正式搜索之前先用較淺的搜索來得到誤差較大的值

//然后根據(jù)這些值來對子結點排序, 只保留最好的S_WIDTH個結點進行正式搜索。

//顯然,這個剪枝有一定的風險

if(depth=2 countS_WIDTH+2)

{

int value[125];

cur=0;

maxvalue=-10000;

while(cur count)

{

curvalue=Search(tmap,tmanposition,tside,chessman[cur],targetpoint[cur],-10000,depth-2);

value[cur]=curvalue;

if(curvaluemaxvalue)maxvalue=curvalue;

cur ++;

}

::Mantis_QuickSort(value,chessman,targetpoint,0,count-1); //排序

count=S_WIDTH;//剪枝

}

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

maxvalue=-10000;

cur=0;

while(cur count)

{

curvalue=Search(tmap,tmanposition,tside,chessman[cur],targetpoint[cur],maxvalue,depth);

if(curvaluemaxvalue)maxvalue=curvalue;

if(curvalue=-upmax)goto _ENDSUB; //α-β剪枝, 符合剪枝條件的就Cut掉。 這里用了goto語句了, 千萬別學我。

cur ++;

}

}

else maxvalue=9800;

}

else //是底層結點

{

maxvalue=Value(tmap,tmanposition,tside); //估值

}

_ENDSUB:

//返回之前要恢復父結點的局面

//####################################################################################

tmanposition[man].x=xs; //這兩行是:

tmanposition[man].y=ys; //在face上的恢復

tmap[xs][ys]=man; //在map上的恢復

if(ate!=32)

{

tmanposition[ate]=point;

tmap[point.x][point.y]=ate;

}

else tmap[point.x][point.y]=32;

tside=!tside;

//####################################################################################

return -maxvalue;

}

上面的代碼用到了α-β剪枝, 舉個例子就明白了:

還是這個博弈樹,從上往下遍歷。

1a( 1) ┳ 2a(-1) ┳ 3a(-1)

┃ ┗ 3b( 1)

┗ 2b(-5) ┯ 3c( 2)

├ 3d(-4)

└ 3e( 5)

2a遍歷完后 upmax=-1, 繼續(xù)遍歷完3c后返回2b, 發(fā)現(xiàn)3c=2-upmax, 這時就不用管3d和3e了, 因為無論他們的值是多少 2b=-max(3c,3d,3e)2a 一定成立,

也就是說2b可以安全地剪掉。這就是α-β剪枝。

從上面的代碼來看我的MantisChess算法與標準的α-β剪枝搜索并沒有什么不同, 只不過加了排序和剪枝而已。

使用java編程:國際象棋棋盤64個格,第一格放一粒米,每一格比前一格多一顆,放滿需要多少米 急!急!

package com.plague.math;

import java.lang.Math;

public class Chess {

private final static int CHESS_NUMBER = 64;

private int total;

public Chess () {

System.out.println("國王的賞賜,其實,問題是這樣的:" +

"在國際象棋的棋盤上,第一格放一粒米,第二格放2粒米,第三個放四粒米。。。最后國王要賞賜多少米");

for (int i = 0; i CHESS_NUMBER; i++) {

total += Math.pow(2.0,(double)i);

}

System.out.println("國王的賞賜是:"+total);

}

public static void main(String[] args) {

Chess c1 = new Chess();

}

}

象棋對弈軟件是如何編制出來的

呵呵,開始我也覺得沒有破綻,后來發(fā)現(xiàn)了軟件也會出昏招。原來原理很簡單,只是把基本的開局定式以及常見的對弈拆解局面轉(zhuǎn)換成數(shù)據(jù)庫函數(shù),當出現(xiàn)數(shù)據(jù)庫招數(shù),便調(diào)出同類型的宏功能。說到底,只是電腦軟件做到了更多的對弈棋局收集,把相關的招數(shù)進行了數(shù)碼匯編。比如:仙人指路開局,軟件就會自動把存儲在數(shù)據(jù)庫中的符合這一定式類型的所有函數(shù)自動調(diào)出,選擇基本應招(根據(jù)用戶選手游戲難度不同,軟件也會選擇相應招數(shù)致勝比率和復雜程度)。所以按一般局面和軟件玩,就等于和一個熟讀兵法的謀士作戰(zhàn),很難贏。你會有看不透,想不到的時候,軟件按步就班,數(shù)據(jù)庫就是它的眼睛和腦袋。但是編制軟件的并不是一流大師,他們手頭上有的都是找得到的棋局,但是棋盤千變?nèi)f化,有很多招式不可能存在軟件中,所以軟件也會碰到出昏招的時候。我們可以做一個小實驗,兩臺電腦玩相同的象棋游戲,如果以A電腦進行先手,B電腦進行后手,以B電腦的招式來和A電腦下。百分之九十九的機率是和棋。如果我們用自己的方式操作B電腦和A電腦進行至中局(有一方有多子優(yōu)勢),然后再讓兩臺電腦自己下,肯定有一臺電腦是輸?shù)?。你就會發(fā)現(xiàn)輸?shù)碾娔X下的棋局很一般,因為它還是在以應對的形式開展,試問沒有優(yōu)勢的情況下,那臺數(shù)據(jù)庫一樣的電腦軟件會出現(xiàn)奇招嘛?也就是說軟件也是會輸?shù)摹N矣浀脟H象棋那個深藍也輸給過卡斯帕羅夫,然后那個更深的藍贏了卡斯帕羅夫。還是贏在數(shù)據(jù)采集啊。

用java寫一個國際象棋的棋盤,輸出結果要是一張 國際象棋的棋盤

import java.awt.*;

import javax.swing.*;

public class Chessboard extends JApplet {

int baseXPosition, baseYPosition;

int currentXPosition, currentYPosition;

public void init() {

baseXPosition = 40; // 棋盤的開始x位置

baseYPosition = 40; // 棋盤的開始y位置

setBackground(Color.black); // 設置背景顏色黑色

}

public void paint(Graphics g) { // 繪制棋盤

currentXPosition = baseXPosition; // currentXPosition當前的x位置

currentYPosition = baseYPosition; // currentYPosition當前的y位置

for (int row = 0; row 8; row++) {

currentXPosition = baseXPosition + row * 40;

for (int column = 0; column 8; column++) {

if ((column + row) % 2 == 0)

g.setColor(Color.white); // 設置棋盤格子的顏色

else

g.setColor(Color.red); // 設置棋盤格子的顏色

currentYPosition = baseXPosition + column * 40;

g.drawRect(currentXPosition,currentYPosition,40,40);//;代碼4 //在當前位置繪制棋盤的格子;每個格子的大小是40*40像

g.fillRect(currentXPosition,currentYPosition,40,40);

}

}

}

}

顯示一個國際象棋棋盤的java源代碼

import java.awt.Color;

import javax.swing.*;

public class Chess extends JPanel

{// 繼承面板類

public Chess(int grids,int gridsize)

{//grids:行數(shù)和列數(shù), gridsize:單元格的高和寬

super(null);

for(int i=0; igrids; i++)

{

for(int j=0; jgrids; j++)

{

JLabel l = new JLabel();//生成標簽實例

l.setSize(gridsize,gridsize);

l.setLocation(i*gridsize,j*gridsize);

if((i+j)%2==0)

{ //當小方格的坐標和剛好是偶數(shù)時,

l.setBackground(Color.black); //設置為方格為黑色

l.setOpaque(true); //設置為不透明

}

l.setBorder(BorderFactory.createLineBorder(Color.black)); //設置邊界為黑色

add(l);//將l標簽添加到面板

}

}

}

public static void main(String[] args)

{

JFrame f = new JFrame();

f.setSize(658,677); //邊框的長和寬

f.setLocationRelativeTo(null); //設置窗口相對于指定組件的位置

f.add(new Chess(8,80));

f.setVisible(true);

}

}

當前標題:java象棋ai偽代碼 開源象棋 AI
新聞來源:http://muchs.cn/article24/hjcoje.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護、關鍵詞優(yōu)化、網(wǎng)站設計公司手機網(wǎng)站建設、用戶體驗、搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)