⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 board.cpp

📁 在linux下使用qt来开发的五子棋
💻 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 + -