五子棋
五子棋是一个比较简单的经典小游戏,使用QT制作五子棋的需要用到绘图事件处理函数paintEvent(QPaintEvent *event)
和鼠标事件处理函数mousePressEvent(QMouseEvent *e)
过程如下:
- 绘制棋盘
- 绘制棋子
- 棋盘初始化
- 点击鼠标获取棋子窗口落点位置
- 将棋子落点位置转换为棋盘行列线位置
- 下棋子(重绘棋盘)
- 判断输赢
头文件:fivechesswidget.h
#ifndef FIVECHESSWIDGET_H
#define FIVECHESSWIDGET_H
#include <QWidget>
#include<QString>
//QLabel 类代表标签,它是一个用于显示文本或图像的窗口部件。
#include<QLabel>
#include<QRect>
#include<QPoint>
#include<QMouseEvent>
#include<QPaintEvent>
#include<QPainter>
#include<QMessageBox>
class FiveChessWidget : public QWidget
{
Q_OBJECT
public:
QLabel*label;
QString str;
QRect rect;
QPoint x_y_pos;
//0为空,1为白棋,2为黑棋
int chessboard[18][18];
int x0 = 60;//第一个交叉点的横坐标
int y0 = 60;//第一个交叉点的纵坐标
int width = 40;//棋盘格子宽度
int c_r = 20;//棋子半径
bool iswhite = 1;//先下白棋
public:
explicit FiveChessWidget(QWidget *parent = 0);
~FiveChessWidget();
protected:
virtual void paintEvent(QPaintEvent *event);//绘图事件
virtual void mousePressEvent(QMouseEvent *e);//点击鼠标事件
void play_chess(int i,int j);//下棋子
void judge_chess(int i,int j);//判断棋子
void scan_chessboard(int i,int j,int color);//扫描棋盘
void judge_win(int num,int color);//判断输赢
void clean_chessboard();//清空棋盘
};
#endif // FIVECHESSWIDGET_H:
fivechesswidget.cpp
#include "fivechesswidget.h"
/******构造函数初始化对象******/
FiveChessWidget::FiveChessWidget(QWidget *parent)
: QWidget(parent)
{
setFixedSize(800,800);//设置固定的窗口大小
setWindowTitle("低配版五子棋");//窗口标题
label = new QLabel;
label->setParent(this);
clean_chessboard();
}
FiveChessWidget::~FiveChessWidget()
{
}
/******清空棋盘******/
void FiveChessWidget::clean_chessboard()
{
for(int i = 0;i<18;i++)
{
for(int j = 0;j<18;j++)
{
chessboard[i][j]=0;
}
}
}
/******绘制棋盘和棋子******/
void FiveChessWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);//创建QPainter对象
//设置画笔
QPen pen;
pen.setStyle(Qt::SolidLine);
pen.setWidth(2);
pen.setColor(Qt::darkGray);
painter.setPen(pen);
//设置画刷
QBrush brush;
//画矩形
painter.drawRect(30,30,740,740);
painter.drawRect(60,60,680,680);
//painter.drawPoint(100,100);画一个点
//QPoint是QT中表示点的坐标类,用整型值表示某个点的坐标
//画列线
for(int i = 100; i < 730; i+=40)
{
painter.drawLine(QPoint(i,60),QPoint(i,740));
}
//画横线
for(int j =100 ;j < 730; j+=40)
{
painter.drawLine(QPoint(60,j),QPoint(740,j));
}
//画棋子
for(int i = 0; i<18;i++)
{
for(int j = 0;j<18;j++)
{
if(chessboard[i][j]==1)
{
pen.setStyle(Qt::SolidLine);
pen.setWidth(2);
pen.setColor(Qt::white);
painter.setPen(pen);
brush.setColor(Qt::white);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);
painter.drawEllipse(x0+i*width-c_r,y0+j*width-c_r,2*c_r,2*c_r);//画白棋
}
else if(chessboard[i][j]==2)
{
pen.setStyle(Qt::SolidLine);
pen.setWidth(2);
pen.setColor(Qt::darkGray);
painter.setPen(pen);
brush.setColor(Qt::darkGray);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);
painter.drawEllipse(x0+i*width-c_r,y0+j*width-c_r,2*c_r,2*c_r);//画黑棋
}
}
}
}
/******点击鼠标获取棋子坐标******/
void FiveChessWidget::mousePressEvent(QMouseEvent *e)
{
int i,j;
if(e->button()==Qt::LeftButton)
{
x_y_pos = e->pos();
for(i = 0;i < 18;i++)
{
for(j = 0;j<18;j++)
{
rect = QRect(x0+i*width-c_r,y0+j*width-c_r,2*c_r,2*c_r);
if(rect.contains(x_y_pos))
{
if(chessboard[i][j]==0)
{
play_chess(i,j);
label->move(590,10);
label->resize(180,20);
str.sprintf("当前棋子坐标:(%d,%d)",(x0+i*width),(y0+j*width));
//label->setText("("+QString::number(x0+i*width)+","+QString::number(y0+j*width)+")");
label->setText(str);
}
}
}
}
}
}
/******下棋子******/
void FiveChessWidget::play_chess(int i, int j)
{
if(iswhite)
{
chessboard[i][j] = 1;
}
else
{
chessboard[i][j] = 2;
}
iswhite = !iswhite;
this->update();
judge_chess(i,j);
}
/******判断棋子******/
void FiveChessWidget::judge_chess(int i, int j)
{
if(chessboard[i][j]==0)//判断是否为空
return;
if(chessboard[i][j]==1)//是否为白棋
scan_chessboard(i,j,1);
if(chessboard[i][j]==2)//是否为黑棋
scan_chessboard(i,j,2);
}
/******扫描棋盘******/
void FiveChessWidget::scan_chessboard(int i, int j,int color)
{
int row;//行
int col;//列
int chessnums=0;//棋子数量
int direction;//扫描方向
for(direction=0;direction<4;direction++)
{
switch (direction) {
case 0://行扫描
{
for(row=i,col=j;(chessboard[row][col-1]==color)&&(col>=0);chessnums++,col--);
for(row=i,col=j;(chessboard[row][col+1]==color)&&(col<18);chessnums++,col++);
judge_win(chessnums+1,color);
chessnums=0;
break;
}
case 1://列扫描
{
for(row=i,col=j;(chessboard[row-1][col]==color)&&(row>=0);chessnums++,row--);
for(row=i,col=j;(chessboard[row+1][col]==color)&&(row<18);chessnums++,row++);
judge_win(chessnums+1,color);
chessnums=0;
break;
}
case 2://左对角线
{
for(row=i,col=j;(chessboard[row-1][col-1]==color)&&(row>=0);chessnums++,row--,col--);
for(row=i,col=j;(chessboard[row+1][col+1]==color)&&(row<18);chessnums++,row++,col++);
judge_win(chessnums+1,color);
chessnums=0;
break;
}
case 3://右对角线
{
for(row=i,col=j;(chessboard[row-1][col+1]==color)&&(row>=0);chessnums++,row--,col++);
for(row=i,col=j;(chessboard[row+1][col-1]==color)&&(row<18);chessnums++,row++,col--);
judge_win(chessnums+1,color);
chessnums=0;
break;
}
default:
break;
}
}
}
/******判断输赢******/
void FiveChessWidget::judge_win(int num,int color)
{
if(num==5)
{
if(color==1)
{
QMessageBox::question(this,QString("结束"),QString("白棋获胜"),"确认");
clean_chessboard();
this->update();//重绘棋盘
}
if(color==2)
{
QMessageBox::question(this,QString("结束"),QString("黑棋获胜"),"确认");
clean_chessboard();
this->update();//重绘棋盘
}
}
else
return;
}
main.cpp
#include "fivechesswidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
FiveChessWidget w;
w.show();
return a.exec();//消息循环
}