QT五子棋项目

本文介绍了一个使用QT框架开发的五子棋项目,不依赖XML文件,完全通过代码实现界面。项目重点在于得分计算、胜负判断和界面设计,涉及paintevent事件处理和定时器技术。主要包括主界面类和游戏模式类,支持人与人、人与机对战。内容涵盖界面绘制、逻辑判断及鼠标事件响应等。
摘要由CSDN通过智能技术生成

今天给大家带来一个QT的五子棋项目,没有用到xml文件,界面都是纯代码写的,这个项目的主要难点在于得分的计算、输赢的判断逻辑、界面的规划,用到了paintevent等事件,以及定时器的技术,主要写了两个类一个是主界面的,另一个是是关于游戏模式的类,因为这个可以实现人人对战,与人机对战。
首先来看运行如下:
在这里插入图片描述

在这里插入图片描述

1 项目的目录结构如下:
在这里插入图片描述
2 mainwindow.h:
这个就是主界面的头文件,因为主界面上的菜单栏要选择游戏模式,所以和gamemodel类交互必须包含gamemodel的头文件。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "gamemodel.h"
class MainWindow : public QMainWindow
{
   
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
protected:
    //只要窗口部件需要被重绘就被调用
    void paintEvent(QPaintEvent *event);
    //鼠标移动落子 虚的
    void mouseMoveEvent(QMouseEvent *event);
    //真实落子
    void mouseReleaseEvent(QMouseEvent *event);
private:
    GameModel *game; // 游戏指针
    GameType game_type; // 存储游戏类型
    //存储将点击的位置
    int clickPosRow,clickPosCol;
    //初始化游戏
    void initGame();
private slots:
    //人下棋
    void Peoplechess();
    //AI下棋
    void AIchess();
    //初始化人与人模式游戏界面
    void initPVPGame();
    //初始化人与机器模式游戏界面
    void initPVEGame();


};

#endif // MAINWINDOW_H

3 mainwindow.cpp:

这个主界面就是先画出棋盘,再进行逻辑的判断,完善人下棋机器下棋,以及鼠标移动事件等操作

#include "mainwindow.h"
#include <QPainter>
#include <QTimer>
#include <QSound>
#include <QMouseEvent>
#include <QMessageBox>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QDebug>
#include <math.h>

//游戏的音频资源
#define CHESS_ONE_SOUND "J:/respicture/chessone.wav"
#define WIN_SOUND "J:/respicture/win.wav"
#define LOSE_SOUND "J:/respicture/lose.wav"

//棋盘边缘空隙
const int Edge_gapSize=30;
//五子棋半径
const int Radius=15;
//五子棋落子标记边长
const int MarkSize=6;
//格子大小
const int LatticeSize=40;
//鼠标点击的模糊距离上限
const int ObscurePos=20;
//AI思考时间
const int AIthinkTime=700;
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
   
    //棋盘大小
    setFixedSize(Edge_gapSize*2+LatticeSize*kBoardSizeNum,Edge_gapSize*2+LatticeSize*kBoardSizeNum);
    //使用setMouseTracking(true)对鼠标进行监控(mouseMoveEvent(QMouseEvent *event)),如果WidgetA有个子窗体WidgetB会占据WidgetA的绝大部分空间,那么当鼠标移动到WidgetB上时,WidgetA就会失去对鼠标的监控。
    setMouseTracking(true);
    QMenu *menu=menuBar()->addMenu(tr("Game"));
    QAction *actionPVP = new QAction("Person VS Person", this);
    QAction *actionPVE = new QAction("Person VS Computer", this);
    menu->addAction(actionPVP);
    menu->addAction(actionPVE);
    //菜单栏信号与槽
    connect(actionPVP,SIGNAL(triggered(bool)),this,SLOT(initPVPGame()));
    connect(actionPVE,SIGNAL(triggered(bool)),this,SLOT(initPVEGame()));
    //初始化游戏
    initGame();
}

MainWindow::~MainWindow()
{
   
    if(game){
   
        delete game;
        //这个nullptr看看这个https://zhuanlan.zhihu.com/p/257421030
        game=nullptr;
    }

}

void MainWindow::initGame()
{
   
    game = new GameModel;
    initPVPGame();

}

void MainWindow::initPVPGame()
{
   
    game_type = PERSON;
    game->gameStatus = PLAYING;
    game->startGame(game_type);
    update();

}

void MainWindow::initPVEGame()
{
   
    game_type = AI;
    game->gameStatus = PLAYING;
    game->startGame(game_type);
    update();

}


void MainWindow::paintEvent(QPaintEvent *event)
{
   
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);
    for(int i=0;i<kBoardSizeNum+1;i++){
   
        //列
        painter.drawLine(Edge_gapSize+LatticeSize*i,Edge_gapSize,Edge_gapSize+LatticeSize*i,size().height()-Edge_gapSize);
        //行
        painter.drawLine(Edge_gapSize,Edge_gapSize+LatticeSize*i,size().width()-Edge_gapSize,LatticeSize*i+Edge_gapSize);
    }
    QBrush brush;
    //纯色 https://doc.qt.io/archives/qt-4.8/qbrush.html#:~:text=The%20standard%20style%20for%20filling%20is%20Qt%3A%3ASolidPattern.%20The,%28%29%20defines%20the%20color%20of%20the%20fill%20pattern.
    brush.setStyle(Qt::SolidPattern);

    //绘制落子标记
    if (clickPosRow > 0 && clickPosRow < kBoardSizeNum &&
           clickPosCol > 0 && clickPosCol < kBoardSizeNum &&
           game->gameMapVec[clickPosRow][clickPosCol] == 0){
   
        if(game->playerFlag){
   
            brush.setColor(Qt::white);
        }else{
   
            brush.setColor(Qt::black);
        }
       painter.drawRect(Edge_gapSize + LatticeSize * clickPosCol - MarkSize / 2, Edge_gapSize + LatticeSize * clickPosRow - MarkSize / 2, MarkSize, MarkSize);
    }
    // 绘制棋子
    for(int i=0;i<kBoardSizeNum;i++){
   
        for(int j=0;j<kBoardSizeNum;j++){
   
            //画白棋
            if(game->gameMapVec[i][j]==1){
   
                brush.setColor(Qt
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值