// Think_W() 関数を定義した Think.cs
using System;
using System.Collections;
using System.Windows.Forms;
using System.Diagnostics;
public partial class MyForm
{ int[,] m_vt = new int[8, 8] // 1-1, 2-2 は別途
{{ 0, -6, 4, 2, 2, 4, -6, 0 },
{ -6, 0, -2, -1, -1, -2, 0, -6 },
{ 4, -2, 0, 0, 0, 0, -2, 4 },
{ 2, -1, 0, 0, 0, 0, -1, 2 },
{ 2, -1, 0, 0, 0, 0, -1, 2 },
{ 4, -2, 0, 0, 0, 0, -2, 4 },
{ -6, 0, -2, -1, -1, -2, 0, -6 },
{ 0, -6, 4, 2, 2, 4, -6, 0 }};
int[,] t00 = new int[4, 2] //0-0 座標テーブル(Y,X)
{{ 0,0 }, { 0,7 }, { 7,7 }, { 7,0 }};
int[,] t11 = new int[4, 2] //1-1 座標テーブル(Y,X)
{{ 1,1 }, { 1,6 }, { 6,6 }, { 6,1 }};
int[,] dt = new int[4, 2] //上辺→,右辺↓,下辺←,左辺↑
{{ 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 }};
int[,] dt5 = new int[4, 2] //左上,右上,右下,左下
{{ 1, 1 }, { 1, -1 }, { -1, -1 }, { -1, 1 }};
// t[8][8] から辺を一列取り出す
ArrayList GetLine(int no, int[,] t)
{
ArrayList array= new ArrayList();
int xp,yp,k;
yp= t00[no,0];
xp= t00[no,1];
for(k=0; k<8; k++)
{ array.Add(t[yp,xp]);
yp+= dt[no,0];
xp+= dt[no,1];
}
return array;
}
// コーナ(黒or白)から展開する駒をカウント
int Corner(int no, int[,] t)
{ int x,y,xp,yp,cnt;
int koma;
yp = t00[no, 0];
xp = t00[no, 1];
if (t[yp, xp] == 0) return 0;
koma = t[yp, xp];
//コーナ(no)のt[8,8]をt55にコピー
int[,] t55 = new int[5, 5];
for(y=0, yp=t00[no, 0]; y<5; y++, yp+=dt5[no, 0])
{ for(x=0, xp=t00[no, 1]; x<5; x++, xp+=dt5[no, 1])
{ t55[y,x] = t[yp,xp]; }
}
//コーナの確定した石数を求める
cnt = 0;
xp = 4;
for(y=0; y<4 && t55[y,0]==koma; y++)
{ for(x=0; x<xp; x++)
{ if ((t55[y,x]!=koma) ||
(y>0 && x>0 && t55[y-1, x+1]!=koma && t55[y+1, x-1]!=koma))
{ xp=x; break; }
cnt++;
}
}
return cnt;
}
// 端の駒(黒or白)の立場で続く駒を評価
int EvEdge(ArrayList s, int bcnt, int wcnt, int scnt)
{
if (scnt<3) return 0;
if ((int)s[0]==1 && (int)s[1]==-1 && (int)s[2]==0 ) return wcnt*20; // [●○△・・・]
if ((int)s[0]==-1 && (int)s[1]==1 && (int)s[2]==0 ) return bcnt*20; // [○●△・・・]
return 0;
}
// 1-2 に駒(黒or白)があるとき(黒が有利なら+の値)
int EvPattern(ArrayList s, int sc)
{
if (sc == 4)
{ // [△○●・・・・] 黒(c)の手番で隅を取れる
if ((int)s[1]==-1 && (int)s[2]==1) return 50;
return 20; // 辺が全て黒になる[△●○・・・]
}
if ((int)s[1]==1) // 1-2 に黒 [△●・・・]
{
if ((int)s[2]==-1 && (int)s[3]==1) return -60; // [△●○●・・・]
if ((int)s[2]==-1 && (int)s[3]==0 && (int)s[4]==-1) return -40; // [△●○ ○・・・]
return 0;
}
if ((int)s[1] == -1) // 1-2 に白[△○・・・]
{
if ((int)s[2] == 1 && (int)s[3] == -1) return 60; // [△○●○・・・]
if ((int)s[2] == 0 && (int)s[3] == -1) return 20; // [△○※○・・・]
if ((int)s[2] == 0 && (int)s[3] == 0 && (int)s[4] == 1) return 30; //[△○※・●・・・]
if ((int)s[2] == 0 && (int)s[3] == 1 && (int)s[4] == -1) return 30; //[△○※●○・・・]
}
return 0;
}
// ●の手番(立場)で取り出した1列の辺を評価(黒が有利なら+)
int EvLine(ArrayList s)
{
ArrayList ws= new ArrayList();
int bcnt, wcnt, scnt, rt, val, wk;
// 黒石, 白石, 列の数をカウント
bcnt = wcnt = 0;
scnt = 1;
wk = (int)s[0];
foreach(int DAT in s)
{
if (DAT==1) bcnt++;
if (DAT==-1) wcnt++;
if (DAT != wk)
{
scnt++;
wk = DAT;
}
}
if (bcnt+wcnt==8) return (bcnt-wcnt)*20;
if (scnt<3) return 0;
//連続する(○,●)を一つに詰める
wk = 9;
foreach (int DAT in s)
{
if (DAT == 0 || DAT != wk)
{
ws.Add(DAT);
wk = DAT;
}
}
rt= ws.Count-1;
// 端に黒(白)が置かれている
if ((int)ws[0] != 0)
{
val = EvEdge(ws, bcnt, wcnt, scnt);
if ((int)ws[0]==1) return val;
else return(0-val);
}
if ((int)ws[rt]!=0)
{
ws.Reverse();
val = EvEdge(ws, bcnt, wcnt, scnt);
if ((int)ws[0]==1) return val;
else return(0-val);
}
// [△・・・△]
if (scnt==3) return (bcnt-wcnt)*10;
val= 0;
// 1-2 に駒 [△*・・・△]
if ((int)ws[1]!=0 || (int)ws[rt-1]!=0)
{
if ((int)ws[1]!=0)
{
if ((int)ws[1]==-1) val+= EvPattern(ws,scnt);
else val-= EvPattern(ws,scnt);
}
if ((int)ws[rt-1]!=0)
{
ws.Reverse();
if ((int)ws[1]==-1) val+= EvPattern(ws, scnt);
else val-= EvPattern(ws, scnt);
}
}
// 両端は[△△・・・△△]
if (scnt==3) return (bcnt-wcnt)*10; //[△○△][△●△]
if (scnt==4) return (bcnt+wcnt)*10; //[△○●△]
return val;
}
// コンピュータ後手で列挙した手を実行して黒番で評価
int Eval_B(int[,] wt)
{ ArrayList line;
int x,y,val;
bool flg;
val= 0;
for(int i=0; i<4; i++)
{ y= t00[i,0];
x= t00[i,1];
if (wt[y,x]!=0) // Corner() 関数の評価
{ if (wt[y,x]==1) val+= Corner(i,wt)*20+30;
else val-= Corner(i,wt)*20+30;
}
else
{
flg = false;
if (Check(1,x,y,wt)) // 隅を取れる
{ val += 30;
flg = true;
}
if (flg==false)
{ y = t11[i, 0];
x = t11[i, 1];
if (wt[y,x]==-1) val += 20;
if (wt[y,x]==1) val -= 20;
}
line = GetLine(i, wt);
int wk= EvLine(line);
val += wk;
}
}
for(int i=0; i<8; i++)
{ for(int j=0; j<8; j++)
{ if (wt[i,j]==1) val+= m_vt[i,j];
if (wt[i,j]==-1) val-= m_vt[i,j];
}
}
return val;
}
//★ t[8,8] の局面を c の手番で最後まで読み切る
int Final(int lev, int c, int[,] t)
{
ArrayList array;
int[,] w_t;
int best,xy,i,ans;
int nc;
if (lev>20)
{ MessageBox.Show("Final Call Over Level");
return(Count(-1,t)-Count(1,t));
}
nc= 0-c;
array= Search(c, t);
if (array.Count==0)
{ array= Search(nc, t); // パスの時反転して検索
if (array.Count==0) // ゲーム終了まで到達
{
return(Count(-1,t)-Count(1,t));
}
return(Final(lev+1,nc,t)); //★反転して再起コール★
}
xy = 0;
best= 60000;
if (c==-1) best= -60000;
foreach(int DAT in array)
{
w_t = (int[,])t.Clone();
if (Reverse(c,DAT,w_t)==false)
{ T_Log(8,t);
MessageBox.Show("Final Reverce Error");
}
ans= Final(lev+1,nc,w_t); //★再起コール★
if (best<ans && c==-1)
{ best= ans;
xy= DAT;
}
if (best>ans && c==1)
{ best= ans;
xy= DAT;
}
}
array.Clear();
if (lev==0) m_pos= xy; //lev=0 のとき必ずここを通る
return best;
}
// 白番で手を列挙して、実行した局面を黒番で評価し、最小値を求める
int Think_W(int[,] t)
{
ArrayList array;
int[,] w_t;
int val,pos,wk,i;
i= Count(0,t);
if (i<14)
{
string str = DateTime.Now.ToString();
this.Text = str;
Final(0,-1,t);
str += " END:" + DateTime.Now.ToString();
this.Text = str;
System.Media.SystemSounds.Asterisk.Play();
return m_pos;
}
val= 10000;
array= Search(-1, t);
if (array.Count==0)
{ MessageBox.Show("コンピューターがプレイ出来ません");
return 99;
}
pos = 99;
foreach(int DAT in array)
{ w_t= (int[,])t.Clone();
Reverse(-1,DAT,w_t);
wk= Eval_B(w_t);
if (val>wk)
{ val = wk;
pos = DAT;
}
}
return pos;
}
}
|