文章目录
- 前言
- 一、游戏实现效果
- 二、需求分析
- 三、解决方案
- 四、核心步骤
- 1.插入棋盘图
- 2.双方落子
- 3.输赢判定
- 4.重新开始
- 五、完整源码
- 1.main.cpp
- 2.chessboard.h
- 3.chessboard.cpp
- 总结
前言
本篇,我们将使用QT实现一个人机对战的简易五子棋游戏,适合QT零基础和初学者进行学习。
一、游戏实现效果
- 这里的电脑为简单人机,没有采用特定的算法,因此没有防守功能,有兴趣的小伙伴可以自行拓展。
二、需求分析
- 项目开始前,需要我们对项目进行简单的需求分析,知道我们应该做些什么?
(1)在窗口背景插入棋盘图
(2)玩家鼠标点击棋盘某个区域落子
(3)电脑在棋盘上某个空白区域落子
(4)输赢判定,在棋盘的水平方向、垂直方向、对角线方向是否五子连珠
(5)清空棋盘,开始新一轮游戏
三、解决方案
- 完成需求分析后,需要针对每个需求思考相应的解决方案,确保项目的可行性。
(1)在窗口内创建一个QLabel类标签用来插入棋盘图
(2)使用鼠标点击事件函数,动态创建一个标签插入棋子图,并显示在鼠标的点击位置
(3)使用随机数生成函数,在随机生成的键盘某个区域位置,用同样的方法插入棋子图
(4)创建一个二维向量容器对应棋盘的每个坐标,并使用双重循环遍历棋盘判断是否五子连珠
(5)在窗口内嵌套一个透明窗口作为棋子容器,游戏结束时,释放该窗口并重新动态创建透明窗口
四、核心步骤
1.插入棋盘图
- 我们借助QLabel标签显示图片,并将标签设置与主窗口同等大小作为背景图
//插入棋盘背景this->bg = new QLabel(this); //创建标签到主窗口中this->bg->setGeometry(0,0,810,810); //设置标签大小和位置this->bg->setPixmap(QPixmap("./picture/chessboard.png")); //将棋盘图插入到标签中this->bg->setScaledContents(true); //图片自适应标签大小
2.双方落子
- 使用鼠标点击事件,在玩家在点击位置落子,紧接着电脑利用随机数生成坐标落子
void chessboard::mousePressEvent(QMouseEvent *event)
{//若鼠标点击位置没有棋子,则玩家落子if(chess.at(event->x()/54).at(event->y()/54) == 0){//返回值判断一方是否获胜bool result = this->piecePress(PLAYERS,event->x(),event->y());//玩家胜利时,跳过电脑落子重新开始游戏if(result == true){return;}//直到生成随机数区域没有棋子,则电脑落子while(1){//生成随机横坐标int computerx = qrand()%800;//生成随机纵坐标int computery = qrand()%800;//判断该位置是否有棋子if(chess.at(computerx/54).at(computery/54) == 0){//电脑落子this->piecePress(COMPUTER,computerx,computery);break;}}}
}
- 落子显示,我们通过动态创建标签的方式显示棋子图片,并根据下棋对象显示黑棋/白棋
bool chessboard::piecePress(bool object, int x, int y)
{//动态创建标签插入棋子图,并初始化位置信息this->piece = new QLabel(this->chessWin);this->piece->setGeometry(x-x%54,y-y%54,54,54);this->piece->setScaledContents(true);//若下棋对象为玩家if(object == PLAYERS){//插入黑棋图this->piece->setPixmap(QPixmap("./picture/black.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 1;}//若下棋对象为电脑else if(object == COMPUTER){//插入白棋图this->piece->setPixmap(QPixmap("./picture/white.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 2;}//棋子显示this->piece->show();//输赢判定,并返回判定结果return this->winner();
}
3.输赢判定
- 在玩家/电脑每次落子之后,将通过四个不同方向扫描整个棋盘进行一次输赢判定
bool chessboard::winner()
{//横向扫描for(int i=0;i<15;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i][j+1]==1 && chess[i][j+2]==1 && chess[i][j+3]==1 && chess[i][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i][j+1]==2 && chess[i][j+2]==2 && chess[i][j+3]==2 && chess[i][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//纵向扫描for(int j=0;j<15;j++){for(int i=0;i<11;i++){if(chess[i][j]==1 && chess[i+1][j]==1 && chess[i+2][j]==1 && chess[i+3][j]==1 && chess[i+4][j]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j]==2 && chess[i+2][j]==2 && chess[i+3][j]==2 && chess[i+4][j]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//对角扫描for(int i=0;i<11;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i+1][j+1]==1 && chess[i+2][j+2]==1 && chess[i+3][j+3]==1 && chess[i+4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j+1]==2 && chess[i+2][j+2]==2 && chess[i+3][j+3]==2 && chess[i+4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//反对角扫描for(int j=0;j<11;j++){for(int i=14;i>3;i--){if(chess[i][j]==1 && chess[i-1][j+1]==1 && chess[i-2][j+2]==1 && chess[i-3][j+3]==1 && chess[i-4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i-1][j+1]==2 && chess[i-2][j+2]==2 && chess[i-3][j+3]==2 && chess[i-4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}return false;
}
4.重新开始
- 游戏结束后,初始化棋盘,并释放主窗口中所有通过动态创建的标签显示的棋子图
void chessboard::newGame()
{//初始化棋盘for(int i=0;i<15;i++){for(int j=0;j<15;j++){chess[i][j] = 0;}}//释放棋盘窗口,包括棋子delete this->chessWin;//创建新棋盘窗口,并初始化this->chessWin = new QWidget(this);this->chessWin->resize(810,810);this->chessWin->show();
}
五、完整源码
1.main.cpp
#include "widget.h"
#include "chessboard.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);chessboard *five = chessboard::getInstance(); //创建棋盘窗口five->show(); //棋盘窗口显示return a.exec();
}
2.chessboard.h
#ifndef CHESSBOARD_H
#define CHESSBOARD_H#include <QLabel>
#include <QVector>
#include <QWidget>
#include <QMouseEvent>#define PLAYERS 0
#define COMPUTER 1class chessboard : public QWidget
{Q_OBJECT
public://静态公有的获取类对象指针的方法static chessboard* getInstance();//鼠标点击事件void mousePressEvent(QMouseEvent *event);//落子函数bool piecePress(bool object,int x,int y);//输赢判定函数bool winner();//重新开始游戏void newGame();
private://构造函数私有化explicit chessboard(QWidget *parent = 0);//静态私有的类对象指针static chessboard* pchessboard;//棋盘图片QLabel *bg;//棋子图片QLabel *piece;//棋盘落子情况:0无棋子,1有棋子static QVector<QVector<int>> chess;//棋盘窗口QWidget *chessWin;
signals:public slots:
};#endif // CHESSBOARD_H
3.chessboard.cpp
#include <QTime>
#include <QtGlobal>
#include <QMessageBox>
#include "chessboard.h"QVector<QVector<int>> chessboard::chess;
chessboard* chessboard::pchessboard = nullptr; chessboard *chessboard::getInstance()
{if(chessboard::pchessboard == nullptr){chessboard::pchessboard = new chessboard();}return chessboard::pchessboard;
}void chessboard::mousePressEvent(QMouseEvent *event)
{//若鼠标点击位置没有棋子,则玩家落子if(chess.at(event->x()/54).at(event->y()/54) == 0){//返回值判断一方是否获胜bool result = this->piecePress(PLAYERS,event->x(),event->y());//玩家胜利时,跳过电脑落子重新开始游戏if(result == true){return;}//直到生成随机数区域没有棋子,则电脑落子while(1){//生成随机横坐标int computerx = qrand()%800;//生成随机纵坐标int computery = qrand()%800;//判断该位置是否有棋子if(chess.at(computerx/54).at(computery/54) == 0){//电脑落子this->piecePress(COMPUTER,computerx,computery);break;}}}
}bool chessboard::piecePress(bool object, int x, int y)
{//动态创建标签插入棋子图,并初始化位置信息this->piece = new QLabel(this->chessWin);this->piece->setGeometry(x-x%54,y-y%54,54,54);this->piece->setScaledContents(true);//若下棋对象为玩家if(object == PLAYERS){//插入黑棋图this->piece->setPixmap(QPixmap("./picture/black.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 1;}//若下棋对象为电脑else if(object == COMPUTER){//插入白棋图this->piece->setPixmap(QPixmap("./picture/white.png"));//棋盘相应位置进行标记chess[x/54][y/54] = 2;}//棋子显示this->piece->show();//输赢判定,并返回判定结果return this->winner();
}bool chessboard::winner()
{//横向扫描for(int i=0;i<15;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i][j+1]==1 && chess[i][j+2]==1 && chess[i][j+3]==1 && chess[i][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i][j+1]==2 && chess[i][j+2]==2 && chess[i][j+3]==2 && chess[i][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//纵向扫描for(int j=0;j<15;j++){for(int i=0;i<11;i++){if(chess[i][j]==1 && chess[i+1][j]==1 && chess[i+2][j]==1 && chess[i+3][j]==1 && chess[i+4][j]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j]==2 && chess[i+2][j]==2 && chess[i+3][j]==2 && chess[i+4][j]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//对角扫描for(int i=0;i<11;i++){for(int j=0;j<11;j++){if(chess[i][j]==1 && chess[i+1][j+1]==1 && chess[i+2][j+2]==1 && chess[i+3][j+3]==1 && chess[i+4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i+1][j+1]==2 && chess[i+2][j+2]==2 && chess[i+3][j+3]==2 && chess[i+4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}//反对角扫描for(int j=0;j<11;j++){for(int i=14;i>3;i--){if(chess[i][j]==1 && chess[i-1][j+1]==1 && chess[i-2][j+2]==1 && chess[i-3][j+3]==1 && chess[i-4][j+4]==1){QMessageBox::information(nullptr,"温馨提示","玩家获胜!");this->newGame();return true;}else if(chess[i][j]==2 && chess[i-1][j+1]==2 && chess[i-2][j+2]==2 && chess[i-3][j+3]==2 && chess[i-4][j+4]==2){QMessageBox::information(nullptr,"温馨提示","电脑获胜!");this->newGame();return true;}}}return false;
}void chessboard::newGame()
{//初始化棋盘for(int i=0;i<15;i++){for(int j=0;j<15;j++){chess[i][j] = 0;}}//释放棋盘窗口,包括棋子delete this->chessWin;//创建新棋盘窗口,并初始化this->chessWin = new QWidget(this);this->chessWin->resize(810,810);this->chessWin->show();
}chessboard::chessboard(QWidget *parent) : QWidget(parent)
{//隐藏标题栏this->setFixedSize(810,810);//创建棋盘背景this->bg = new QLabel(this);this->bg->setGeometry(0,0,810,810);this->bg->setPixmap(QPixmap("./picture/chessboard.png"));this->bg->setScaledContents(true);//创建棋盘窗口this->chessWin = new QWidget(this);this->chessWin->resize(810,810);//初始化棋盘for(int i=0;i<15;i++){QVector<int> row;for(int j=0;j<15;j++){row.append(0);}chess.append(row);}//随机数初始化qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
}
总结
以上就是【QT项目】简易五子棋游戏(人机对战)的所有内容,希望大家阅读后都能有所收获!原创不易,转载请标明出处,若文章出现有误之处,欢迎读者留言指正批评!