图6 拒绝悔棋 Figure 6 refuse to calculate
7.2.6 和棋消息——MSG_DRAW
表明对方请求和棋,除uMsg成员外其余成员皆无效。接到这个消息后,会弹出MessageBox询问是否接受对方的请求(如图7所示),并根据玩家的选择回返MSG_AGREEDRAW或MSG_REFUSEDRAW消息。另外,在发送这个消息之后,主界面上的某些元素将不再响应用户的操作。
图7 请求和棋
Figure 7 request for a draw in chess
7.2.7 同意和棋消息——MSG_AGREEDRAW
表明对方接受了玩家的和棋请求(如图8所示),除uMsg成员外其余成员皆无效。接到这个消息后,双方和棋。
图8 同意和棋
Figure 8 agree to a draw in chess
7.2.8 拒绝和棋消息——MSG_REFUSEDRAW
表明对方拒绝了玩家的和棋请求(如图9所示),除uMsg成员外其余成员皆无
- 13 -
效。接到这个消息后,整个界面将恢复发送和棋请求前的状态。
图9 拒绝和棋
Figure 9 refused a draw in chess
7.2.9 认输消息——MSG_GIVEUP
表明对方已经投子认输(如图10所示),除uMsg成员外其余成员皆无效。接到这个消息后,整个界面将转换为胜利后的状态。
图10 认输 Figure 10 Lose
7.2.10 对方信息消息——MSG_INFORMATION
用来获取对方玩家的姓名,szMsg表示对方的姓名,其余成员无效。在开始游戏的时候,由客户端向服务端发送这条消息,服务端接到后设置对方的姓名,并将自己的姓名同样用这条消息回发给客户端。 7.2.11 再次开局消息——MSG_PLAYAGAIN
表明对方希望开始一局新的棋局,除uMsg成员外其余成员皆无效。接到这个消息后,会弹出MessageBox询问是否接受对方的请求(如图11所示),并根据玩家的选择回返MSG_AGREEAGAIN消息或直接断开网络。
- 14 -
图11 再次开局 Figure 11 start again
7.2.12 同意再次开局消息——MSG_AGREEAGAIN
表明对方同意了再次开局的请求,除uMsg成员外其余成员皆无效。接到这个消息后,将开启一局新游戏。
8 主要算法
无论是人机对弈,还是网络对弈,都需要合理算法的支持,本节中将详细介绍五子棋中使用的算法。
8.1 判断胜负
五子棋的胜负,在于判断棋盘上是否有一个点,从这个点开始的右、下、右下、左下四个方向是否有连续的五个同色棋子出现,如图12:
图12 判断胜负方向
Figure 12 judging the outcome direction
这个算法也就是CTable的Win成员函数。从设计的思想上,需要它接受一个棋子颜色的参数,然后返回一个布尔值,这个值来指示是否胜利,代码如下: BOOL CTable::Win( int color ) const {
int x, y;
for ( y = 0; y < 15; y++ ) // 判断横向 {
for ( x = 0; x < 11; x++ ) {
if ( color == m_data[x][y] &&
- 15 -
color == m_data[x + 1][y] &&
color == m_data[x + 2][y] &&
color == m_data[x + 3][y] &&
color == m_data[x + 4][y] ) {
return TRUE; } } }
for ( y = 0; y < 11; y++ ) // 判断纵向 {
for ( x = 0; x < 15; x++ ) {
if ( color == m_data[x][y] &&
color == m_data[x][y + 1] &&
color == m_data[x][y + 2] &&
color == m_data[x][y + 3] &&
color == m_data[x][y + 4] ) {
return TRUE; } } }
for ( y = 0; y < 11; y++ ) // 判断“\\”方向 {
for ( x = 0; x < 11; x++ ) {
if ( color == m_data[x][y] &&
color == m_data[x + 1][y + 1] &&
color == m_data[x + 2][y + 2] &&
color == m_data[x + 3][y + 3] &&
- 16 -
color == m_data[x + 4][y + 4] ) {
return TRUE; } } }
for ( y = 0; y < 11; y++ ) // 判断“/”方向 {
for ( x = 4; x < 15; x++ ) {
if ( color == m_data[x][y] &&
color == m_data[x - 1][y + 1] &&
color == m_data[x - 2][y + 2] &&
color == m_data[x - 3][y + 3] &&
color == m_data[x - 4][y + 4] ) {
return TRUE; } } }
return FALSE; // 不满足胜利条件 }
由于这个算法所遵循的搜索顺序是从左到右、自上而下,因此在每次循环的时候,都有一些坐标无需纳入考虑范围。例如对于横向判断而言,由于右边界所限,因而所有横坐标大于等于11的点,都构不成五子连的条件,所以横坐标的循环上界也就定为11,这样也就提高了搜索的速度。
8.2 人机对弈算法
人机对弈算法完全按照CGame基类定义的接口标准,封装在了COneGame派生类之中。下面将对这个算法进行详细地介绍。 8.2.1 获胜组合
获胜组合是一个三维数组,它记录了所有取胜的情况。也就是说,参考于
- 17 -