QtラーニングはQTableWigetを使用して、単純なバックギャモンゲーム(マンマシンバトル)を実装します

コンテンツ

I.はじめに

第二に、ゲーム効果の表示

3.需要分析

第四に、コードの実装

1.QWidgetから継承する新しいクラスfive_in_a_rowを作成します

2.ヘッダーファイル(five_in_a_row.h)

3.コンストラクター(チェス盤を初期化します)

4.チェススロット機能を配置します

5.機能の勝ち負け

6.チェス盤機能をクリアします

7.cppが使用するヘッダーファイル

8.主な機能テスト

V.まとめ


I.はじめに

        この記事では、Qtを使用して、QTableWigetを使用してチェス盤を描画し、2次元配列の知識を使用してバックギャモンのマンマシンバトルの機能を実現することにより、簡単なバックギャモンゲームを実装します。

第二に、ゲーム効果の表示

        コンピューターはばかげていて、防御する方法がわかりません(笑)、いや、私は上手すぎるはずです!ハハ!

3.需要分析

  • QTableWigetを使用してチェス盤を描く
  • チェス盤の領域をダブルクリックして、その領域で駒を「再生」します
  • 人がチェスの駒をプレイした後、コンピューターは特定の領域でチェスをプレイする必要もあります(乱数を使用)
  • 勝ち負けの判断(5人連続かどうか)
  • 勝者が決定した後、ボードをクリアする必要があります

要件を分析した後は、あまり言わずに、コーディングを開始してください

第四に、コードの実装

1.QWidgetから継承する新しいクラスfive_in_a_rowを作成します

  • (1)プロジェクトフォルダを右クリック->新しいファイルの追加

  • (2)C ++-> C ++クラスを選択し、[次へ]をクリックします

  • (3)クラス名はfive_in_a_row、基本クラスはQWidgetで、[次へ]、[完了]の順にクリックします。

2.ヘッダーファイル(five_in_a_row.h)

#ifndef FIVE_IN_A_ROW_H
#define FIVE_IN_A_ROW_H

#include <QWidget>
#include <QTableWidget>
#include <QMessageBox>

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.コンストラクター(チェス盤を初期化します)

  • 2次元配列を初期化します
  • 新しい20x20フォーム
  • テーブルの幅と高さを設定する
  • バインド信号スロット
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、h

    for(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をロードします。つまり、チェスの駒を「再生」し、2次元を設定します。 array num [x] [y]=1.ここにマークがポーンです。

        人がチェスの駒をプレイした後、5つの連続したビーズがあるかどうかが判断されます。そうでない場合、コンピューターはチェスのプレイを開始し、コンピューターは乱数によってxとyの近くの位置(temp_x、temp_y)を生成します。そして、テーブルのtemp_x行とtemp_y列に交差したQLabelをロードし、2次元配列num [temp_x] [temp_y] =-1を設定します。ここにマークを付けるのは、コンピューターの下のチェスの駒です。そして、コンピューターが5人の息子であるかどうかを判断します。

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.チェス盤機能をクリアします

        まず、2次元配列のすべての値を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 <QLabel>

#include <QTime>

8.主な機能テスト

#include "five_in_a_row.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc,argv);

    five_in_a_row w;//创建棋盘类对象

    w.show();//显示棋盘

    return app.exec();
}

V.まとめ

        上記のコードで、バックギャモンゲームは終了です。実際、多くの欠点があります。例えば:

1.勝ち負けを判断する場合、2次元配列の範囲外の問題があります。

2.チェスの駒の近くにチェスをする場所がない場合、コンピューターはどこでチェスをするかわからず、プログラムがクラッシュします。

3.境界でチェスをプレイする場合、コンピューターはチェスをプレイするのに長い時間がかかります(コンピューターがチェスをプレイするには位置が少なすぎます)。

4.コンピュータのチェスの位置は、防御する方法を知るのに十分な知性がありません。

興味のある友達はそれを最適化するか、人間同士の戦いに変えるか、良い友達と遊ぶことができます、ハハハ。

 

上記はGobangで使用されている写真です。必要な友達はダウンロードできます。

オリジナリティは簡単ではありません。転載の際は出典をお知らせください。

ご不明な点がございましたら、コメント欄にメッセージを残して、ワンクリックのスリーリンクをお待ちしております。

おすすめ

転載: blog.csdn.net/wmcy123/article/details/123650729