关于c++:QT5写Tetris之AI机器人玩游戏

44次阅读

共计 2895 个字符,预计需要花费 8 分钟才能阅读完成。

背景

应用 Qt5.12.9 的 QGraphicsItem 来实现俄罗斯方块,应用简略的评估函数,实现 AI 机器人玩俄罗斯方块游戏。这是 AI 机器人的第一步,这个算法很简略,但很无效,大多数状况能消 5 百层以上,最近的为数不多的测试中,最高纪录曾经消了超过 2500 层。在这个根底上,能够不便的积攒原始数据,我心愿能抽取模式,进行模式识别及至机器学习。

思路

在手动游戏根底上进行革新,借鉴回放的教训,只须要退出一个评估算法,为每一个新方块找出一个搁置的姿势(旋转次数)和最终地位坐标就能够了。我的算法设计也很简略,就是为每一个方块穷举其搁置办法,应用一个严密水平的评估算法进行评分,取出最高分的操作,若有雷同得分的操作,用随机数二一添做五。

效果图

要害代码剖析

流程管制

界面操作控制变量,做到随时能够在手动与主动两种模式之间进行切换。

    if (isAutoRunning) {                // 主动模式
        autoProcessCurBlock();            // 解决以后方块,应用评估函数确定方块的最终姿势与地位
        block->relocate(curPos);            // 搁置
        block->setBlockNotActive();        // 固定方块
        generateNextBlock();            // 取下一个方块,游戏持续}else                        // 手动模式
        this->moveBlockDown();
    ...

方块搁置评分函数

我的设计思维很直观,俄罗斯方块就是要尽量严密的沉积在一起,所以对每一个组成方块的 block 都检测一个它四周的四个地位,看是否有 block(包含边界)存在,若有就加 1 分,没有不加分。这块的加分,并没有区别组成方块本身的 block 和外界的 block,因为每个方块都是与本人进行比拟,所以辨别与不辨别成果是一样的。起始分由深度确定,越深我认为成果越好。另个,block 的垂直下方最好不要有空洞,若有会减分。

int Game::evaluate(Tetris* t)
{QPoint pos = t->getPos();
    int ct = pos.y();                // 深度为根底分
    int cct = t->cleanCount();
    if (cct > 1)                // 能消层,加分
        ct += 10 * (cct - 1);
    for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {if (t->data[i][j]) {ct += t->hasTetrisBlock(pos.x() + j + 1, pos.y() + i) ? 1 : 0;            // 检测 block 左边的地位
                ct += t->hasTetrisBlock(pos.x() + j - 1, pos.y() + i) ? 1 : 0;            // 检测 block 右边的地位
                ct += t->hasTetrisBlock(pos.x() + j, pos.y() + i + 1) ? 1 : 0;            // 检测 block 下方的地位
                ct += t->hasTetrisBlock(pos.x() + j, pos.y() + i - 1) ? 1 : 0;            // 检测 block 上方的地位

                if (i == 3 || t->data[i + 1][j] == 0) {if (!t->hasTetrisBlock(pos.x() + j, pos.y() + i + 1)) {            //block 下方的紧临空洞
                        ct -= 4;
                    }
                    else {
                        int k = 2;
                        while (pos.y() + i + k <= 19) {if (!t->hasTetrisBlock(pos.x(), pos.y() + i + k)) {    //block 下方的非紧临空洞
                                ct -= 1;
                                break;
                            }
                            k++;
                        }
                    }
                }
            }
        }
    }
    return ct;
}

穷举方块的所有搁置形式

一个方块最多只有四种姿势,把方块的每一种姿势都从左到右 moveDownEnd 一次,进行评分,获得分最高的计划。

void Game::autoProcessCurBlock()
{
    int max = 0;
    QPoint initPos = block->getPos();
    Tetris* tmp = new Tetris(initPos, block->getShape(), -1);        // 结构以后方块的替身,blockType 为 -1,这种方块不会显示
    int rotateCt = block->getRotateNum();                // 同步替身初始姿势
    for (int k = 0; k < rotateCt; k++)
        tmp->rotate();
    rotateCt = 0;                            // 用于保留方块的最终姿势

    for (int r = 0; r < 4; r++) {                    // 四种姿势遍历,其实能够优化,有的方块不须要四次
        if (r > 0) {tmp->relocate(initPos);                // 留神,旋转要在方块进入游戏界面的中央旋转,不然可能旋转不胜利
            tmp->rotate();}
        while (tmp->moveLeft());                // 从最右边开始
        do {tmp->moveDownEnd();
            tmp->setBlockNotActive();            // 固定方块,以便进行评分
            int score = evaluate(tmp);            // 评分
            if (score > max) {                // 找到以后最优计划
                max = score;
                curPos = tmp->getPos();
                rotateCt = r;
            }
            else if (score == max) {                // 呈现相等评分,随机取
                if (qrand() % 2 == 1) {curPos = tmp->getPos();
                    rotateCt = r;
                }
            }
            //initPos.setX(tmp->getPos().x());
            tmp->relocate(QPoint(tmp->getPos().x(), initPos.y()));    // 返回到游戏空间上方
            tmp->setBlockTest();                // 方块复原到测试状态} while (tmp->moveRight());                // 方块右移,直到不能挪动 
    }
    delete tmp;                            // 销毁测试方块,忽然想到这块能够优化,只须要建七个方块就好,这样就不必一直的创立和销毁了
    for (int k = 0; k < rotateCt; k++)
        block->rotate();}

下一步的构想

应用 python 从新实现所有性能,也不再用 Qt,就用 python 自带的 tkinter 就好。把重点放在模式提取,让 AI 主动玩游戏,写个算法,提取优良的操作模式。而后应用模式匹配或机器学习算法来优化 AI。当初还没有具体的想法,只有这么个大略的构想。

源代码及运行办法

我的项目采纳 cmake 组织,请装置 cmake3.10 以上版本。上面脚本是 windows 下基于 MSVC 的,其它操作系统上根本相似,或者应用 qtcreator 关上进行操作。

cmake -A win32 -Bbuild .
cd build
cmake --build . --config Release

注:本我的项目采纳计划能跨平台运行,曾经适配过 windows,linux,mac。

源代码:

https://gitee.com/zhoutk/qtetris.git

https://gitee.com/zhoutk/qtdemo/tree/master/tetrisGraphicsItem

https://github.com/zhoutk/qtDemo/tree/master/tetrisGraphicsItem

正文完
 0