Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)

目录
一、前言
二、游戏效果展示
三、需求分析
四、代码实现
1、新建一个类five_in_a_row继承于QWidget
2、头文件(five_in_a_row.h)
3、构造函数(初始化棋盘)
4、放置棋子槽函数
5、定输赢函数
6、清空棋盘函数
7、cpp用到的头文件
8、主函数测试
五、总结

一、前言 本文为使用Qt实现一个简易的五子棋游戏,通过使用QTableWiget绘制棋盘,使用二维数组相关知识实现五子棋人机对战的功能。

二、游戏效果展示 电脑比较笨,不懂得防守(哈哈哈),不,应该是我太厉害了!哈哈!!!


三、需求分析

  • 使用QTableWiget画一个棋盘
  • 双击棋盘中的某块区域,在该区域“下”一颗棋子
  • 人下完棋子之后,电脑也需要在某块区域下棋(使用随机数)
  • 判断输赢(是否五子连珠)
  • 分出胜负后需要清空棋盘
分析完需求之后,话不多说,直接开始上代码
四、代码实现 1、新建一个类five_in_a_row继承于QWidget
  • (1) 右键工程文件夹——>添加新文件
Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)
文章图片

  • (2) 选择C++——>C++ Class,点击下一步
Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)
文章图片

  • (3) 类名为 five_in_a_row,基类选择 QWidget,点击下一步,点击完成。
Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)
文章图片

2、头文件(five_in_a_row.h)
#ifndef FIVE_IN_A_ROW_H #define FIVE_IN_A_ROW_H#include #include #include class five_in_a_row : public QWidget { Q_OBJECT public: explicit five_in_a_row(QWidget *parent = 0); void whetherWin(int type); //定输赢 void clearChessBoard(); //清空表格,初始化数组private: QTableWidget *tableWidget; //表格,用于绘制棋盘 QMessageBox *message; //消息框 int num[20][20]; //二维数组,存放棋子位置 int win; //输赢的标志位signals:public slots: void setChess(int x, int y); //下棋 }; #endif // FIVE_IN_A_ROW_H

3、构造函数(初始化棋盘)
  • 初始化二维数组
  • 新建20 x 20表格
  • 设置表格宽高
  • 绑定信号槽
five_in_a_row::five_in_a_row(QWidget *parent) : QWidget(parent) { this->setFixedSize(700, 700); this->setWindowTitle("五子棋"); this->setWindowIcon(QIcon(":/image/小棋盘.png")); message = new QMessageBox(QMessageBox::NoIcon, "Tip", "", QMessageBox::Ok | QMessageBox::No, this); message->setWindowIcon(QIcon(":/image/提示.png")); message->setStyleSheet("QMessageBox QLabel{min-width: 400px; " "min-height: 100px; font:16pt; font-family:'楷体'; }"); for(int i = 0; i < 20; i++)//初始化二维数组 { for(int j = 0; j < 20; j++) { num[i][j] = 0; } }tableWidget = new QTableWidget(20, 20,this); //20x20 的表格 tableWidget->setGeometry(0, 0, this->width(), this->height()); //设置表格 x、y、w、hfor(int i=0; i<20; i++) { tableWidget->setColumnWidth(i, this->width()/21); //设置列宽 tableWidget->setRowHeight(i, this->height()/21); //设置行高 }tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); //设置表格不可编辑//双击下棋 connect(tableWidget, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(setChess(int, int))); }

4、放置棋子槽函数 通过双击信号得到的行(x)和列(y),在表格 x行y列 的地方加载一个打钩QLabel,也就是“下”一颗棋子,并且将二维数组 num[x][y] =1,标记此处是我们下的棋子。
人下完棋子之后,判断有没有五子连珠,没有的话电脑开始下棋,电脑通过随机数产生一个在x,y附近的位置(temp_x 、temp_y)。并在表格 temp_x 行,temp_y 列 的地方加载一个打叉QLabel,并且将二维数组 num[temp_x ][temp_y] =-1,标记此处是电脑下的棋子。并判断电脑是否五子连珠。
void five_in_a_row::setChess(int x, int y) { //num[x][y] == 0表示该位置没有棋子 if(num[x][y] == 0) { num[x][y] = 1; //人下的棋子,用1代替 QLabel *lab = new QLabel; lab->setPixmap(QPixmap(":/image/打钩红.png").scaled(this->width()/21, this->height()/21)); tableWidget->setCellWidget(x, y, lab); //放置一颗棋子(打钩) whetherWin(1); //判断人是否赢了 if(this->win == 1) { message->setText("你赢啦!是否再来一局?"); if(message->exec() == QMessageBox::Ok) //再来一局 { this->clearChessBoard(); } else //退出游戏 { this->close(); } return; }//电脑通过随机数下棋 message->setText("电脑下棋中……"); message->exec(); while(1) { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); //随机数种子,让随机数更随机 //产生一个人下的棋子附近的随机位置 int temp_x = (qrand()%5-2)+x; int temp_y = (qrand()%5-2)+y; if(num[temp_x-1][temp_y-1]==0 && temp_x<20 && temp_y<20 && temp_x > 0 && temp_y >0)//该位置没有棋子 { num[temp_x-1][temp_y-1] = -1; //电脑下的棋子,用-1代替 QLabel *temp_lab = new QLabel; temp_lab->setPixmap(QPixmap(":/image/打叉.png").scaled(this->width()/21, this->height()/21)); tableWidget->setCellWidget(temp_x-1, temp_y-1, temp_lab); //放置一颗棋子(打叉) break; } else { continue; } } whetherWin(-1); //判断电脑是否赢了 if(this->win == -1) { message->setText("电脑赢啦!是否再来一局?"); if(message->exec() == QMessageBox::Ok) //再来一局 { this->clearChessBoard(); } else //退出游戏 { this->close(); } } } }

5、定输赢函数 通过循环遍历二维数组的方法,判断行方向、列方向、斜方向是否五子连珠。
//判断行方向、列方向、斜方向是否五子连珠 void five_in_a_row::whetherWin(int type)//type=1表示人,type=-1表示电脑 { int i, j; for(i=0; i<20; i++)//判断行方向是否五子连珠 { for(j=0; j<20; j++) { if(num[i][j]==type && num[i][j+1]==type && num[i][j+2]==type && num[i][j+3]==type && num[i][j+4]==type) { win = type; return; } else { win = 0; } } } for(j=0; j<20; j++)//判断列方向是否五子连珠 { for(i=0; i<20; i++) { if(num[i][j]==type && num[i+1][j]==type && num[i+2][j]==type && num[i+3][j]==type && num[i+4][j]==type) { win = type; return; } else { win = 0; } } } for(j=0; j<20; j++)//判断斜(\)方向是否五子连珠 { for(i=0; i<20; i++) { if(num[i][j]==type && num[i+1][j+1]==type && num[i+2][j+2]==type && num[i+3][j+3]==type && num[i+4][j+4]==type) { win = type; return; } else { win = 0; } } } for(j=0; j<20; j++)//判断斜(/)方向是否五子连珠 { for(i=0; i<20; i++) { if(num[i][j]==type && num[i-1][j+1]==type && num[i-2][j+2]==type && num[i-3][j+3]==type && num[i-4][j+4]==type) { win = type; return; } else { win = 0; } } } }

6、清空棋盘函数 首先将二维数组内的值全部置为0,然后将表格内容清空,将输赢的标志位 置0。
//清空棋盘 void five_in_a_row::clearChessBoard() { for(int i = 0; i < 20; i++)//初始化数组 { for(int j = 0; j < 20; j++) { num[i][j] = 0; } } tableWidget->clear(); //清空表格 this->win = 0; //输赢的标志位 置0 }

7、cpp用到的头文件
#include "five_in_a_row.h"
#include
#include
8、主函数测试
#include "five_in_a_row.h" #include int main(int argc, char *argv[]) { QApplication app(argc,argv); five_in_a_row w; //创建棋盘类对象w.show(); //显示棋盘return app.exec(); }

五、总结 通过以上代码,我们的这个五子棋小游戏就做完了,其实有很多不足的地方。比如:
1、判断输赢的时候,存在二维数组越界问题。
2、当人下的棋子附近没有地方下棋的时候,电脑不知道下哪里,程序就会崩溃掉。
3、在边界下棋时,电脑下棋会很久才下一颗棋(供电脑下棋的位置太少)。
4、电脑下棋的位置不够智能,不知道防守。

感兴趣的小伙伴可以优化优化,也可以改成人与人对战,可以和好朋友一起玩,哈哈哈。
Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)
文章图片
Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)
文章图片
Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)
文章图片
Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)
文章图片

以上是五子棋用到的图片,需要的小伙伴可以下载一下。

原创不易,转载请标明出处。
【Qt学习|Qt学习之使用QTableWiget实现简易五子棋游戏(人机对战)】有什么问题可以评论区留言,期待您的一键三连,嘻嘻。

    推荐阅读