📄 board.cpp
字号:
#include <QtGui>
#include <qmessagebox.h>
#include <qtextcodec.h> //显示中文必需
#include "myQFrame.h"
#include "board.h"
#include "chess.h"
#include "chessblack.h"
#include "chesswhite.h"
#include "arithmetic.h"
#include "node.h"
#include "GobangFrom.h"
#include <QWidget>
Board::Board(Board *parent) //构造棋盘
: QWidget(parent)
{
//setFrameStyle(QFrame::Sunken | QFrame::StyledPanel);
//setAcceptDrops(true);
boardIcon = new QLabel(this);
boardIcon->setPixmap(QPixmap(":/images/board.bmp")); //画棋盘
boardIcon->move(6.5, 6.5);
boardIcon->show();
boardIcon->setAttribute(Qt::WA_DeleteOnClose);
newchess = NULL;
for( int i = 0; i < 225; grid[i] = NULL, i++ ); //把指针数组置null,用以判断某位置是否有棋子,置null防止出错
for( int i=0; i<15; i++) //棋子数组初始化
{
for( int j=0; j<15; j++)
{
realgrid[i][j] = NULL;
}
}
//存棋子顺序的变量和数组初始化
whosturn = 0;
for( int i=0; i<15; i++)
{
for( int j=0; j<15; j++)
{
order[i][j] = 0;
}
}
//根据主菜单或按钮由参与者选择
robotcolor = 'W'; //默认机器人为白棋,
choosecolor = 'B'; //默认棋手选了黑棋
chessnow = 'B'; //下黑棋
victory = false;
//test,先安一粒棋子在中央
//newchess = new ChessWhite( (7 + 1) * 35 + 12.5, (7 + 1) * 35 + 12.5, this );
//newchess->DrawChess( (7 + 1) * 35 + 12.5, (7 + 1) * 35 + 12.5 );
}
Board:: ~Board()
{
delete boardIcon;
for( int i = 0; i < 225; i++ )
{
if( grid[i] != NULL )
{
delete grid[i];
}
}
for( int i=0; i<15; i++) //棋子数组初始化
{
for( int j=0; j<15; j++)
{
realgrid[i][j] = NULL;
}
}
}
char Board::clstab() //类型标识
{
return NULL; // 1 标识为棋盘
}
/* 棋盘重置 */
/* 删除所有棋子,并将chess指针数组置NULL */
void Board::InitializeBoard()
{
for( int i = 0; i < 225; i++ )
{
if( grid[i] != NULL )
{
delete grid[i];
}
}
for( int i = 0; i < 225; grid[i] = NULL, i++ );
for( int i=0; i<15; i++) //棋子数组初始化
{
for( int j=0; j<15; j++)
{
realgrid[i][j] = NULL;
}
}
//存棋子顺序的变量和数组初始化
whosturn = 0;
for( int i=0; i<15; i++)
{
for( int j=0; j<15; j++)
{
order[i][j] = 0;
}
}
victory = true; //胜利或重新开局标示,停止自动下棋
chessnow = 'B';
//电脑黑棋,电脑先手
if( robotcolor == 'B')
{
float y = ( 7 + 1 - 0.5 ) * 35 + 30;
float x = ( 7 + 1 - 0.5 ) * 35 + 30;
newchess = new ChessBlack( x, y, this ); //new棋子对象
newchess->DrawChess( x, y ); //画棋子
//chessnow换色
switch( chessnow ){
case 'B':
{
chessnow = 'W';
break;
}
default:
{
chessnow = 'B';
}
}
}
}
void Board::ChooseBlack()
{
choosecolor = 'B';
robotcolor = 'W';
chessnow = 'B';
//棋手为黑,先手,全部清干净
for( int i = 0; i < 225; i++ )
{
if( grid[i] != NULL )
{
delete grid[i];
}
}
for( int i = 0; i < 225; grid[i] = NULL, i++ );
for( int i=0; i<15; i++) //棋子数组初始化
{
for( int j=0; j<15; j++)
{
realgrid[i][j] = NULL;
}
}
//存棋子顺序的变量和数组初始化
whosturn = 0;
for( int i=0; i<15; i++)
{
for( int j=0; j<15; j++)
{
order[i][j] = 0;
}
}
}
void Board::ChooseWhite()
{
choosecolor = 'W';
robotcolor = 'B';
//存棋子顺序的变量和数组初始化
whosturn = 0;
for( int i=0; i<15; i++)
{
for( int j=0; j<15; j++)
{
order[i][j] = 0;
}
}
//电脑黑棋,电脑先手
float y = ( 7 + 1 - 0.5 ) * 35 + 30;
float x = ( 7 + 1 - 0.5 ) * 35 + 30;
//棋子先全部清干净
for( int i = 0; i < 225; i++ )
{
if( grid[i] != NULL )
{
delete grid[i];
}
}
for( int i = 0; i < 225; grid[i] = NULL, i++ );
for( int i=0; i<15; i++) //棋子数组初始化
{
for( int j=0; j<15; j++)
{
realgrid[i][j] = NULL;
}
}
newchess = new ChessBlack( x, y, this ); //new棋子对象
newchess->DrawChess( x, y ); //画棋子
//chessnow换色
chessnow = 'W';
}
/* 填完新棋子,按八个方向搜索棋盘,是否有五连 */
/* 作按8个方向,准备递归查找 */
/* newchess用引用传递 */
void Board::ScanBoard()
{
//下句为显示中文
QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
for(int i = 1; i < 5; i++ )
{
//计算某两个相对方向上相同棋子数,相加,4次循环,8个方向
int count = newchess->CheckStart(i) + newchess->CheckStart( 9 - i ); //1 左上, 9 - 1 = 8 右下
if( count >= 6 ) //新棋子按两个方向递归,自己加了两次
{
//victory = true;
//胜利对话框之前(下完棋),需要刷新,更改过期棋子的图片
RefreshChesspic();
QMessageBox messageBox(this);
QAbstractButton *initialize;
switch( chessnow ){
case 'B':
initialize = messageBox.addButton(tr(" Black Win! "), QMessageBox::ActionRole);
break;
case 'W':
initialize = messageBox.addButton(tr(" White Win! "), QMessageBox::ActionRole);
break;
}
messageBox.exec();
if (messageBox.clickedButton() == initialize)
{
/* 胜利对话框,跳出循环,棋盘重置,删除不用的指针和chess对象 */
InitializeBoard();
/* 初始化后,停止各个方向上的查找 */
break;
}
}
}
}
/* 点击鼠标,填新棋子 */
/* 1、填子是否有效 */
/* 2、控制黑白棋交替填子 */
void Board::mousePressEvent(QMouseEvent *event) //鼠标点击,画棋子
{
myQFrame *child = static_cast<myQFrame*>(childAt(event->pos()));
if (!child) //判断,如果点到了空面板,点击无效
return;
bool limit = Arithmetic::LimitArea(event->x(),event->y()); //判断,点击在无效区域(离落子点较远),点击无效
if (limit == false)
return;
int place = Arithmetic::ChessPlace(event->x(),event->y()); //判断,如果点击处已有棋子,点击无效
if (grid[place])
return;
victory = false; //鼠标点击后,标示位false,开始自动下棋
/* 黑白交替下棋 */
//棋手下棋
if( chessnow == choosecolor )
{
//下黑棋
if( chessnow == 'B' )
{
newchess = new ChessBlack( event->x(), event->y(), this );
}
//下白棋
else
{
newchess = new ChessWhite( event->x(), event->y(), this );
}
newchess->DrawChess( event->x(), event->y() );
ScanBoard();
//chessnow换色
//如果胜利了,ScanBoard后的初始化中已经开始下子,不用变色
if( victory != true )
{
switch( chessnow ){
case 'B':
{
chessnow = 'W';
break;
}
default:
{
chessnow = 'B';
}
}
}
}
//电脑自动下棋
/* 如果胜利,停止自动下棋*/
if( !victory )
{
//轮到机器下棋时,自动生成子节点并进行相应权值计算
if( chessnow == robotcolor )
{
MainNode mainnode(newchess->m, newchess->n, newchess); //根据刚下的(黑棋),相应的,生成一个黑棋节点,(树的第一层,主节点)
//subnode.AddSubNode();
mainnode.AddSubNode();
//根据位置算出坐标
float y = ( mainnode.bestm + 1 - 0.5 ) * 35 + 30;
float x = ( mainnode.bestn + 1 - 0.5 ) * 35 + 30;
//下黑棋
if( chessnow == 'B' )
{
newchess = new ChessBlack( x, y, this );
}
//下白棋
else
{
newchess = new ChessWhite( x, y, this );
}
newchess->DrawChess( x, y );
ScanBoard();
//chessnow换色
//如果胜利了,ScanBoard后的初始化中已经开始下子,不用变色
if( victory != true )
{
switch( chessnow ){
case 'B':
{
chessnow = 'W';
break;
}
default:
{
chessnow = 'B';
}
}
}
}
}
//下完棋,需要刷新,更改过期棋子的图片
RefreshChesspic();
}
void Board::RefreshChesspic()
{
int i,j;
int m1,n1;
int m2,n2;
int x1,y1;
int x2,y2;
//根据顺序,搜索位置,找到棋子指针
for( i=0; i<15; i++)
{
for( j=0; j<15; j++)
{
if(( order[i][j] == ( whosturn - 3)) && (( whosturn - 3 ) > 0 ))
{
m1 = i;
n1 = j;
x1 = (n1 ) * 35 + 12.5;
y1 = (m1 ) * 35 + 12.5;
grid[15 * m1 + n1]->DrawLaterChess( x1, y1 );
}
else if(( order[i][j] == ( whosturn - 2)) && (( whosturn - 2 ) > 0 ))
{
m2 = i;
n2 = j;
x2 = (n2 ) * 35 + 12.5;
y2 = (m2 ) * 35 + 12.5;
grid[15 * m2 + n2]->DrawLaterChess( x2, y2 );
}
}
}
}
//悔棋
void Board::Undo()
{
//当前没有棋子时,不允许悔棋,直接返回
if( whosturn == 0 || whosturn == 1 )
{
return;
}
int i,j;
int m1,n1;
int m2,n2;
int x1,y1;
int x2,y2;
int deletenum = 0;
//1、删掉最新的两粒棋子
for( i=0; i<15; i++)
{
for( j=0; j<15; j++)
{
if( order[i][j] == whosturn )
{
m1 = i;
n1 = j;
x1 = (n1 + 1) * 35 + 12.5;
y1 = (m1 + 1) * 35 + 12.5;
delete grid[15 * m1 + n1];
//对象删除后,指针要置为空
grid[15 * m1 + n1] = NULL;
order[m1][n1] = 0;
realgrid[m1][n1] = NULL;
deletenum++;
}
else if( (order[i][j] == ( whosturn - 1 )) && (( whosturn - 1 ) > 0 ))
{
m2 = i;
n2 = j;
x2 = (n2 + 1) * 35 + 12.5;
y2 = (m2 + 1) * 35 + 12.5;
delete grid[15 * m2 + n2];
//对象删除后,指针要置为空
grid[15 * m2 + n2] = NULL;
order[m2][n2] = 0;
realgrid[m2][n2] = NULL;
deletenum++;
}
}
}
//更新剩下的棋子的图片,最近的两个棋子图片更新,画成新棋子
m1=0;n1=0;m2=0;n2=0;
for( i=0; i<15; i++)
{
for( j=0; j<15; j++)
{
if( (order[i][j] == ( whosturn - 2 )) && (( whosturn - 2 ) > 0 ))
{
m1 = i;
n1 = j;
x1 = (n1 + 1) * 35 + 12.5;
y1 = (m1 + 1) * 35 + 12.5;
grid[15 * m1 + n1]->DrawChess( x1, y1 );
}
else if( (order[i][j] == ( whosturn - 3 )) && (( whosturn - 3 ) > 0) )
{
m2 = i;
n2 = j;
x2 = (n2 + 1) * 35 + 12.5;
y2 = (m2 + 1) * 35 + 12.5;
grid[15 * m2 + n2]->DrawChess( x2, y2 );
}
}
}
//删了几粒棋,棋子总数减几
whosturn = whosturn - deletenum;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -