JAVAの最初の小項目である五子棋の制作(第二編)
6288 ワード
前の文章では、どのように碁盤を作って、碁の効果を実現して、どのように勝負を判断するかについて話しました.では、スマートなヒューマン・マシン・ウォーズを実現する方法についてお話しします.実は少しコンピュータを知っている人はすべてコンピュータがとても愚かなことを知っていて、自分の思考がなくて、それは何をするには指定しなければならなくて、しかも明確で唯一でなければなりません.では、人机大戦を実现するには、もちろんいくつかのアルゴリズムを使う必要があります.前に先生が讲义していた时、何种类も言いました.木も含めて、自分は闻いたことがありません.自分はACM校队にいますが、主な方向は図论です.まあ、言い訳です.どうせ今回は一番简単で分かりやすいアルゴリズムです.
権値法は何ですか.実は彼は列挙された暴力に基づく方法だ.前に五子棋の碁盤は15*15だと言いました.そして、獲得状況は5つの同じ駒が1つにつながっているので、私たちはすべての獲得状況を挙げることができて、約数千種類を挙げることができて、私たちから見ればこの数字は比較的に大きいですが、1秒で数級から8まで処理できるコンピュータにとって、小さなcaseではありませんか?では、この理解があれば、私たちは2つの表を実現することができます.それぞれ機械と人の勝利表、つまり勝利状況を格納する表です.では、この表があれば、最終的に機械が碁を打つことを決定するのは重み値で判断します.重み値はどのように来ても、まず気にしないでください.私たちも2つの表で機械と人の重み値の表をそれぞれ格納し、コードを貼ります.
これらのものの意味を言うと、scorepは人の重みを格納するテーブルであり、scorecは機械の重みを格納するテーブルである.winlist同理は勝った場合を格納する表である.それは1つの構造体の配列で、その中のx、yはそれぞれ5つの駒がつながっている座標を貯蔵して、lastはこの状況が有効かどうかを示して、説明して、例えばこれは白棋が勝つ1種の情況を貯蔵して、5つの駒の座標はすべてすでに貯蔵して、しかし碁の経過の中で、1つの黒い駒の下でこの5つの座標の1つになって、では、白棋はこの状況で勝つことはできません.それは無効です.将棋が多くなるにつれて、コンピュータでも人間のwinlistでも無効なものが多くなることがわかります.
winlistの役割を理解して、私达はscoreの作用を言って、彼は権値を蓄える表で、毎回遍歴して黒棋と白棋の権値の最大値を探し出して、私达は白棋を受け取ってコンピュータで、黒棋は人で、それではもし権値の最大のは白棋ならば攻撃を体現して、もし黒棋ならば体現する守備で、私たちが今言っているのはコンピュータに対するものです.私たちがこのプログラムを作ったのは、コンピュータに碁を打つ方法を知らせるためです.
どのようにして重みを計算しますか?まずジャンプしないで、winlistがどのように初期化して更新するかを見てみましょう.初期化はすべての勝った状況をすべて保存することですか.コードを貼ります.
コードは長いですが難しくないので、一部貼っておきますが、分かったら残りのコードは自分で補うのは絶対に問題ありません.コードを見てみると、すべての勝った状況を列挙していることが明らかになるはずです.それぞれ横方向と縦方向、斜め方向の2つで、forサイクルで直接すべて初期化できます.score配列の初期化はもちろん0である.
では、winlist配列をどのように更新するかは簡単です.白棋を更新すると、碁盤を回って黒棋の位置を探して、winlist表を回って、この黒棋の座標がどのような状況に含まれているかを見て、この状況は無効になります.コードを貼ります.
私の言うとおりにコードを見に行くのは簡単ではないでしょうか.
では、次にscore配列を更新する方法についてお話しします.この座標がwinlistに含まれている場合が多ければ多いほど、将棋のこの位置での使い道が大きくなるのは明らかです.これは一つの側面ですが、なぜwinlistにはwn配列があるのでしょうか.それは3つの駒がつながっているかどうかを判断することです.4つの駒がつながっています??などなど.重み値なので、それぞれの状況には一定の数値が必要です.例えば、生きているうちに大きくなったり、生きているうちに負けてしまったりして、重み値がどのように確かに大きな影響を与えたのか、自分では今まで良い分配方法が見つかりませんでした.これはどのようにみんなに自分で决めるようにしましょう、残りの私は多く言わないで、毎回更に権値のリストを行って、最大の位置を选んで碁を打つのがよくて、しかしすべての情况をすべて考虑したため、前に1人が言ったことがあって、もしコンピュータの先手は胜つことを保证することができないならばしかし负けないことができます.ハハハしかし、私が実現していないこの程度は、やはり強化しなければなりません.その五つの碁はここまでだ.
権値法は何ですか.実は彼は列挙された暴力に基づく方法だ.前に五子棋の碁盤は15*15だと言いました.そして、獲得状況は5つの同じ駒が1つにつながっているので、私たちはすべての獲得状況を挙げることができて、約数千種類を挙げることができて、私たちから見ればこの数字は比較的に大きいですが、1秒で数級から8まで処理できるコンピュータにとって、小さなcaseではありませんか?では、この理解があれば、私たちは2つの表を実現することができます.それぞれ機械と人の勝利表、つまり勝利状況を格納する表です.では、この表があれば、最終的に機械が碁を打つことを決定するのは重み値で判断します.重み値はどのように来ても、まず気にしないでください.私たちも2つの表で機械と人の重み値の表をそれぞれ格納し、コードを貼ります.
private GoBangPanel panel;
private Graphics2D g;
private int num;
private Judge j;
public class struct
{
int last;
// x,y
int[] x = new int[5];
int[] y = new int[5];
//
int[] wn = new int[5];
}
struct[] winlistp = new struct[800];
struct[] winlistc = new struct[800];
int[][] scorep = new int[Row][Coloum];
int[][] scorec = new int[Row][Coloum];
これらのものの意味を言うと、scorepは人の重みを格納するテーブルであり、scorecは機械の重みを格納するテーブルである.winlist同理は勝った場合を格納する表である.それは1つの構造体の配列で、その中のx、yはそれぞれ5つの駒がつながっている座標を貯蔵して、lastはこの状況が有効かどうかを示して、説明して、例えばこれは白棋が勝つ1種の情況を貯蔵して、5つの駒の座標はすべてすでに貯蔵して、しかし碁の経過の中で、1つの黒い駒の下でこの5つの座標の1つになって、では、白棋はこの状況で勝つことはできません.それは無効です.将棋が多くなるにつれて、コンピュータでも人間のwinlistでも無効なものが多くなることがわかります.
winlistの役割を理解して、私达はscoreの作用を言って、彼は権値を蓄える表で、毎回遍歴して黒棋と白棋の権値の最大値を探し出して、私达は白棋を受け取ってコンピュータで、黒棋は人で、それではもし権値の最大のは白棋ならば攻撃を体現して、もし黒棋ならば体現する守備で、私たちが今言っているのはコンピュータに対するものです.私たちがこのプログラムを作ったのは、コンピュータに碁を打つ方法を知らせるためです.
どのようにして重みを計算しますか?まずジャンプしないで、winlistがどのように初期化して更新するかを見てみましょう.初期化はすべての勝った状況をすべて保存することですか.コードを貼ります.
public GoBangAn(GoBangPanel panel)
{
//
for(int i = 0; i < Row; i++)
{
for(int j = 0; j < Coloum; j++)
{
scorep[i][j] = 0;
scorec[i][j] = 0;
}
}
//
for(int i = 0; i < 800; i++)
{
winlistp[i] = new struct();
winlistc[i] = new struct();
}
this.panel = panel;
g = (Graphics2D)this.panel.getGraphics();
num = 0;
// ( 4 )
//
for(int i = 0; i < Row; i++)
{
for(int j = 0; j < 11; j++)
{
for(int k = j; k < j+5; k++)
{
winlistp[num].x[k-j] = i;
winlistp[num].y[k-j] = k;
winlistc[num].x[k-j] = i;
winlistc[num].y[k-j] = k;
winlistp[num].last = 0;
winlistp[num].wn[k-j] = 0;
winlistc[num].last = 0;
winlistc[num].wn[k-j] = 0;
}
num++;
}
}
//
for(int i = 0; i < Coloum; i++)
{
for(int j = 0; j < 11; j++)
{
for(int k = j; k < j+5; k++)
{
winlistp[num].x[k-j] = k;
winlistp[num].y[k-j] = i;
winlistc[num].x[k-j] = k;
winlistc[num].y[k-j] = i;
winlistp[num].last = 0;
winlistp[num].wn[k-j] = 0;
winlistc[num].last = 0;
winlistc[num].wn[k-j] = 0;
}
num++;
}
}
//
for(int i = 1; i < 11; i++)
{
for(int x = i,y = 0; x < 11; x++,y++)
{
for(int kx = x,ky = y; kx < x+5; kx++,ky++)
{
winlistp[num].x[kx-x] = ky;
winlistp[num].y[kx-x] = kx;
winlistc[num].x[kx-x] = ky;
winlistc[num].y[kx-x] = kx;
winlistp[num].last = 0;
winlistp[num].wn[kx-x] = 0;
winlistc[num].last = 0;
winlistc[num].wn[kx-x] = 0;
}
num++;;
}
}
//
for(int i = 1; i < 11; i++)
{
for(int y = i,x = 0; y < 11; y++,x++)
{
for(int kx = x,ky =y; ky < y+5; kx++,ky++)
{
winlistp[num].x[kx-x] = ky;
winlistp[num].y[kx-x] = kx;
winlistc[num].x[kx-x] = ky;
winlistc[num].y[kx-x] = kx;
winlistp[num].last = 0;
winlistp[num].wn[kx-x] = 0;
winlistc[num].last = 0;
winlistc[num].wn[kx-x] = 0;
}
num++;
}
}
コードは長いですが難しくないので、一部貼っておきますが、分かったら残りのコードは自分で補うのは絶対に問題ありません.コードを見てみると、すべての勝った状況を列挙していることが明らかになるはずです.それぞれ横方向と縦方向、斜め方向の2つで、forサイクルで直接すべて初期化できます.score配列の初期化はもちろん0である.
では、winlist配列をどのように更新するかは簡単です.白棋を更新すると、碁盤を回って黒棋の位置を探して、winlist表を回って、この黒棋の座標がどのような状況に含まれているかを見て、この状況は無効になります.コードを貼ります.
//
public void update(int sitx,int sity)
{
if(array[sitx][sity]%2 == 0)
{
for(int i = 0; i < num; i++)
{
if(winlistp[i].last == 0)
{
for(int j = 0; j < 5; j++)
{
if((winlistp[i].x[j] == sitx) && (winlistp[i].y[j] == sity))
{
winlistp[i].last = 1;
break;
}
}
}
if(winlistc[i].last == 0)
{
for(int j = 0; j < 5; j++)
{
if((winlistc[i].x[j] == sitx) && (winlistc[i].y[j] == sity))
{
winlistc[i].wn[j] = 1;
break;
}
}
}
}
}else
{
for(int i = 0; i < num; i++)
{
if(winlistc[i].last == 0)
{
for(int j = 0; j < 5; j++)
{
if((winlistc[i].x[j] == sitx) && (winlistc[i].y[j] == sity))
{
winlistc[i].last = 1;
}
}
}
if(winlistp[i].last == 0)
{
for(int j = 0; j < 5; j++)
{
if((winlistp[i].x[j] == sitx) && (winlistp[i].y[j] == sity))
{
winlistp[i].wn[j] = 1;
}
}
}
}
}
私の言うとおりにコードを見に行くのは簡単ではないでしょうか.
では、次にscore配列を更新する方法についてお話しします.この座標がwinlistに含まれている場合が多ければ多いほど、将棋のこの位置での使い道が大きくなるのは明らかです.これは一つの側面ですが、なぜwinlistにはwn配列があるのでしょうか.それは3つの駒がつながっているかどうかを判断することです.4つの駒がつながっています??などなど.重み値なので、それぞれの状況には一定の数値が必要です.例えば、生きているうちに大きくなったり、生きているうちに負けてしまったりして、重み値がどのように確かに大きな影響を与えたのか、自分では今まで良い分配方法が見つかりませんでした.これはどのようにみんなに自分で决めるようにしましょう、残りの私は多く言わないで、毎回更に権値のリストを行って、最大の位置を选んで碁を打つのがよくて、しかしすべての情况をすべて考虑したため、前に1人が言ったことがあって、もしコンピュータの先手は胜つことを保证することができないならばしかし负けないことができます.ハハハしかし、私が実現していないこの程度は、やはり強化しなければなりません.その五つの碁はここまでだ.