《用electron制造俄罗斯方块游戏》 后续文章,智能顺序玩俄罗斯方块游戏。
背景
前不久用ES6完成了基础的俄罗斯方块游戏,本日已完成了一个开端的智能算法,能够自动玩俄罗斯方块了,让本身的主意朝完成更近了一步。
效果图
第一次运转,消除了1398行,窃喜!最高纪录3676行。
顺序构造
重要关注智能算法,构造简朴化,悉数放在了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
小结
开启了我的智能算法进修之路,这还只是一个最简朴的自动顺序,都谈不上任何智能,但对我来说是一个新方向的最先,加油!