20230408 单人五子棋

该代码实现了一个基于QT的单人五子棋游戏,包括棋盘绘制、棋子放置逻辑、胜利条件检查以及语音提示功能。玩家可以点击棋盘进行落子,程序会判断游戏状态并提供语音反馈。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QT 单人五子棋


#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QPainter>
#include <QDebug>
#include <QMouseEvent>
#include <QTextToSpeech>
#include <QMessageBox>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

//棋子
class Chess{
public:
    int getX() const{
        return _x;
    }
    int getY() const{
        return _y;
    }
    int getStatus() const{
        return _status;
    }
    void changeStatus(int _status=0) {
       this->_status = _status;
    }
    void setXY(int _x,int _y){
        this->_x = _x;
        this->_y = _y;
    }
private:
    //坐标
    int _x;
    int _y;
    //状态值:0初始状态 1黑棋 2白棋
    int _status=0;
};

class Widget : public QWidget
{
    Q_OBJECT

public:

    static const int x_grid_count = 10;//x轴网格数
    static const int y_grid_count = 10;//y轴网格数
    static const int grid_margin = 60;//网格简介

    static const int win_width = 800;//窗口宽度
    static const int win_height = 800;//窗口高度

    static const int startPos_x = 100;//起始点
    static const int startPos_y = 100;//终点

    static const int _range=Widget::grid_margin/2;//判断长度
    //判断点击发生的位置是否在棋子判定范围
    //_op 1黑棋/2白棋
    static bool within_range(Chess &_chess,QPoint &_point,int _op);

    //起点位置
    Widget(QWidget *parent = nullptr);
    ~Widget();
    int _op;
    //初始化棋牌棋子
    void initialChesses();
    //判断是谁赢了
    bool checkChesses() const;
    //绘画事件
    void paintEvent(QPaintEvent *event) override;
    //鼠标点击事件
    void mousePressEvent(QMouseEvent *event) override;
    //重置棋牌
    void resetChesses();
private:
    Ui::Widget *ui;

    Chess *chesses;

    QTextToSpeech *qTextToSpeech;
};




#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置窗口固定大小
    this->setFixedSize(QSize(win_width,win_height));

    //初始化棋牌棋子
    int chessesNum = (Widget::x_grid_count+1) * (Widget::y_grid_count +1);
    this->chesses = new Chess[chessesNum];
    initialChesses();

    //黑棋先走
    this->_op = 1;

    this->qTextToSpeech = new QTextToSpeech(this);
}

Widget::~Widget()
{
    delete ui;
    delete qTextToSpeech;
    delete [] chesses;
}
//初始化棋牌棋子
void Widget::initialChesses(){
    int _x = Widget::startPos_x;
    int _y = Widget::startPos_y;
    int pos;

    for(int i=0;i<=Widget::y_grid_count;i++){
        _x = Widget::startPos_x;
        for(int j=0;j<=Widget::x_grid_count;j++){
            pos = i * (Widget::y_grid_count+1) + j;
            (chesses+pos)->setXY(_x,_y);
            _x+=Widget::grid_margin;
        }
        _y+=Widget::grid_margin;
    }
}
//判断是否胜利
bool Widget::checkChesses() const
{
    int pos = 0;
    int cStatus;
    bool sign = false;
    for(int i=2;i<=Widget::y_grid_count-2;i++){
        for(int j=2;j<=Widget::x_grid_count-2;j++){
            pos = i * (Widget::y_grid_count+1) + j;
            if(this->chesses[pos].getStatus() != _op){
                continue;
            }
            cStatus = _op;
            //横向
            sign = true;
            for(int jj=j-2;jj<=j+2;jj++){
                pos = i * (Widget::y_grid_count+1) + jj;
                if(chesses[pos].getStatus() != cStatus){
                    sign = false;
                    break;
                }
            }
            if(sign){
                //qDebug()<<"横向";
                return true;
            }
            //纵向
            sign = true;
            for(int ii=i-2;ii<=i+2;ii++){
                pos = ii * (Widget::y_grid_count+1) + j;
                if(chesses[pos].getStatus() != cStatus){
                    sign = false;
                    break;
                }
            }
            if(sign){
                //qDebug()<<"纵向";
                return true;
            }
            //左斜方向
            sign = true;
            for(int ii=i-2,jj=j-2;ii<=i+2;ii++,jj++){
                pos = ii * (Widget::y_grid_count+1) + jj;
                if(chesses[pos].getStatus() != cStatus){
                    sign = false;
                    break;
                }
            }
            if(sign){
                //qDebug()<<"左斜";
                return true;
            }
            //右斜方向
            sign = true;
            for(int ii=i-2,jj=j+2;ii<=i+2;ii++,jj--){
                pos = ii * (Widget::y_grid_count+1) + jj;
                if(chesses[pos].getStatus() != cStatus){
                    sign = false;
                    break;
                }
            }
            if(sign){
                //qDebug()<<"右斜";
                return true;
            }
        }
    }
    return false;
}

//判断点击发生的位置是否在棋子判定范围
//_op 1黑棋/2白棋
bool Widget::within_range(Chess &_chess, QPoint &_point, int _op)
{
    if(_chess.getStatus() != 0){
        return false;//
    }
    //如果点击事件发生在棋子周围(长度为_range*2的长方形)
    if(_chess.getX()+_range>=_point.x() && _chess.getX()-_range<=_point.x() &&
       _chess.getY()+_range>=_point.y() && _chess.getY()-_range<=_point.y()){
        _chess.changeStatus(_op);
        qDebug()<<_point<<_op;
        return true;
    }
    return false;
}
//鼠标点击事件
void Widget::mousePressEvent(QMouseEvent *event)
{
    QPoint _point = event->pos();
    int pos = 0;
    for(int i=0;i<=Widget::y_grid_count;i++){
        for(int j=0;j<=Widget::x_grid_count;j++){
            pos = i * (Widget::y_grid_count+1) + j;
            if(Widget::within_range(chesses[pos],_point,_op)){
                //更新界面
                update();
                if(checkChesses()){
                    QString str = _op==1?"黑棋获胜,是否继续":"白棋获胜,是否继续";
                    this->qTextToSpeech->say(str);
                    auto ret = QMessageBox::question(this,"提示",str,QMessageBox::Yes | QMessageBox::No);
                    if(QMessageBox::Yes == ret){
                        //重置棋牌
                        resetChesses();
                        update();
                        return;
                    }else{
                        this->close();
                    }
                }
                _op=_op == 1?2:1;
                break;
            }
        }
    }
}
//重置棋牌
void Widget::resetChesses()
{
    int pos;
    this->_op = 1;
    for(int i=0;i<=Widget::y_grid_count;i++){
        for(int j=0;j<=Widget::x_grid_count;j++){
            pos = i * (Widget::y_grid_count+1) + j;
            this->chesses[pos].changeStatus();
        }
    }
}

void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPen pen(Qt::black);
    pen.setWidth(3);
    painter.setPen(pen);
    int pos1,pos2;
    int x_count = Widget::x_grid_count+1;
    int y_count = Widget::y_grid_count+1;
    //画横线
    for(int i=0;i<=Widget::y_grid_count;i++){
        pos1 = i*y_count;
        pos2 = i*y_count+Widget::y_grid_count;
        painter.drawLine(chesses[pos1].getX(),chesses[pos1].getY(),chesses[pos2].getX(),chesses[pos2].getY());
    }
    //画竖线
    for(int i=0;i<=Widget::x_grid_count;i++){
        pos1 = i;
        pos2 = Widget::y_grid_count*x_count+i;
        painter.drawLine(chesses[pos1].getX(),chesses[pos1].getY(),chesses[pos2].getX(),chesses[pos2].getY());
    }
    //画棋子
    int pos = 0;
    int radius = Widget::_range-5;
    for(int i=0;i<=Widget::y_grid_count;i++){
        for(int j=0;j<=Widget::x_grid_count;j++){
            pos = i * (Widget::y_grid_count+1) + j;
            if(chesses[pos].getStatus() != 0){
                painter.setBrush(chesses[pos].getStatus()==1?Qt::black:Qt::white);
                painter.drawEllipse(chesses[pos].getX()-radius,chesses[pos].getY()-radius,radius*2,radius*2);
            }
        }
   }

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值