基于Qt实现的井字棋小游戏

1

用Qt做个井字棋小游戏

ui界面

使用9个PushButton来作为井字格

PushButton需要编好名称,方便后续统一处理

在菜单栏中添加三个action分别负责:重开游戏,退出游戏,帮助文档。

整体思路

我们的思路是:

当游戏开始时,通过点击PushButton改变PushButton的文本内容来表示下棋的过程

当玩家下完一步后,电脑接着下一步(设置电脑延迟,使游戏更有真实感)

当下棋步数>=3时,对游戏的胜负进行判断。(考虑平局)

通过菜单栏重启游戏或退出。

事先准备

头文件

#include <QMainWindow>
#include <QDebug>
#include <QMessageBox>
#include <QRandomGenerator>
#include <QList>
#include <QPushButton>
#include <QTimer>

函数和成员

 mainwindow.h

private slots:
    void on_action_3_triggered();//退出游戏

    void on_action_2_triggered();//重开游戏

    void on_action_triggered();//游戏帮助文档

    void PlayerChess();//玩家下棋

    void ComputerChess();//电脑下棋

    void playerWinner();//玩家获胜

    void computerWinner();//电脑获胜

private:
    Ui::MainWindow *ui;
    QList<QPushButton*> buttons;//创建buttons列表存储PushButton
    int count=0;                //计数器记录步数

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    //统一管理PushButton
    buttons = { ui->pushButton_1, ui->pushButton_2, ui->pushButton_3,
                ui->pushButton_4, ui->pushButton_5, ui->pushButton_6,
                ui->pushButton_7, ui->pushButton_8, ui->pushButton_9 };
    //当buttons中被点击时,触发PlayerChess函数
    for (auto button : buttons) {
            connect(button, &QPushButton::clicked, this, &MainWindow::PlayerChess);
        }
}

 玩家下棋

       按钮被点击后获取按钮指针,确定被点击的按钮,检查按钮的文本内容,并进行修改,若步数大于等于3,进行胜负判断,若不存在胜负关系,则延迟触发电脑下棋。

void MainWindow::PlayerChess()//Player
{
    // 获取发送信号的按钮指针
    QPushButton *clickedButton = qobject_cast<QPushButton*>(sender());   
        if (clickedButton) {
            if (clickedButton->text().isEmpty()) {
                count++;
                clickedButton->setText("X");
                if(count>=3){
                    playerWinner();
                    }
                }
                QTimer::singleShot(1000, this, &MainWindow::ComputerChess);
            }
}

电脑下棋

       创建另一个列表保存空按钮(text为空),通过随机数获得索引,将索引指向的按钮转换为O,即为电脑的下棋。并进行判断胜负(此处判断也可以通过步数count限制判断时机)。

void MainWindow::ComputerChess()
{
    QList<QPushButton*> emptyButtons;
        // 遍历所有按钮,找出所有空按钮
        for (auto button : buttons) {
            if (button->text().isEmpty()) {
                emptyButtons.append(button);
            }
        }
        // 如果有空按钮,则随机选择一个空按钮并设置为"O"
        if (!emptyButtons.isEmpty()) {
            int randomIndex = QRandomGenerator::global()->bounded(0, emptyButtons.size());
            QPushButton *randomButton = emptyButtons[randomIndex];
            randomButton->setText("O");
            computerWinner();
        }
}

胜负判断

       胜负判断,我之前是写到一个函数里面的,但是通过if else进行判断时因为存在先后顺序的影响,对于电脑获胜的判断存在bug,于是使用了两个函数,如果有一个函数写出来的,希望能分享代码,一起学习。同样我的平局判断也是存在重复,其实可以单独写一个平局的函数,当棋盘上的所有格子都被修改过后,进行判断,若所有胜利条件都不符合,则平局。

void MainWindow::computerWinner()
{
    QVector<QVector<QPushButton*>> winCombinations {
            { ui->pushButton_1, ui->pushButton_2, ui->pushButton_3 },
            { ui->pushButton_4, ui->pushButton_5, ui->pushButton_6 },
            { ui->pushButton_7, ui->pushButton_8, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_4, ui->pushButton_7 },
            { ui->pushButton_2, ui->pushButton_5, ui->pushButton_8 },
            { ui->pushButton_3, ui->pushButton_6, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_5, ui->pushButton_9 },
            { ui->pushButton_3, ui->pushButton_5, ui->pushButton_7 }
        };

        // 遍历每个胜利组合,检查是否有一方胜利
    for (const auto& combination : winCombinations) {
            if (combination[0]->text() == "O" &&
                combination[0]->text() == combination[1]->text() &&
                combination[1]->text() == combination[2]->text()) {
                QMessageBox::information(this, "游戏结束", "电脑胜利!");
                return;
            }
    }
    bool allFilled = true;
    for (const auto& combination : winCombinations) {
        for (auto button : combination) {
            if (button->text().isEmpty()) {
                allFilled = false;
                break;
            }
        }
        if (!allFilled) break;
    }
    if (allFilled) {
        QMessageBox::information(this, "游戏结束", "平局!");
    }
}


void MainWindow::playerWinner()
{
    QVector<QVector<QPushButton*>> winCombinations {
            { ui->pushButton_1, ui->pushButton_2, ui->pushButton_3 },
            { ui->pushButton_4, ui->pushButton_5, ui->pushButton_6 },
            { ui->pushButton_7, ui->pushButton_8, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_4, ui->pushButton_7 },
            { ui->pushButton_2, ui->pushButton_5, ui->pushButton_8 },
            { ui->pushButton_3, ui->pushButton_6, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_5, ui->pushButton_9 },
            { ui->pushButton_3, ui->pushButton_5, ui->pushButton_7 }
        };

        // 遍历每个胜利组合,检查是否有一方胜利
    for (const auto& combination : winCombinations) {
            if (combination[0]->text() == "X" &&
                combination[0]->text() == combination[1]->text() &&
                combination[1]->text() == combination[2]->text()) {
                QMessageBox::information(this, "游戏结束", "玩家胜利!");
                return;
            }
        }
    bool allFilled = true;
    for (const auto& combination : winCombinations) {
        for (auto button : combination) {
            if (button->text().isEmpty()) {
                allFilled = false;
                break;
            }
        }
        if (!allFilled) break;
    }
    if (allFilled) {
        QMessageBox::information(this, "游戏结束", "平局!");
    }

}

源代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QMessageBox>
#include <QRandomGenerator>
#include <QList>
#include <QPushButton>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_action_3_triggered();

    void on_action_2_triggered();

    void on_action_triggered();

    void PlayerChess();

    void ComputerChess();

    void playerWinner();

    void computerWinner();

private:
    Ui::MainWindow *ui;
    QList<QPushButton*> buttons;
    int count=0;

};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    buttons = { ui->pushButton_1, ui->pushButton_2, ui->pushButton_3,
                                    ui->pushButton_4, ui->pushButton_5, ui->pushButton_6,
                                    ui->pushButton_7, ui->pushButton_8, ui->pushButton_9 };
    for (auto button : buttons) {
            connect(button, &QPushButton::clicked, this, &MainWindow::PlayerChess);
        }
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_action_3_triggered()
{
    this->close();
}


void MainWindow::on_action_2_triggered()
{
    this->close();

        // 创建新的主窗口实例并显示
        MainWindow *newMainWindow = new MainWindow();
        newMainWindow->show();
}


void MainWindow::on_action_triggered()
{
    QMessageBox::information(this,"游戏提示","点击按钮下棋,"
                                         "三点一线获胜");
}

void MainWindow::PlayerChess()//Player
{
    QPushButton *clickedButton = qobject_cast<QPushButton*>(sender());  // 获取发送信号的按钮指针
    qDebug()<<"buttonsize"<<buttons.size();
        if (clickedButton) {
            qDebug() << "玩家点击了按钮:" << clickedButton->objectName();
            if (clickedButton->text().isEmpty()) {
                count++;
                clickedButton->setText("X");
                if(count>=3){
                    playerWinner();
                    }
                }
                QTimer::singleShot(1000, this, &MainWindow::ComputerChess);
            }
}

void MainWindow::ComputerChess()
{
    QList<QPushButton*> emptyButtons;
        // 遍历所有按钮,找出所有空按钮
        for (auto button : buttons) {
            if (button->text().isEmpty()) {
                emptyButtons.append(button);
            }
        }
        qDebug() << "空按钮个数:" << emptyButtons.size();

        // 如果有空按钮,则随机选择一个空按钮并设置为"O"
        if (!emptyButtons.isEmpty()) {
            int randomIndex = QRandomGenerator::global()->bounded(0, emptyButtons.size());
            QPushButton *randomButton = emptyButtons[randomIndex];
            randomButton->setText("O");
            computerWinner();
            qDebug() << "计算机在按钮:" << randomButton->objectName() << " 下了一步";
        } else {
            qDebug() << "所有按钮都已经有了棋子,无法继续下棋";
        }
}
    
void MainWindow::computerWinner()
{
    QVector<QVector<QPushButton*>> winCombinations {
            { ui->pushButton_1, ui->pushButton_2, ui->pushButton_3 },
            { ui->pushButton_4, ui->pushButton_5, ui->pushButton_6 },
            { ui->pushButton_7, ui->pushButton_8, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_4, ui->pushButton_7 },
            { ui->pushButton_2, ui->pushButton_5, ui->pushButton_8 },
            { ui->pushButton_3, ui->pushButton_6, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_5, ui->pushButton_9 },
            { ui->pushButton_3, ui->pushButton_5, ui->pushButton_7 }
        };

        // 遍历每个胜利组合,检查是否有一方胜利
    for (const auto& combination : winCombinations) {
            if (combination[0]->text() == "O" &&
                combination[0]->text() == combination[1]->text() &&
                combination[1]->text() == combination[2]->text()) {
                qDebug() << "电脑胜利";
                QMessageBox::information(this, "游戏结束", "电脑胜利!");
                return;
            }
    }
    bool allFilled = true;
    for (const auto& combination : winCombinations) {
        for (auto button : combination) {
            if (button->text().isEmpty()) {
                allFilled = false;
                break;
            }
        }
        if (!allFilled) break;
    }
    if (allFilled) {
        qDebug() << "平局";
        QMessageBox::information(this, "游戏结束", "平局!");
    }
}


void MainWindow::playerWinner()
{
    QVector<QVector<QPushButton*>> winCombinations {
            { ui->pushButton_1, ui->pushButton_2, ui->pushButton_3 },
            { ui->pushButton_4, ui->pushButton_5, ui->pushButton_6 },
            { ui->pushButton_7, ui->pushButton_8, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_4, ui->pushButton_7 },
            { ui->pushButton_2, ui->pushButton_5, ui->pushButton_8 },
            { ui->pushButton_3, ui->pushButton_6, ui->pushButton_9 },
            { ui->pushButton_1, ui->pushButton_5, ui->pushButton_9 },
            { ui->pushButton_3, ui->pushButton_5, ui->pushButton_7 }
        };

        // 遍历每个胜利组合,检查是否有一方胜利
    for (const auto& combination : winCombinations) {
            if (combination[0]->text() == "X" &&
                combination[0]->text() == combination[1]->text() &&
                combination[1]->text() == combination[2]->text()) {
                qDebug() << "玩家胜利";
                QMessageBox::information(this, "游戏结束", "玩家胜利!");
                return;
            }
        }
    bool allFilled = true;
    for (const auto& combination : winCombinations) {
        for (auto button : combination) {
            if (button->text().isEmpty()) {
                allFilled = false;
                break;
            }
        }
        if (!allFilled) break;
    }
    if (allFilled) {
        qDebug() << "平局";
        QMessageBox::information(this, "游戏结束", "平局!");
    }

}

main.cpp 

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值