序文
五人の子供、それはすべての年齢のための娯楽である、古代中国のチェスの一つです。マン・マシン・ゲームは行く、チェスあまり変化に比較して、最も簡単なカテゴリである、アルゴリズムは実装が比較的簡単です。
上側の手の優位性を制限するルールの開発に手にいくつかの段階的な禁止がなされているので、バックギャモンはただ、理論的には百パーセント勝率を取得します。しかし、これらはプロ選手のために、平均的なプレーヤーのために非常に多くの制限を必要としない、単純なことができます。それは、単純なバックギャモンは、それゆえ、それほど制約を考慮することがあるので、このアルゴリズムは、あまりにも、ここにあります。
デザインのアイデア
設計アルゴリズムのように、私たちはバックギャモンマイニングの背後にある原則を持っています。チェスゲームは疑問に分類することができます。ゲーム2は、戦いの利益、ゲームの最終的な結果は、両側の利益のほとんどアウトを得ることができます誰が見ていることです。
私たちの最初のチェスの深い分析は、攻撃と守備のモードに分かれて。たとえば、この時点で、私たちは三つのサブコネクションを持っている、攻撃的である、4の次に1を接続し、そこに他の三つのサブ接続、我々は守備のある4つのサブ牙連城を停止しようとしているとき。
思考の攻撃と守備の方法によると、私たちは下の最大の利益を取得する方法を比較検討する必要があります。簡単な方法はLazi高および低スコアを比較検討する各位置に応じて、画分としての利益を定量化することです。
したがって、公正なグレーディングシステムの確立は非常に重要です。数と息子、そして息子に応じて、および(欠員のためのXの敵の息子、O私の息子、_)次のように両側には、相手Laziのスコアシートかどうかを確立します。
レイアウト | 子ません | 一子 | 二子 | 三人の息子 | 四人の息子 | 五人の子供 |
---|---|---|---|---|---|---|
2つの抗 | XX | XOX | 競合 | XOOOX | XOOOOX | XOOOOOX |
証明 | バツ_ | XO_ | XOO_ | XOOO_ | XOOOO_ | XOOOOO_ |
証拠ません | _ | ザ・ | と | OOO | OOOO | oooooが |
分数 | 子ません | 一子 | 二子 | 三人の息子 | 四人の息子 | 五人の子供 |
---|---|---|---|---|---|---|
2つの抗 | 0 | 0 | 0 | 0 | 0 | 10000 |
証明 | 0 | 0 | 20 | 100 | 500 | 10000 |
証拠ません | 0 | 20 | 100 | 500 | 2500 | 10000 |
数は5つのサブサブよりも大きい場合であっても、5人の子供が計算されます。
OK、我々はプログラムを書き始めることができます。
アルゴリズム
標準的なバックギャモンは、一般的に15の* 15の格子、その最初のボードを設置し、太陽黒点1、-1アルビノに代わって契約です。
vector<vector<int>> topo(15, vector<int>(15, 0));
上記のスコア表によると、私たちは、それぞれの位置のためのプログラムの評価を記述する必要があります:
//米字型搜索
//[—, | , / , \]四个移动方向
static const int inX[] = { 1,0,1,1 };
static const int inY[] = { 0,1,1,-1 };
//评分表
static const int Score[3][6] = {
{ 0, 0, 0, 0, 0,10000 },//防守2子
{ 0, 0, 20,100, 500,10000 },//防守1子
{ 0,20,100,500,2500,10000 } //防守0子
};
//topo:棋盘
//x,y:棋盘位置
//color:落子颜色(黑色:1;白色:-1)
int getScore(vector<vector<int>> topo,
const int x, const int y,
const int color) {
//返回评分值
int re = 0;
//向 [—,|, /, \]四个方向搜索,对应inX,inY
for (int i = 0; i < 4; ++i) {
//k记录连子两侧空位的数目(非墙,非敌方落子)
int k = 0;
//记录连子的数目,初始值为1因为假设在当前位置落子
int count = 1;
//[—,|, /, \]四个方向的正负方向
for (int j = -1; j < 2; j += 2) {
int dx = x + j * inX[i];
int dy = y + j * inY[i];
//判断是否超出棋盘边界
while (dx >= 0 && dx < topo.size() &&
dy >= 0 && dy < topo[0].size()) {
//假如遇到颜色相同的子,count+1,反之则退出循环,并判断此时有无空位
if (color*topo[dx][dy] > 0) {
++count;
}
else {
if (color*topo[dx][dy] == 0) ++k;
break;
}
dx += j * inX[i];
dy += j * inY[i];
}
}
//假如连子大于5,使之等于5
if (count > 5) count = 5;
//加上该方向所得评分
re += Score[k][count];
}
return re;
}
書かれた機能を得点、我々は以前の考え方によると、AIの選手を設計するために始めた、私たちはすべての空を通過して、利益を得るための最大のポイントを見つける必要があります。次のとおりです。
void AiChesser(int color,
int &x, int &y,
vector<vector<int>> topo) {
int max = INT_MIN;
vector<int> X;
vector<int> Y;
for (int i = 0; i < topo.size(); ++i) {
for (int j = 0; j < topo[i].size(); ++j) {
//判断是否为空位
if (topo[i][j] == 0) {
//进攻还是防守,寻找利益最大值
int score = max(getScore(topo, i, j, color),
getScore(topo, i, j, -color));
//以防有多个相同的最大值
if (score >= max) {
if (score > max) {
X.clear();
Y.clear();
max = score;
}
X.push_back(i);
Y.push_back(j);
}
}
}
}
//在最大值中任取一个返回,大部分情况只有一个
int r = rand() % X.size();
x = X[r];
y = Y[r];
}
言葉の後
もちろん、このようなものは、特定のUI設計を実行することができますまた、プログラムではありません意見の問題であるが、これは主にアルゴリズムを説明しています。Easyxライブラリーの設計は、完全な提供バックギャモンプロジェクトを実行EXEファイルを添付するための基準として。
実際にはこのアルゴリズムは、ジュニア選手のレベルに達したが、普通の人との戦いに十分。
シンプルなデザインの多くの部分でまだ理解しやすいコード用に最適化されたアルゴリズムに値する多くの場所があります。
アドバンスデザイン
私たちのAIのデザインはかなりシンプルですが、本当のマスターは目だけを見ることができない、彼らがステップダウンする傾向にあるサービスの多くをバックステップです。したがって、我々はさらに私たちのアルゴリズムを改善したいと考えて、それが戻ってからのステップの多くを考慮する必要があり、そして唯一の即時のステップは表示されません。ここではミニマックスアルゴリズムとアルファ・ベータ法のアルゴリズムを導入する必要がある、私は将来の記事では、これらについて説明します。