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);
}
}
}
}