井字棋游戏:任意一方先走,占据一个格子,只要某一方先在井字中画成一条直线就算赢。
首先在Qt Creator 中创建我们需要的项目,代码如下
widget.h文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
class QGridLayout;
class QLabel;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
//初始化界面布局
void initUi();
//重写事件过滤器
bool eventFilter(QObject *, QEvent *);
//计算
bool calculate(QList<int>,int);
//判断是否已经选择
inline bool isSelected(int);
private:
//网格布局
QGridLayout* gridLayout;
//声明9个格子
QLabel* label1;
QLabel* label2;
QLabel* label3;
QLabel* label4;
QLabel* label5;
QLabel* label6;
QLabel* label7;
QLabel* label8;
QLabel* label9;
//接收选中的数字
int num;
//判断是红方还是蓝方(自增,奇数为红,偶数为蓝)
int isRed;
//保存红方选中的数字列表
QList<int> redList;
//保存蓝方选中的数字列表
QList<int> blueList;
};
#endif // WIDGET_H
widget.cpp 文件
#include "widget.h"
#include <QLabel>
#include <QGridLayout>
#include <QEvent>
#include <QDebug>
#include <QMessageBox>
#include <QString>
#include <QPushButton>
#include <QApplication>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//判断是红方还是蓝方(自增,奇数为红,偶数为蓝)
isRed = 1;
//设置窗口标题
setWindowTitle(QStringLiteral("井字棋游戏"));
//设置主窗口最小大小
setMinimumSize(740, 700);
//初始化界面布局
initUi();
//给每个格子添加事件过滤
label1->installEventFilter(this);
label2->installEventFilter(this);
label3->installEventFilter(this);
label4->installEventFilter(this);
label5->installEventFilter(this);
label6->installEventFilter(this);
label7->installEventFilter(this);
label8->installEventFilter(this);
label9->installEventFilter(this);
}
//初始化界面布局
void Widget::initUi(){
//初始化
label1 = new QLabel("1");
label1->setText("1");
label2 = new QLabel("2");
label3 = new QLabel("3");
label4 = new QLabel("4");
label5 = new QLabel("5");
label6 = new QLabel("6");
label7 = new QLabel("7");
label8 = new QLabel("8");
label9 = new QLabel("9");
gridLayout = new QGridLayout(this);
//网格间隙为0
gridLayout->setVerticalSpacing(0);
gridLayout->setHorizontalSpacing(0);
//设置水平居中
label1->setAlignment(Qt::AlignCenter);
label2->setAlignment(Qt::AlignCenter);
label3->setAlignment(Qt::AlignCenter);
label4->setAlignment(Qt::AlignCenter);
label5->setAlignment(Qt::AlignCenter);
label6->setAlignment(Qt::AlignCenter);
label7->setAlignment(Qt::AlignCenter);
label8->setAlignment(Qt::AlignCenter);
label9->setAlignment(Qt::AlignCenter);
//设置边框
label1->setFrameStyle(QFrame::Box);
label2->setFrameStyle(QFrame::Box);
label3->setFrameStyle(QFrame::Box);
label4->setFrameStyle(QFrame::Box);
label5->setFrameStyle(QFrame::Box);
label6->setFrameStyle(QFrame::Box);
label7->setFrameStyle(QFrame::Box);
label8->setFrameStyle(QFrame::Box);
label9->setFrameStyle(QFrame::Box);
// 添加到网格布局中
gridLayout->addWidget(label1,0,0);
gridLayout->addWidget(label2,0,1);
gridLayout->addWidget(label3,0,2);
gridLayout->addWidget(label4,1,0);
gridLayout->addWidget(label5,1,1);
gridLayout->addWidget(label6,1,2);
gridLayout->addWidget(label7,2,0);
gridLayout->addWidget(label8,2,1);
gridLayout->addWidget(label9,2,2);
}
//重写事件过滤器
bool Widget::eventFilter(QObject* obj, QEvent* ev){
//判断是不是 鼠标点击事件
if(ev->type() == QEvent::MouseButtonPress){
//设置背景色
QPalette p;
//奇数为红,偶数为蓝
if(isRed % 2 == 1){
p.setColor(QPalette::Window,Qt::red);
}else{
p.setColor(QPalette::Window,Qt::blue);
}
if(obj == label1){
num = 1;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label1->setAutoFillBackground(true);
label1->setPalette(p);
}
if(obj == label2){
num = 2;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label2->setAutoFillBackground(true);
label2->setPalette(p);
}
if(obj == label3){
num = 3;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label3->setAutoFillBackground(true);
label3->setPalette(p);
}
if(obj == label4){
num = 4;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label4->setAutoFillBackground(true);
label4->setPalette(p);
}
if(obj == label5){
num = 5;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label5->setAutoFillBackground(true);
label5->setPalette(p);
}
if(obj == label6){
num = 6;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label6->setAutoFillBackground(true);
label6->setPalette(p);
}
if(obj == label7){
num = 7;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label7->setAutoFillBackground(true);
label7->setPalette(p);
}
if(obj == label8){
num = 8;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label8->setAutoFillBackground(true);
label8->setPalette(p);
}
if(obj == label9){
num = 9;
bool isOK = isSelected(num);
if(isOK){
return QWidget::eventFilter(obj,ev);
}
label9->setAutoFillBackground(true);
label9->setPalette(p);
}
//下一步谁走
if(isRed % 2 == 1){
//把红方选中的保存到redList中
redList << num;
qDebug() << "redList = " << redList;
//判断谁赢
bool boolR = calculate(redList,blueList.size()+redList.size());
if(boolR){
if(QMessageBox::Ok == QMessageBox::information(this,"success",QStringLiteral("红方赢了 "))){
//设置程序的退出码
qApp->exit(122);
}
}
}else{
//把蓝方选中的保存到redList中
blueList << num;
qDebug() << "blueList = " << blueList;
//判断谁赢
bool boolR = calculate(blueList,blueList.size()+redList.size());
if(boolR){
if(QMessageBox::Ok == QMessageBox::information(this,"success",QStringLiteral("蓝方赢了 "))){
qApp->exit(122);
}
}
}
//自增,对方走
isRed++;
qDebug() << "isRed = " << isRed;
}
return QWidget::eventFilter(obj,ev);
}
//计算
bool Widget::calculate(QList<int> list,int size){
//3个数字才能组成一组(这个条件有没有不影响)
if(list.size() > 2){
//判断list中是否包含该数字
bool b1 = list.contains(1);
bool b2 = list.contains(2);
bool b3 = list.contains(3);
bool b4 = list.contains(4);
bool b5 = list.contains(5);
bool b6 = list.contains(6);
bool b7 = list.contains(7);
bool b8 = list.contains(8);
bool b9 = list.contains(9);
//组成一条线的组合
if(b1 & b2 & b3){
return true;
}
if(b4 & b5 & b6){
return true;
}
if(b7 & b8 & b9){
return true;
}
if(b1 & b4 & b7){
return true;
}
if(b2 & b5 & b8){
return true;
}
if(b3 & b6 & b9){
return true;
}
if(b3 & b5 & b7){
return true;
}
if(b1 & b5 & b9){
return true;
}
//判断是否平局
if(size == 9){
QMessageBox::information(this,"success",QStringLiteral("该游戏平局 "));
qApp->exit(122);
return false;
}
}
return false;
}
//判断是否已经选择
bool Widget::isSelected(int num){
//判断当前是哪一方
if(isRed % 2 == 1){
//红方
//判断是否选中对方已有的
if(blueList.contains(num)){
QMessageBox::warning(this,"warning",QStringLiteral("已经被对方选中!!!蓝 "));
return true;
}
//判断是否重复选中
if(redList.contains(num)){
QMessageBox::warning(this,"warning",QStringLiteral("不能选中自身已有 "));
return true;
}
}else{
//蓝方
//判断是否选中对方已有的
if(redList.contains(num)){
QMessageBox::warning(this,"warning",QStringLiteral("已经被对方选中!!!红 "));
return true;
}
//判断是否重复选中
if(blueList.contains(num)){
QMessageBox::warning(this,"warning",QStringLiteral("不能选中自身已有 "));
return true;
}
}
return false;
}
Widget::~Widget(){}
main.cpp 文件
#include "widget.h"
#include <QApplication>
#include <QProcess>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
//接收并判断退出码
int code = a.exec();
if(code == 122){
//使用 startDetached () 函数打开外部进程时,外部进程启动后,不会随主程序的退出而退出
//参数:需要启动的应用程序的文件路径
QProcess::startDetached(qApp->applicationFilePath());
return 0;
}
return code;
}
感觉写的很繁琐,希望能简化一下,接受建议