人工智能课上学了一些搜索算法以及最近学了对弈学在棋类中的应用,认识到了alpha-beta剪枝算法,实现一个简单的黑白棋的程序。源码
链接:http://pan.baidu.com/s/1i5K41z3 密码:6i5z
黑白棋:
又叫翻转棋(Reversi)、奥赛罗棋(Othello)、苹果棋或反棋(Anti reversi)。黑白棋在西方和日本很流行。游戏通过相互翻转对方的棋子,最后以棋盘上谁的棋子多来判断胜负。它的游戏规则简单,因此上手很容易,但是它的变化又非常复杂。
黑白棋百度百科
黑白棋维基百科
我的黑白棋为了简单改成6*6的,关于6*6的黑白棋网上有个在线可以用我的黑白棋玩一玩由于考虑到运行时间,所以就max->min->max->min往下搜四层,当然想要搜索层数更多更智能咯
对于应用在黑白棋的算法其实还有许多,比如决策树,BP神经网之类的算法,好多。
然后关于我用到的alpha-beta剪枝算法,不是很熟悉的可以看下别人写的这个文档,里面的伪代码写的很好,而且还讲到了优化方法,比如置换表,历史表,以及学习算法的应用。链接:http://pan.baidu.com/s/1kVCsNGF 密码:kn5x
附两个重要的函数:
(1)棋翻转函数:
void CBlackWhiteDlg::TransChess(int ChessType, int y, int x)
{
if (y<0 || x<0)return;
int k, m, l, n;//计数器
if (ChessType == WhiteChess)
{
for (k = x + 1; k < 6; k++)//水平向右方向
{
if (ChessBoard[y][k] == NoChess)
break;
if (ChessBoard[y][k] == WhiteChess)
{
for (l = x + 1; l < k; l++)
{
SubChess(BlackChess, y, l, BlackPosition);
DrawChess(WhiteChess, y, l);
}
break;
}
}
for (k = x - 1; k >= 0; k--)//水平向左方向
{
if (ChessBoard[y][k] == NoChess)
break;
if (ChessBoard[y][k] == WhiteChess)
{
for (l = k + 1; l < x; l++)
{
SubChess(BlackChess, y, l, BlackPosition);
DrawChess(WhiteChess, y, l);
}
break;
}
}
for (k = y + 1; k < 6; k++)//垂直向下方向
{
if (ChessBoard[k][x] == NoChess)
break;
if (ChessBoard[k][x] == WhiteChess)
{
for (l = y + 1; l < k; l++)
{
SubChess(BlackChess, l, x, BlackPosition);
DrawChess(WhiteChess, l, x);
}
break;
}
}
for (k = y - 1; k >= 0; k--)//垂直向上方向
{
if (ChessBoard[k][x] == NoChess)
break;
if (ChessBoard[k][x] == WhiteChess)
{
for (l = k + 1; l < y; l++)
{
SubChess(BlackChess, l, x, BlackPosition);
DrawChess(WhiteChess, l, x);
}
break;
}
}
for (k = x - 1, m = y - 1; k >= 0 && m >= 0; k--, m--)//左上角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == WhiteChess)
{
for (l = x - 1, n = y - 1; l>k&&n>m; l--, n--)
{
SubChess(BlackChess, n, l, BlackPosition);
DrawChess(WhiteChess, n, l);
}
break;
}
}
for (k = x + 1, m = y + 1; k<6 && m <6; k++, m++)//右下角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == WhiteChess)
{
for (l = x + 1, n = y + 1; lbreak;
}
}
for (k = x - 1, m = y + 1; k >= 0 && m <6; k--, m++)//左下角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == WhiteChess)
{
for (l = x - 1, n = y + 1; l>k&&nbreak;
}
}
for (k = x + 1, m = y - 1; k<6 && m >= 0; k++, m--)//右上角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == WhiteChess)
{
for (l = x + 1, n = y - 1; lm; l++, n--)
{
SubChess(BlackChess, n, l, BlackPosition);
DrawChess(WhiteChess, n, l);
}
break;
}
}
}
if (ChessType == BlackChess)
{
for (k = x + 1; k < 6; k++)//水平向右方向
{
if (ChessBoard[y][k] == NoChess)
break;
if (ChessBoard[y][k] == BlackChess)
{
for (l = x + 1; l < k; l++)
{
SubChess(WhiteChess, y, l, WhitePosition);
DrawChess(BlackChess, y, l);
}
break;
}
}
for (k = x - 1; k >= 0; k--)//水平向左方向
{
if (ChessBoard[y][k] == NoChess)
break;
if (ChessBoard[y][k] == BlackChess)
{
for (l = k + 1; l < x; l++)
{
SubChess(WhiteChess, y, l, WhitePosition);
DrawChess(BlackChess, y, l);
}
break;
}
}
for (k = y + 1; k < 6; k++)//垂直向下方向
{
if (ChessBoard[k][x] == NoChess)
break;
if (ChessBoard[k][x] == BlackChess)
{
for (l = y + 1; l < k; l++)
{
SubChess(WhiteChess, l, x, WhitePosition);
DrawChess(BlackChess, l, x);
}
break;
}
}
for (k = y - 1; k >= 0; k--)//垂直向上方向
{
if (ChessBoard[k][x] == NoChess)
break;
if (ChessBoard[k][x] == BlackChess)
{
for (l = k + 1; l < y; l++)
{
SubChess(WhiteChess, l, x, WhitePosition);
DrawChess(BlackChess, l, x);
}
break;
}
}
for (k = x - 1, m = y - 1; k >= 0 && m >= 0; k--, m--)//左上角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == BlackChess)
{
for (l = x - 1, n = y - 1; l>k&&n>m; l--, n--)
{
SubChess(WhiteChess, n, l, WhitePosition);
DrawChess(BlackChess, n, l);
}
break;
}
}
for (k = x + 1, m = y + 1; k<6 && m <6; k++, m++)//右下角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == BlackChess)
{
for (l = x + 1, n = y + 1; lbreak;
}
}
for (k = x - 1, m = y + 1; k >= 0 && m <6; k--, m++)//左下角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == BlackChess)
{
for (l = x - 1, n = y + 1; l>k&&nbreak;
}
}
for (k = x + 1, m = y - 1; k<6 && m >= 0; k++, m--)//右上角方向
{
if (ChessBoard[m][k] == NoChess)
break;
if (ChessBoard[m][k] == BlackChess)
{
for (l = x + 1, n = y - 1; lm; l++, n--)
{
SubChess(WhiteChess, n, l, WhitePosition);
DrawChess(BlackChess, n, l);
}
break;
}
}
}
}
(2)alpha-beta剪枝
///alpha-beta搜索,max,min,max,min各两层
void CBlackWhiteDlg::Computer(int *stepRow, int *stepColumn)
{
int QuanMin[PositionMax];
int alfa = QuanZhiMax, belta = QuanZhiMin;
int i, j, l, m;//计数器
int V;//评估值
int ParentRow, ParentColumn, ChildRow, ChildColumn, Child_2_Row, Child_2_Column;
int Child_3_Row, Child_3_Column;
CChessPosition ParentWhiteCanGo[PositionMax];
CChessPosition ChildBlackCanGo[PositionMax];
CChessPosition Child_2_WhiteCanGo[PositionMax];
CChessPosition Child_3_BlackCanGo[PositionMax];
CChessPosition Child_4_WhiteCanGo[PositionMax];
ListCanGo(WhiteChess, ParentWhiteCanGo);
*stepRow = ParentWhiteCanGo[1].Row;
*stepColumn = ParentWhiteCanGo[1].Column;
//初始化
for (i = 0; i <= ParentWhiteCanGo[0].ChessNum; i++)
{
QuanMin[i] = QuanZhiMin;
}
for (i = 1; i <= ParentWhiteCanGo[0].ChessNum; i++)
{
BOOL CutFlag = FALSE;
CChessPosition ParentWhiteTrans[PositionMax];
ParentRow = ParentWhiteCanGo[i].Row;
ParentColumn = ParentWhiteCanGo[i].Column;
AddChess(WhiteChess, ParentRow, ParentColumn, WhitePosition);//白棋位置上增加一个坐标
ChessBoard[ParentRow][ParentColumn] = WhiteChess;
TransChessPredict(WhiteChess, ParentRow, ParentColumn, ParentWhiteTrans);
ListCanGo(BlackChess, ChildBlackCanGo);
for (j = 1; j <= ChildBlackCanGo[0].ChessNum; j++)
{
CChessPosition ChildBlackTrans[PositionMax];
ChildRow = ChildBlackCanGo[j].Row;
ChildColumn = ChildBlackCanGo[j].Column;
AddChess(BlackChess, ChildRow, ChildColumn, BlackPosition);
ChessBoard[ChildRow][ChildColumn] = BlackChess;
TransChessPredict(BlackChess, ChildRow, ChildColumn, ChildBlackTrans);
ListCanGo(WhiteChess, Child_2_WhiteCanGo);
///还原
for (l = 1; l <= Child_2_WhiteCanGo[0].ChessNum; l++)
{
CChessPosition Child_2_WhiteTrans[PositionMax];
Child_2_Row = Child_2_WhiteCanGo[l].Row;
Child_2_Column = Child_2_WhiteCanGo[l].Column;
AddChess(WhiteChess, Child_2_Row, Child_2_Column, WhitePosition);
ChessBoard[Child_2_Row][Child_2_Column] = WhiteChess;
TransChessPredict(WhiteChess, Child_2_Row, Child_2_Column, Child_2_WhiteTrans);
ListCanGo(BlackChess, Child_3_BlackCanGo);
for (m = 1; m <= Child_3_BlackCanGo[0].ChessNum; m++)
{
CChessPosition Child_3_BlackTrans[PositionMax];
Child_3_Row = Child_3_BlackCanGo[m].Row;
Child_3_Column = Child_3_BlackCanGo[m].Column;
AddChess(BlackChess, Child_3_Row, Child_3_Column, BlackPosition);
ChessBoard[Child_3_Row][Child_3_Column] = BlackChess;
TransChessPredict(BlackChess, Child_3_Row, Child_3_Column, Child_3_BlackTrans);
ListCanGo(WhiteChess, Child_4_WhiteCanGo);
V = QuanZhi(WhitePosition, BlackPosition) + Child_4_WhiteCanGo[0].ChessNum;
//还原
BackStep(BlackChess, Child_3_Row, Child_3_Column, Child_3_BlackTrans);
belta = V;
if (V < QuanMin[i])
QuanMin[i] = V;
//发生裁剪
if ((i != 1) && (beltabreak;
}
}
BackStep(WhiteChess, Child_2_Row, Child_2_Column, Child_2_WhiteTrans);
//发生裁剪
if (CutFlag)
break;
}
BackStep(BlackChess, ChildRow, ChildColumn, ChildBlackTrans);
//发生裁剪
if (CutFlag)
break;
}
//还原
BackStep(WhiteChess, ParentRow, ParentColumn, ParentWhiteTrans);
////如果没有发生裁剪,则保留坐标
if (!CutFlag&&QuanMin[i] != QuanZhiMin)
{
alfa = QuanMin[i];
*stepRow = ParentRow;
*stepColumn = ParentColumn;
}
}
DrawChess(WhiteChess, *stepRow, *stepColumn);
TransChess(WhiteChess, *stepRow, *stepColumn);
}
又是很粗暴,具体的其他细节可以看源码里面的BlackWhiteDlg.cpp