俄罗斯方块

俄罗斯方块游戏自动机

《用electron制作俄罗斯方块游戏》 后续文章,智能程序玩俄罗斯方块游戏。

背景

前不久用ES6完成了基本的俄罗斯方块游戏,今天已经完成了一个初步的智能算法,可以自动玩俄罗斯方块了,让自己的想法朝实现更近了一步。

效果图

第一次运行,消除了1398行,窃喜!

程序结构

主要关注智能算法,结构简单化,全部放在了index.js中。

用定时器驱动游戏

function autoPlayClick(){
    isAutoPlay = document.getElementById(‘autoPlay‘).checked;
    if(isAutoPlay){
        clearInterval(interval)
        interval = setInterval( autoTick, 1 );        //自动算法入口
    }else{
        clearInterval(interval)
        interval = setInterval( tick, TICKVAL );      //自动下落入口
    }
    document.getElementById(‘speedShow‘).focus();
}

变量定义

模拟手动操作,一个方块分三步走:旋转、左或右移、下落到底。

const MOVEOPS = [‘moveLeft‘,‘moveRight‘]                //左、右移动定义
var opList = [], bestEva;                               //待操作队列

class Opration{                                         //操作细节
    constructor(op,num){
        this.op = op;                                   //操作方法
        this.num = num;                                 //操作次数
    }
}

class Evaluation{                                      //局面评估函数结果定义
    constructor(r,x,eva){
        this.r = r;                                    //旋转次数
        this.x = x;                                    //方块水平位置
        this.eva = eva;                                //评估结果
    }
}

智能算法调度

function autoTick(){
    if(opList.length == 0){                            //上个方块已经处理完毕
        getStrategy();                                 //策略算法,生成下一个方块的操作方法策略序列
    }else{
        let op = opList.shift();                       //取操作方法
        for(let i=0; i<op.num; i++){                   //执行既定策略
            tetris[op.op]();
            if(op.op == ‘moveDown‘)                    //是下落操作,取下一块方块
                generateNext();
        }
    }
}

策略算法

这是算法核心,确定每一块方块的操作方法。

function getStrategy(){
    let max = 0;                                        //存最优评估值
    tetris.erase();
    let tmp = new Tetris(tetris.shape,tetris.ctx,tetris.x,tetris.y,‘rgb(1,1,1,1)‘,‘rgb(111,111,111)‘)                                                //生成用于测试的方块
    for(let i = 0; i < 4; i++){                        //让测试方块与真实方块保持一致,因为我的每一个方块生成时都进行了随机次数的旋转
        for(let j = 0; j < 4; j++){
            tmp.data[i][j] = tetris.data[i][j];
        }
    }
    for(let r = 0; r < 4; r++){                    //每个方块,旋转四次,分别进行局面评估
        tmp.erase();
        tmp.x = tetris.x;
        tmp.y = tetris.y;
        if(r > 0)
            tmp.rotate();
        while(tmp.moveLeft());                                //从最左测试到右
        while(tmp.moveDown());                                //下落到底
        while(rightOver(tmp)){                                //到右结束这一形态的评估
            let score = evaluate(tmp);                        //局面评估
            if(score > max){                                  //保存最优结果
                max = score;
                bestEva = new Evaluation(r,tmp.x,max)
            }
            if(!tmp.moveRight()){                            //右移失败
                if(!tmp.moveUp()){                           //上移,绕过障碍
                    max = 1000;                              //上移失败,说明填补了空洞,方块就放这
                    bestEva = new Evaluation(r,tmp.x,max)
                    break;
                }
            }else{
                while(tmp.moveDown());                      //右移成功后下落到底
            }
        }
        let score = evaluate(tmp);                          //最后一个位置
        if(score > max){
            max = score;
            bestEva = new Evaluation(r,tmp.x,max)
        }
    }
    tmp.erase();
    // console.log(max)

    opList.push(new Opration(‘rotate‘,bestEva.r));        //旋转操作
    let moveAct = bestEva.x - tetris.x > 0 ? 1 : 0;       //水平位置差转化成左或右移操作
    let actNum = Math.abs(bestEva.x - tetris.x)
    opList.push(new Opration(MOVEOPS[moveAct],actNum));   //左或右移操作
    opList.push(new Opration(‘moveDown‘,1));              //下落操作

}

评估函数

现在只做了几个基本参数评估,有待优化。更深入的做法是加入机器学习算法,进行自主反馈学习。

function evaluate(t){
    let ct = t.y;                                                            //调试越大越好
    for(let i = 0; i < 4; i++){                                              //查看每个小方块的四个邻居的情况
        for(let j = 0; j < 4; j++){
            if(t.data[i][j]){
                if(t.canSee(t.x +i, t.y + j + 1))                            //下方是空洞
                    ct -= 5;
                for(let k=0; k<4; k++){
                    switch(k){
                        case 0: ct += t.canSee(t.x + i + 1, t.y + j) ? 0 : 1;   //右
                        break;
                        case 1: ct += t.canSee(t.x + i - 1, t.y + j) ? 0 : 1;   //左
                        break;
                        case 2: ct += t.canSee(t.x + i, t.y + j + 1) ? 0 : 1;   //下
                        break;
                        case 3: ct += t.canSee(t.x + i, t.y + j - 1) ? 0 : 1;   //上
                        break;
                    }
                }
            }
        }
    }
    return ct;
}

源代码:

git clone https://git.oschina.net/zhoutk/Tetris.git
或者:
git clone https://github.com/zhoutk/Tetris

小结

开启了我的智能算法学习之路,这还只是一个最简单的自动程序,都谈不上任何智能,但对我来说是一个新方向的开始,加油!

分类: NodeJs算法

时间: 2024-08-27 11:40:22

俄罗斯方块的相关文章

很棒的计算机入门课程:公开课从与非门到俄罗斯方块(第二部分)

博客中的文章均为meelo原创,请务必以链接形式注明本文地址 Build a Modern Computer from First Principles: Nand to Tetris Part II (project-centered course) by: Noam Nisan & Shimon Schocken from: Hebrew University of Jerusalem 课程链接:https://www.coursera.org/learn/nand2tetris2/home

C语言:俄罗斯方块

大一下学期,第一节c语言课程设计,老师分享了一个基于C语言的俄罗斯方块的游戏,让我们感受. 如果你想用Mac系统跑的话,也不是不行,但是得解决一些问题.在语言程序中#include<windows.h>这个是基于windows下的头文件,用在Mac的Xcode软件会出现Symbol not found的问题.自己百度了一下,一个是装虚拟机,另一个是把报错的地方修改成Xcode的代码,不用windows特有代码.还有一个就是定义了一个全局的变量,让工程不走windows.h.用Mac的同学们可以

关于俄罗斯方块游戏软件C语言初步感受

C语言课程设,老师先给我们发了一个使用C语言做的飞机游戏,第一次看到用C语言做的游戏,虽然画面简陋,但却是真正的游戏.后老师又给我们发了用C语言做的俄罗斯方块的游戏 int x;     //中心方块的x轴坐标 int y;     //中心方块的y轴坐标 int flag;    //标记方块类型的序号 int next;    //下一个俄罗斯方块类型的序号 int speed;    //俄罗斯方块移动的速度 int count;    //产生俄罗斯方块的个数 int score;  

俄罗斯方块软件:C语言应用初步感受

C语言课程设以一节课,老师提供了一个C语言的飞机游戏让我们感受,上学期C语言课程,主要是各种语句的练习,这次是用以前的知识来感受一个实际的系统. 首先安装c-free,然后运行程序. 游戏程序看似简单,但是用C语言来实现还是第一次见,感到很惊奇. 分析一下程序,感觉没有太复杂的,就是上学期学习的简单语句的组合,但是运用的非常好.首先看看用到了几种语句: 1.首先是在屏幕上显示的语句printf printf("俄罗斯方块"); gotoxy(hOut,FrameX+2*Frame_wi

俄罗斯方块和贪吃蛇游戏软件:C语言应用初始感受

C语言课程设以一节课,老师提供了一个C语言的飞俄罗斯方块让我们感受,我们所学的C语言课程,主要是各种语句的练习,这次是用我们所学过的知识来感受一个实际的系统. 首先安装c-free,然后是将代码贴进去运行 界面虽然有点简单,但这确实使用C语言做出来的游戏. 分析一下程序,感觉没有太复杂的,就是上学期学习的简单语句的组合,但是用的非常好.首先看看用到了几种语句: 1.首先是在屏幕上显示的语句printf, 2.另外一个就是多条件判断switch--case 应用方法 switch(tetris->

俄罗斯方块游戏:C语言程序设计初步感受

C语言课程设以一节课,老师提供了一个C语言的俄罗斯方块游戏让我们感受,本学期C语言课程,主要是各种语句的练习,这次是用以前的知识来感受一个实际的系统. 首先安装c-free,然后打开老师所发给我们的小程序. 界面很简单,没想到C语言还能做这么有意思的东西,真是没有想到. 分析一下程序,感觉比较太复杂的,但就是本学期学习的简单语句的组合,运用起来如此神奇. 1.首先是在屏幕上显示的语句printf 2.运用for语句建立窗口 for(i=2;i<2*Frame_width-2;i+=2) { go

前端作品五之——完美俄罗斯方块

---恢复内容开始--- 1.功能概述 实现传统的俄罗斯方块的功能.有几种固定形状和颜色的方块随机下落,满一行则此行消除.并让积分增加100,使用本地存储功能将方块的状态和得分存起来.在下次进行游戏的时候载入数据,并在游戏中进行存储操作. 2.选材布局 用canvas组件画方格图.用JavaScript语言实现逻辑功能. 3.功能实现与体会 源码中本人发现了几处bug, 1.测试发现在旋转操作频繁的时候,会出现方块严重错位,或丢失,出现一些匪夷所思的现象. 经分析,是旋转操作的处理出现的问题.

用JAVA写的俄罗斯方块

业务需求->业务对象模型(对象关系)->数据建模->类的设计->概要编码->详细功能设计 基本规则: 1)首先呢,俄罗斯方块都是由一个个小格子构成的,我们叫它Cell: 行宽:10,列高:20,以每个小正方形为单位 2)其次,所有的俄罗斯方块都是一组由4个小型正方形组成的规则图形,我们叫它Tetromino    分别为:S.Z.L.J.I.O.T这几种 哈哈,有了这样的分析,就可以构建数据结构设计了 数据结构设计: Cell     格子|--     int row 行|

H5版俄罗斯方块(3)---游戏的AI算法

前言: 算是"long long ago"的事了, 某著名互联网公司在我校举行了一次"lengend code"的比赛, 其中有一题就是"智能俄罗斯方块". 本着一向甘做分母, 闪耀分子的绿叶精神, 着着实实地打了一份酱油. 这次借学习H5的机会, 再来重温下俄罗斯方块的AI编写. 本系列的文章链接如下: 1). 需求分析和目标创新 2). 游戏的基本框架和实现 这些博文和代码基本是同步的, 并不确定需求是否会改变, 进度是否搁置, 但期翼自己能