📄 gobangplayer.cpp
字号:
//gobangPlayer.cpp
#include "gobangPlayer.h"
#include "chessboard.h"
#include <cctype>
chessboard gobangPlayer::m_chessboard;
unsigned int gobangPlayer::count=0;
// static 类型, 独立初始化
gobangPlayer::gobangPlayer()
{
m_chessmanColor=black;
m_Move=point(0,0);
}
gobangPlayer::~gobangPlayer()
{
}
void gobangPlayer::setChessmanColor( states color)
{
m_chessmanColor=color;
}
void gobangPlayer::setMove(char x, char y)
{
isdigit(x) ? m_Move.x=x-'0'-1 : m_Move.x=toupper(x)-'A'+9;
isdigit(y) ? m_Move.y=y-'0'-1 : m_Move.y=toupper(y)-'A'+9;
}
// 要是char x 为'0'-'9', x-'0'返回字符相对应的int 类型的数字, 因为在ASCII码表中
// 连续排列, C\C++中数组坐标从0开始, 所以要减1.
// 不是'0'-'9',要是输入合法,就一定是字母, 先返回对应的大写值,这样就可以同时
// 支持大小写输入 减去'A',因为'A'就代表10,再考虑数组从0开始,
// 应该是 toupper(x)-'A'+10-1 就是toupper(x)-'A'+9
void gobangPlayer::getMove(char &x, char &y)
{
m_Move.x<9 ? x=('1'+m_Move.x) : x=('A'+m_Move.x-9);
m_Move.y<9 ? y=('1'+m_Move.y) : y=('A'+m_Move.y-9);
}
// 上面对应的逆过程
bool gobangPlayer::checkMove()
{
bool result=true;
if( m_Move.x<0 || m_Move.x>size )
result=false;
if( m_Move.y<0 || m_Move.y>size )
result=false;
// 输入的棋步不在棋盘上
if( m_chessboard.getGridState(m_Move)!=blank )
result=false;
// 虽然在棋盘上,不过棋盘上已经有了棋子
if( result==true )
m_chessboard.setGridState(m_Move,m_chessmanColor);
// 要是输入的棋步合法,就更改棋盘的状态,表示在上面下棋子
return result;
}
void gobangPlayer::autoMove()
{
m_chessboard.updateMarks(m_chessmanColor);
m_chessboard.getMaxGridMark(m_Move);
m_chessboard.setGridState(m_Move,m_chessmanColor);
// 电脑自动下棋: 先更新整个棋盘的格子的分数,找到分数最高的,
// 接着在上面下子
}
bool gobangPlayer::isWin()
{
int count=0;
int i,j,k;
for( k=1; k<=8; k++ ) // 有八个方向需要扫描
// 上, 下, 右, 左, 左斜下, 右斜上, 右斜下, 左斜上
{
i=m_Move.x;
j=m_Move.y; // 取得刚下棋步的坐标, 因为是不是胜利, 总是和刚下的棋
// 有关
if( k%2==1)
count=0;
// 扫描的时候要考虑向左,和向右的情况, 比如向左知道有2个相同
// 向右又有两个相同的棋子, 向左向有在同一直线上,加上
// 刚下的, 就有五个棋子, 5子连线就胜了.
// count是用来表示同一直线上相连棋子的数目的, count==4时,就赢了
// 刚才已经说过, 假如先向左扫描, 得到相连棋子的数目, 再向右扫描时,
// 在左边的棋子还会起作用, 因为他们是在同一直线上的
// 跟着,扫描另外一条直线的时候, count就应该重新为0, 比如说, 横的直线
// 不会影响竖的直线. 一条直线扫描两次. 所以k%2==1, count=0
//
while( 1 )
{
switch( k )
{
case 1: i++; break; // 向上
case 2: i--; break; // 向下
case 3: j++; break; // 向右
case 4: j--; break; // 向左
case 5: i--; j--; break; // 左斜上
case 6: i++; j++; break; // 右斜下
case 7: i++; j--; break; // 左斜上
case 8: i--; j++; break;
}
// case 语句的顺序不能顺便掉转, 一定要保证同一直线连续扫描两次
if( i>=0 && i<size && j>=0 && j<size )
{
if( m_chessboard.getGridState(point(i,j))==m_chessmanColor )
count++;
else break;
}
else break;
// 已经超出棋盘范围, 跳出while循环,扫描下一个方向
if( count==4 )
return true; // count==4, 就表示胜利
}
}
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -