for ( i = 0; i < 572; i++ )
{
// 修改状态变化
if ( m_Player[stepPut.x][stepPut.y][i] &&
m_Win[0][i] != -1 )
m_Win[0][i]++;
if ( m_Computer[stepPut.x][stepPut.y][i] )
{
m_Computer[stepPut.x][stepPut.y][i] = false;
m_Win[1][i] = -1;
}
}
6.2.3 查找棋盘空位
在计算机落子之前,需要查找棋盘的空位,所以需要一个SearchBlank成员函数完成此项工作,此函数需要进行不重复的查找,也就是说,对已查找过的空位进行标记,并返回找到空位的坐标,其代码如下:
bool COneGame::SearchBlank( int &i, int &j,
int nowTable[][15] )
{
int x, y;
for ( x = 0; x < 15; x++ )
{
for ( y = 0; y < 15; y++ )
{
if ( nowTable[x][y] == -1 && nowTable[x][y] != 2 )
{
i = x;
j = y;
return true;
}
}
}
return false;
}
6.2.4 落子打分
找到空位后,需要对这个点的落子进行打分,这个分数也就是这个坐标重要性的体现,代码如下:
int COneGame::GiveScore( const STEP& stepPut )
{
int i, nScore = 0;
for ( i = 0; i < 572; i++ )
{
if ( m_pTable->GetColor() == stepPut.color )
{
// 玩家下
if ( m_Player[stepPut.x][stepPut.y][i] )
{
switch ( m_Win[0][i] )
{
case 1:
nScore -= 5;
break;
case 2:
nScore -= 50;
break;
case 3:
nScore -= 500;
break;
case 4:
nScore -= 5000;
break;
default:
break;
}
}
}
else
{
// 计算机下
if ( m_Computer[stepPut.x][stepPut.y][i] )
{
switch ( m_Win[1][i] )
{
case 1:
nScore += 5;
break;
case 2:
nScore += 50;
break;
case 3:
nScore += 100;
break;
case 4:
}
}
return nScore;
}
如代码所示,考虑到攻守两方面的需要,所以将玩家落子给的分数置为负值。
6.2.5 防守策略
落子的考虑不单单要从进攻考虑,还要从防守考虑。这一细节的实现其实就是让计算机从玩家棋盘布局分析战况,然后找出对玩家最有利的落子位置。整个过程如下:
for ( m = 0; m < 572; m++ )
{
// 暂时更改玩家信息
if ( m_Player[i][j][m] )
{
temp1[n] = m;
m_Player[i][j][m] = false;
}
ptempTable[i][j] = 0;
pi = i;
pj = j;
while ( SearchBlank( i, j, ptempTable ) )
if ( pscore > ptemp ) // 此时为玩家下子,运用极小极大法时应选取最小值
pscore = ptemp;
}
for ( m = 0; m < n; m++ )
{
// 恢复玩家信息
m_Player[pi][pj][temp1[m]] = true;
m_Win[0][temp1[m]] = temp2[m];
}
6.2.6 选取最佳落子
在循环结束的时候,就可以根据攻、守两方面的打分综合地考虑落子位置了。代码如下:
if ( ctemp + pscore > cscore )
{
cscore = ctemp + pscore;
bestx = pi;
besty = pj;
}
在这之后,重新改变一下棋盘的状态(6.2.2)即可。
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ... 下一页 >>