**高级语言程序设计大作业实验报告**
*对于Gobang_2.0的解析*
这个视频是我对于高级语言程序设计这门课的大作业的解说
## **一.** **作业题目**
制作一个简单的双人五子棋游戏
## **二.** **开发软件**
Qt Creator 4.11.1
## **三.** **课题要求**
1) 页面跳转
2) 页面设计
3) 判断输赢
4)游戏音效
## **四.** **主要流程**
1.打开exe文件,出现进入游戏的主界面
2.进入游戏,点击鼠标实现落子
3.判断是否五子相连,弹出输赢对话框
## **五. 技术路线**
##### 1. 跳转的实现
新建qt设计师界面类(即新出现一个ui)
要实现在mainwindow.ui中打开chess.ui:
1. 在mainwindow.h中添加 “ chess.h"头文件
2. 在mainwindow.h中mainwindow的类的private下
定义一个chess对象Chess *c =new Chess
3. 然后再mainwindow.cpp中添加“ chess.h"头文件
4. 在mainwindow.ui的相应按钮下转到槽click中:
```c++
void MainWindow::on_pushButton_clicked()
{
this->close();
c= new Chess();
c->show();
}
```
即可实现页面跳转
##### 2.对ui的初始化
1. 在相应的ui类头文件下,private权限下定义初始化函数
```c++
void initui();
```
2. 在对应的cpp文件中,进行函数的说明
```c++
void MainWindow::InitUi()
{
//大小
this->resize(350,300);
//定死大小
this->setMaximumSize(350,300);
this->setMinimumSize(350,300);
//设置标题名字
this->setWindowTitle("nkuzyz 五子棋");
//可执行程序图标
this->setWindowIcon(QIcon(":/images/img/loge.png"));//可执行程序图标
}
```
3.别忘记在ui的构造函数中实现这个函数
##### 3.画出需要的材料
##### *涉及的头文件
###### QPainter
//实例化一个绘图工具
利用头文件
```c++
#include<QPainter>
```
从而使用QPainter绘图工具
**使用方法**
```c++
QPainter painter(this);//实例化一个绘图工具
painter.setRenderHint(QPainter::HighQualityAntialiasing,true);//防止棋盘变形
painter.setPen(QPen(QColor(Qt::black),2));//给边框线颜色与大小
painter.setPen(QPen(QColor(Qt::transparent)));//给棋子的边框线透明
painter.setBrush(Qt::yellow);//设置填充形状的颜色
painter.drawRect(“起点横坐标”,“起点纵坐标”,“终点横坐标”,“终点纵坐标”);//绘制矩形(棋盘的格子)
painter.drawEllipse(圆心坐标,“横轴半径”,“纵轴半径”);//绘制椭圆
```
###### QPaintEvent
//实时绘制界面
只有把涉及使用qpainter画图工具绘制的函数加入该事件下,才会进行画图
1. 在头文件中加入头文件
```
#include<QPaintEvent>
```
2. 在头文件的类设定中
```c++
protected:
void paintEvent(QPaintEvent *event);//实时绘制界面
```
3. 在cpp文件中编写使用该函数(编写即会使用)
```c++
void Chess::paintEvent(QPaintEvent *event)//实时绘制界面
{
DrawChessBoard();//画棋盘
DrawHandChess();//画鼠标上的棋子
DrawChessItem();//绘制棋盘上的棋子
update();//强制更新界面
}
```
###### QMouseEvent
//鼠标点击事件
1. 头文件的引入
```
#include<QMouseEvent>
```
2. 类下的函数定义
```c++
protected:
void mousePressEvent(QMouseEvent *event);//鼠标点击事件
```
3. 在cpp文件下,写入发生鼠标点击事件后的相应变化
```
void Chess::mousePressEvent(QMouseEvent *event)
{
//获取鼠标的点击位置
qDebug()<<event->pos()<<endl;
}
```
```c++
event->pos() 获得点击事件得坐标
event->pos().x()//获得点击事件的横坐标
```
###### QDebug
*在Qt程序调试的时候,经常需要==打印一些变量==,那么我们就需要使用qDebug()函数,这种函数有两种使用方法*
在如上的代码的调试过程中,可以==打印==到每次鼠标==点击事件==后获得的坐标
1. 头文件引入#include<QDebug>
2. 像c++中cout用法一样 qDebug()<<event->pos()<<endl;
###### QPoint
//点的类
```c++
QPoint pt;//定义点位
pt.setX((event->pos().x())/MAX_X);
pt.setY((event->pos().y())/MAX_Y);
QPoint ptCenter(X,Y);//初始化点
```
###### QCursor
//mapFromGlobal(QCursor::pos())来实时获取鼠标位置
###### QSound
使用方法:
The QSound class provides a method to play .wav sound files.
Header:
#include <QSound>
qmake:即在.pro文件里面加上
QT += multimedia
设置方法
```c++
QSound* sound = new QSound(":/music/rec/back.wav",this);
sound->setLoops(-1); //设置循环次数 如果是 -1 代表无限循环
sound->play(); //音效开始
```
```c++
QSound * csound = new QSound(":/music/rec/click.wav",this);
csound->play();
```
###### QMessageBox
1. 引入头文件#include<QMessageBox>
2. ```c++
//直接使用
QMessageBox::information(NULL,"GAME OVER",str,QMessageBox::Yes);
```
![image-20210411215443442](D:\markdown\picture\image-20210411215443442.png)
###### QVector
1. 引入头文件#include<QVector>
2. 在类private下添加定义一哈
```
private:
QVector<ChessItem>p_ChessItem;//定义棋子个数
```
其中ChessItem是一个被定义的类——即棋子,有位置与颜色
```
p_ChessItem.size()
p_ChessItem[i]
p_ChessItem.append(item);
p_ChessItem.clear();
p_ChessItem.contains(item)
```
???
```c++
bool QVector::contains(const T &*value*) const
Returns true if the vector contains an occurrence of *value*; otherwise returns false.
This function requires the value type to have an implementation of operator==().
void QVector::append(const T &value)
Inserts value at the end of the vector.
Example:
QVector<QString> vector;
vector.append("one");
vector.append("two");
QString three = "three";
vector.append(three);
// vector: ["one", "two", "three"]
// three: "three"
This is the same as calling resize(size() + 1) and assigning value to the new last element in the vector.
This operation is relatively fast, because QVector typically allocates more memory than necessary, so it can grow without reallocating the entire vector each time.
void QVector::clear()
Removes all the elements from the vector.
```
## **六. 核心算法**
##### 1.画棋盘
```c++
void Chess::DrawChessBoard()
{
QPainter painter(this);//绘图工具
painter.setRenderHint(QPainter::HighQualityAntialiasing,true);//防止棋盘变形
painter.setPen(QPen(QColor(Qt::black),2));//给边框线颜色与大小
//painter.setBrush(Qt::yellow);
//painter.drawPixmap(0,0,750,950,QPixmap(":/image/img/back.jpeg"));
//遍历绘制棋盘的所有格子
for (int i=0;i<CHESS_C;i++) {
for (int j=0;j<CHESS_R;j++) {
//绘制矩形(棋盘的格子)
painter.drawRect((i+0.5)*MAX_X,(j+0.5)*MAX_Y,MAX_X,MAX_Y);
}
}
}
```
##### 2.画鼠标上的棋子
```c++
void Chess::DrawHandChess()
{
QPainter painter(this);
painter.setPen(QPen(QColor(Qt::transparent)));//给棋子的边框线透明
if(b_black)
{
painter.setBrush(Qt::black);
}
else
{
painter.setBrush(Qt::white);
}
// 获取鼠标位置 圆的半径
painter.drawEllipse(mapFromGlobal(QCursor::pos()),(MAX_X/2)-1,(MAX_Y/2)-1);
}
```
##### 3.画棋盘上的棋子
```c++
void Chess::DrawChessItem()
{
QPainter painter(this);