| 作业:五子棋游戏开发 |
|
项目要求: 使用图像化界面完成五子棋 (人人对战): 可以使用EasyX框架(简单)或者Qt(复杂一点) 功能要求:
程序要求:
|
github路径:xuanmiao363/QtProject: Qt项目QtProject/五子棋
1、绘制棋盘
(1) 创建空白主窗口
Application --->Qt Widget Application ---> 设置项目名称和路径 ---> 基类选择QMainwindow

|
(2) 创建棋盘类

1、新建棋盘类:chessboard.h 、 chessboard.cpp
2、棋盘类中添加绘画事件成员函数,在cpp文件中实现绘画事件函数
创建画家对象,通过画家抗锯齿、设置棋盘背景颜色、画棋盘线
protected:
void paintEvent(QPaintEvent *event) override;
void ChessBoard::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
/* 创建画家对象 */
QPainter painter(this); //此处需要#include <QPainter>
/* 抗锯齿 */
painter.setRenderHint(QPainter::Antialiasing);
/* 设置棋盘颜色 */
QColor background = QColor(205, 175, 149);
painter.fillRect(rect(), background);
/* 划棋盘线,常量boardSize、margin和cellSize定义在ChessBoard类中*/
for(int iLoop=0; iLoop<boardSize; iLoop++)
{
painter.drawLine(margin, margin + iLoop*cellSize,
margin+(boardSize-1)*cellSize, margin +iLoop*cellSize);
painter.drawLine(margin + iLoop*cellSize, margin,
margin+iLoop*cellSize, margin + (boardSize-1)*cellSize);
}
}
3、在mainwindow类的构造函数中实例化棋盘对象、设置棋盘布局,窗口名称和大小
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
/* 设置mainwindow窗口大小和名称*/
setFixedSize(800,660);
setWindowTitle("五子棋");
/* 棋盘对象 */
chessBoard = new ChessBoard(this);
/*设置棋盘布局*/
QWidget *centerWidget = new QWidget();
setCentralWidget(centerWidget);
QBoxLayout *layout = new QVBoxLayout(centerWidget);
layout->addWidget(chessBoard);
}
2、绘制悬停点
(1) 初步绘制悬停点
/* 鼠标移动事件函数 */
void ChessBoard::mouseMoveEvent(QMouseEvent *event)
{
/* 计算格子交叉点位置,hoverRow和hoverCol定义在chessboard.h文件中 */
hoverRow = (event->x() - margin) / cellSize;
hoverCol = (event->y() - margin) / cellSize;
/* 手动触发绘画事件 */
update();
}
在棋盘类构造函数中设置鼠标追踪为true
ChessBoard::ChessBoard(QWidget *parent) : QWidget(parent)
{
/* 设置鼠标追踪为true */
setMouseTracking(true);
}
void ChessBoard::paintEvent(QPaintEvent *event)
{
xxx
xxx
xxx
/* 绘制悬停点 */
painter.setBrush(Qt::blue);
painter.drawEllipse(QPoint(margin + hoverRow*cellSize, margin + hoverCol*cellSize),
cellSize/5, cellSize/5);
}
(2) 改进绘制悬停点
void ChessBoard::mouseMoveEvent(QMouseEvent *event)
{
/* 计算格子交叉点位置 */
if(event->x() > margin - cellSize/2 &&
event->y() > margin - cellSize/2 )
{
// hoverRow,hoverCol,hoverFlag在棋盘类中定义
hoverRow = (event->x() - margin + cellSize/2) / cellSize;
hoverCol = (event->y() - margin+ cellSize/2) / cellSize;
}
else
{
hoverRow = -1;
hoverCol = -1;
}
/* 手动触发绘画事件 */
if( ((0<=hoverRow) && (hoverRow < boardSize)) &&
((0<=hoverCol) && (hoverCol < boardSize)))
{
hoverFlag = true;
update();
}
else
{
hoverFlag = false;
update();
}
}
void ChessBoard::paintEvent(QPaintEvent *event)
{
xxx
xxx
xxx
/* 绘制悬停点 */
if( ((0<=hoverRow) && (hoverRow < boardSize)) &&
((0<=hoverCol) && (hoverCol < boardSize)) &&
(hoverFlag == true))
{
painter.setBrush(Qt::black);
painter.drawEllipse(QPoint(margin + hoverRow*cellSize, margin + hoverCol*cellSize),
cellSize/4, cellSize/4);
}
}
3、选择玩家
(1)新建玩家类:player.h 、 player.cpp
(2)player.h在类中声明PushButton对象,并增加对应的槽函数
class Player : public QWidget
{
Q_OBJECT
public:
explicit Player(QWidget *parent = nullptr);
private:
QPushButton *btn1;
QPushButton *btn2;
signals:
/* 按钮按下的槽函数 */
public slots:
void btn1Clicked();
void btn2Clicked();
};
(3)player.cpp在构造函数中设置黑棋和白棋按钮,并且设置信号槽函数连接
#include "player.h"
#include <QDebug>
Player::Player(QWidget *parent) : QWidget(parent)
{
/* 设置黑棋按钮 */
btn1 = new QPushButton;
btn1->setParent(parent);
btn1->setText("黑棋");
QPalette palette1 = btn1->palette();
palette1.setColor(QPalette::ButtonText, QColor(255, 255, 255));
palette1.setColor(QPalette::Button, QColor(0, 0, 0));
btn1->setPalette(palette1);
btn1->move(350, 20);
btn1->resize(100,50);
btn1->setEnabled(true);
/* 设置白棋按钮 */
btn2 = new QPushButton;
btn2->setParent(parent);
btn2->setText("白棋");
QPalette palette2 = btn2->palette();
palette2.setColor(QPalette::ButtonText, QColor(0, 0, 0));
palette2.setColor(QPalette::Button, QColor(255, 255, 255));
btn2->setPalette(palette2);
btn2->move(350, 700);
btn2->resize(100,50);
btn2->setEnabled(true);
// 连接按钮的点击信号到自定义信号
connect(btn1, &QPushButton::clicked, this, &Player::btn1Clicked);
connect(btn2, &QPushButton::clicked, this, &Player::btn2Clicked);
}
在chessboard.cpp文件中设置pushbutton的槽函数,设置FlagBlack和FlagWhite标记
/* PushButton的槽函数 */
void Player::btn1Clicked()
{
FlagBlack = 1;
FlagWhite = 0;
update();
}
void Player::btn2Clicked()
{
FlagBlack = 0;
FlagWhite = 1;
update();
}
4、绘制棋子
(1) 棋盘构造函数中初始化棋子
/* 构造函数 */
ChessBoard::ChessBoard(QWidget *parent) : QWidget(parent)
{
/* 设置鼠标追踪为true */
setMouseTracking(true);
/* 初始化棋子 */
for(int iLoop=0; iLoop<boardSize; iLoop++ )
{
for(int jLoop=0; jLoop<boardSize; jLoop++)
{
boardArray[iLoop][jLoop] = EMPTY;
}
}
}
(2)在chessboard.h文件中增加鼠标点击事件成员函数,在chessboard.cpp文件中实现
protected:
void mousePressEvent(QMouseEvent *event) override;
/* 鼠标点击事件函数 */
void ChessBoard::mousePressEvent(QMouseEvent *event)
{
hoverRow = (event->x() - margin + cellSize/2) / cellSize; //计算当前下棋位置
hoverCol = (event->y() - margin+ cellSize/2) / cellSize; //计算当前下棋位置
qDebug() << "FlagBlack=" << FlagBlack <<endl; // FlagBlack是表示下黑棋
qDebug() << "FlagWhite=" << FlagWhite <<endl; // FlagWhite是表示下白棋
if( ((0<=hoverRow) && (hoverRow < boardSize)) &&
((0<=hoverCol) && (hoverCol < boardSize)) &&
(FlagBlack == 1))
{
if(boardArray[hoverRow][hoverCol] != EMPTY)
{
QMessageBox::information(this, "错误", "此处已经有棋子了");
return;
}
boardArray[hoverRow][hoverCol] = BLACKSIDE;
update();
}
else if(((0<=hoverRow) && (hoverRow < boardSize)) &&
((0<=hoverCol) && (hoverCol < boardSize)) &&
(FlagWhite == 1))
{
if(boardArray[hoverRow][hoverCol] != EMPTY)
{
QMessageBox::information(this, "错误", "此处已经有棋子了");
return;
}
boardArray[hoverRow][hoverCol] = WHITESIDE;
update();
}
}
/* 棋盘绘画事件 */
void ChessBoard::paintEvent(QPaintEvent *event)
{
xxx
xxx
xxx
/* 绘制棋子 */
for(int iLoop=0; iLoop<boardSize; iLoop++ )
{
for(int jLoop=0; jLoop<boardSize; jLoop++ )
{
if (boardArray[iLoop][jLoop] == WHITESIDE)
{
painter.setBrush(Qt::white);
painter.drawEllipse(QPoint(margin + iLoop*cellSize, margin + jLoop*cellSize),
cellSize/3, cellSize/3);
}
else if(boardArray[iLoop][jLoop] == BLACKSIDE)
{
painter.setBrush(Qt::black);
painter.drawEllipse(QPoint(margin + iLoop*cellSize, margin + jLoop*cellSize),
cellSize/3, cellSize/3);
}
}
}
}
5、判定胜负
(1)在chessboard.h的ChessBoard类中增加判定胜负的成员函数
class ChessBoard : public QWidget
{
xxx
xxx
xxx
private:
xxx
xxx
xxx
bool bIsCheckBlackWin(int row, int col);
bool bIsCheckWhiteWin(int row, int col);
signals:
};
(2)实现判定胜负函数
/* 检测白方棋子是否获胜 */
bool ChessBoard::bIsCheckWhiteWin(int row, int col)
{
for(int i=1; i<5; i++)
{
if( boardArray[row+i][col] == WHITESIDE)
{
qDebug()<<"右侧棋子是白色的"<< endl;
WHITECNTRIGHT++;
}
else
{
break;
}
}
for(int i=1; i<5; i++)
{
if( boardArray[row-i][col] == WHITESIDE)
{
qDebug()<<"左侧棋子是白色的"<< endl;
WHITECNTLEFT++;
}
else
{
break;
}
}
for(int i=1; i<5; i++)
{
if( boardArray[row][col+i] == WHITESIDE)
{
qDebug()<<"上侧棋子是白色的"<< endl;
WHITECNTUP++;
}
else
{
break;
}
}
for(int i=1; i<5; i++)
{
if( boardArray[row][col-i] == WHITESIDE)
{
qDebug()<<"下侧棋子是白色的"<< endl;
WHITECNTDOWN++;
}
else
{
break;
}
}
for(int i=1; i<5; i++)
{
if( boardArray[row+i][col+i] == WHITESIDE)
{
qDebug()<<"右上侧棋子是白色的"<< endl;
WHITECNTRIGHTUP++;
}
else
{
break;
}
}
for(int i=1; i<5; i++)
{
if( boardArray[row-i][col-i] == WHITESIDE)
{
qDebug()<<"左下侧棋子是白色的"<< endl;
WHITECNTLEFTDOWN++;
}
else
{
break;
}
}
for(int i=1; i<5; i++)
{
if( boardArray[row+i][col-i] == WHITESIDE)
{
qDebug()<<"右下侧棋子是白色的"<< endl;
WHITECNTRIGHTDOWN++;
}
else
{
break;
}
}
for(int i=1; i<5; i++)
{
if( boardArray[row-i][col+i] == WHITESIDE)
{
qDebug()<<"左上侧棋子是白色的"<< endl;
WHITECNTLEFTUP++;
}
else
{
break;
}
}
qDebug()<<"右侧棋子个数"<< WHITECNTRIGHT << endl;
qDebug()<<"左侧棋子个数"<< WHITECNTLEFT << endl;
qDebug()<<"上侧棋子个数"<< WHITECNTUP << endl;
qDebug()<<"下侧棋子个数"<< WHITECNTDOWN << endl;
qDebug()<<"右下侧棋子个数"<< WHITECNTRIGHTUP << endl;
qDebug()<<"左上侧棋子个数"<< WHITECNTLEFTDOWN << endl;
qDebug()<<"左下侧棋子个数"<< WHITECNTLEFTUP << endl;
qDebug()<<"右上侧棋子个数"<< WHITECNTRIGHTDOWN << endl;
if( (WHITECNTRIGHT + WHITECNTLEFT + 1 >= 5) ||
(WHITECNTUP + WHITECNTDOWN + 1 >= 5) ||
(WHITECNTRIGHTUP + WHITECNTLEFTDOWN + 1 >= 5) ||
(WHITECNTLEFTUP + WHITECNTRIGHTDOWN + 1 >= 5))
{
ret = true;
}
else
{
ret = false;
}
WHITECNTRIGHT = 0;
WHITECNTLEFT = 0;
WHITECNTUP = 0;
WHITECNTDOWN = 0;
WHITECNTRIGHTUP = 0;
WHITECNTLEFTDOWN = 0;
WHITECNTRIGHTDOWN = 0;
WHITECNTLEFTUP = 0;
return ret;
}
实现效果:

Qt五子棋实现
浙公网安备 33010602011771号