- 浏览: 9285 次
- 性别:
- 来自: 大连
最新评论
<html> <head> <title>TETRIS AI</title> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Expires" content="-1" /> <meta http-equiv="Cache-Control" content="no-cache" /> <meta http-equiv="MSThemeCompatible" content="yes" /> <script type="text/javascript" src="./tetrisai.js"></script> <style> .fill { width: 2px; height: 2px; background-color: #666666; } .blank { width: 6px; height: 6px; background-color: #FFFFFF; } .active { width: 6px; height: 6px; background-color: #3399FF; } .pad { background-color: #EEEEEE } .error { width: 6px; height: 6px; background-color: #FF0000 } .block { width: 6px; height: 6px; display:none; } </style> </head> <body onload="load()" onkeydown="EventDispatcher()"> <table> <tr> <td> <div id="render1"></div> <input type="button" value="start" onclick="ctrl1.start();"> <input type="button" value="stop" onclick="ctrl1.stop();"> <input type="button" value="clear" onclick="ctrl1.clear();"> </td> <td> <!-- <div id="render2"></div> --> <!-- <input type="button" value="start" onclick="ctrl2.start();">--> <!-- <input type="button" value="stop" onclick="ctrl2.stop();">--> <!-- <input type="button" value="clear" onclick="ctrl2.clear();">--> <!-- </td>--> </tr> </table> </body> </html>
tetrisai.js
/************************** * Tetris AI Refine Edition * @author FuLi **************************/ /* * The container of the basic methods of the Tetris. */ TetrisUtil = { /* * Copy all the properties of source into destination. */ mix : function(/* mixed */destination, /* mixed */source) { for ( var property in source) { destination[property] = source[property]; } return destination; }, /* * Returns a new class of JavaScript that the default initialize method is * this.initialize. */ createClass : function() { return function() { this.initialize.apply(this, arguments); } }, /* * Returns a clone array of pure data(string/number),without any references. */ cloneAry : function(/* Array */aryin) { var ret = []; var length = aryin.length; for ( var i = 0; i < length; i++) { var element; if (typeof aryin == "object" && aryin[i].constructor == Array) { element = arguments.callee(aryin[i]); } else { element = aryin[i]; } ret.push(element); } return ret; }, /* * Returns a clone array of pure number without any references, very fast in * IE. */ cloneSimpleAry : function(/**/aryin) { return eval("([" + aryin.toString() + "])"); }, /* * Returns the really array object from a fake array(object set) */ toArray : function(/* */ary) { var ret = []; for ( var i = 0; i < ary.length; i++) { ret.push(ary[i]); } return ret; }, /* * Returns a new function that content is the first argument,scopee is the * second argument,and the others is the argument to bind to the given * function. */ bind : function(/* Function,obj0[,obj1...] */) { var args = TetrisUtil.toArray(arguments); var __method = args.shift(); var object = args.shift(); return function() { return __method.apply(object, args.concat(TetrisUtil.toArray(arguments))); } }, /* * Returns the sum of the input array,which is a set of pure number. */ sumAry : function(/* Array */ary) { var ret = 0; for ( var i = 0; i < ary.length; i++) { ret += ary[i]; } return ret; }, /* * Inputs a 2d array[x][y],and returns sum x. */ sumAryX : function(/* Array[][] */ary2d,/* int */rowIndex) { var sum = 0; for ( var i = 0; i < ary2d.length; i++) { sum += ary2d[i][rowIndex]; } return sum; }, /* * Empty function for some default function references. */ emptyFunction : function() { }, deleteLine : function(/* Array[][] */dataTable,/* int */index) { for ( var i = index - 1; i >= 0; i--) { for ( var j = 0; j < dataTable.length; j++) { dataTable[j][i + 1] = dataTable[j][i]; dataTable[j].shift(); dataTable[j].unshift(0); } } }, /* * Returns the count of cleared lines,which the lines are full fixed. */ clearLine : function(/* Array[][] */dataTable) { var clearCount = 0; for ( var i = 0; i < dataTable[0].length; i++) { if (TetrisUtil.sumAryX(dataTable, i) == dataTable.length) { clearCount++; TetrisUtil.deleteLine(dataTable, i); } } return clearCount; }, /* * Merge a position array(bar array)into a base table. using the (given * function/default function) to process * baseTable[posAry[i][0]][posAry[i][0]] the given function would get two * arguments,first is the effecting cell of basetable,second is posAry[i]. * FIX ME: I didn't explained it clearly. */ mergePos : function(/* Array[][] */baseTable,/* Array[4][2] */posAry,/* Optional,Function */operation) { operation = operation || function() { return 2; } for ( var i = 0; i < posAry.length; i++) { if (typeof baseTable[posAry[i][0]][posAry[i][1]] == "undefined") { throw "error"; } baseTable[posAry[i][0]][posAry[i][1]] = operation(baseTable[posAry[i][0]][posAry[i][1]], posAry[i]); } return baseTable; } } /* * A timer class which manages all timing events. */ var Timer = TetrisUtil.createClass(); /* * Extends the Timer's static members. */ TetrisUtil.mix(Timer, { /* * A cache of all the timers.Using timer's name to map timer instance. */ timers : {}, /* * Starts all timers in the timer cache. */ startAll : function() { var timers = this.timers; for ( var i = 0; i < timers.length; i++) { timers[i].start(); } }, /* * Stops all timers in the timer cache. */ stopAll : function() { var timers = this.timers; for ( var i = 0; i < timers.length; i++) { timers[i].stop(); } }, /* * Returns one timer using the timer name. */ get : function(/* String */name) { return this.timers[name]; }, /* * Removes and returns a timer with the certain name. */ remove : function(/* String */name) { var timers = TetrisUtil.toArray(this.timers); var ret; var timersnew = []; while (timers.length) { var tmp = timers.shift(); if (tmp.name == name) { ret = tmp; } else { timersnew.push(tmp); } } return ret; }, /* * Returns an array of all timers. */ getAll : function() { return TetrisUtil.toArray(this.timers); } }); /* * Mixin the members of all the timer instances. */ TetrisUtil.mix(Timer.prototype, { /* * A switch of timer. */ started :false, /* * invertal of the timer. */ invertal :1000, /* * Timer name. */ name :"", /* * Default method for timer to invok. */ method : function() { }, /* * Constructor,to initialize a timer.If the name is used ,it will throw an * exception. */ initialize : function(/* String */name,/* int */invertal,/* Function */method) { if (this.constructor.timers[name]) { throw "has this timer already"; } else { this.constructor.timers[name] = this; } this.name = name; if (typeof invertal != "undefined") { this.invertal = invertal; } ; if (method) { this.method = method; } ; }, /* * The core of Timer,Cycle invok this method in order to invok this timer's * method. */ doTimer : function() { if (!this.started) { return; } setTimeout(TetrisUtil.bind(arguments.callee, this), this.invertal); this.method(); }, /* * To start this timer. */ start : function() { if (!this.started) { this.started = true; this.doTimer(); } }, /* * To stop this timer,the current running time is not effected. */ stop : function() { this.started = false; }, showBar : function(bar,render) { render.appendChild( this.createPad(10,10).table); } }); /* * Main Class of the tetris Game. */ var Tetris = TetrisUtil.createClass(); /* * Static consts of the game,now only conatins the type of the controller. */ Tetris.CONSTS = { KEYBOARD :"keyboard", AI :"ai" } /* * Add all base behavior of tetris game. */ TetrisUtil.mix(Tetris.prototype, { /* * Specify the current status of the game. */ status : {}, /* * All bar data in this 2d array.each is an array of bar. */ barData : [ [ [ 4, 2 ], [ 4, 3 ], [ 5, 3 ], [ 6, 3 ] ], [ [ 4, 2 ], [ 5, 2 ], [ 4, 3 ], [ 4, 4 ] ], [ [ 4, 2 ], [ 5, 2 ], [ 6, 2 ], [ 6, 3 ] ], [ [ 5, 2 ], [ 5, 3 ], [ 5, 4 ], [ 4, 4 ] ], [ [ 6, 2 ], [ 6, 3 ], [ 4, 3 ], [ 5, 3 ] ], [ [ 4, 2 ], [ 4, 3 ], [ 4, 4 ], [ 5, 4 ] ], [ [ 4, 2 ], [ 4, 3 ], [ 5, 2 ], [ 6, 2 ] ], [ [ 4, 2 ], [ 5, 2 ], [ 5, 3 ], [ 5, 4 ] ], [ [ 4, 2 ], [ 5, 2 ], [ 5, 3 ], [ 6, 3 ] ], [ [ 5, 2 ], [ 5, 3 ], [ 4, 3 ], [ 4, 4 ] ], [ [ 4, 3 ], [ 5, 3 ], [ 5, 2 ], [ 6, 2 ] ], [ [ 4, 2 ], [ 4, 3 ], [ 5, 3 ], [ 5, 4 ] ], [ [ 4, 2 ], [ 5, 2 ], [ 6, 2 ], [ 5, 3 ] ], [ [ 4, 2 ], [ 4, 3 ], [ 4, 4 ], [ 5, 3 ] ], [ [ 5, 2 ], [ 5, 3 ], [ 4, 3 ], [ 6, 3 ] ], [ [ 5, 2 ], [ 5, 3 ], [ 5, 4 ], [ 4, 3 ] ], [ [ 4, 2 ], [ 5, 2 ], [ 4, 3 ], [ 5, 3 ] ], [ [ 4, 2 ], [ 5, 2 ], [ 4, 3 ], [ 5, 3 ] ], [ [ 3, 2 ], [ 4, 2 ], [ 5, 2 ], [ 6, 2 ] ], [ [ 5, 2 ], [ 5, 3 ], [ 5, 4 ], [ 5, 5 ] ] ], /* * Method of initialize,specify the game's name,render, and the col/row * counts. */ initialize : function(name, render, width, height) { this.render = render = document.getElementById(render); var padInfo = this.createPad(width, height); this.name = name; this.table = padInfo.table; this.tableMap = padInfo.tableMap; this.dataTable = padInfo.dataTable; this.rect = { width :width, height :height } render.appendChild(this.table); this.status = {}; pageContext.tetris[name] = this; }, /* * replace the current game with an stopped empty game. */ clear : function() { var padInfo = this.createPad(this.rect.width, this.rect.height); this.table = padInfo.table; this.tableMap = padInfo.tableMap; this.dataTable = padInfo.dataTable; this.render.innerHTML = ""; this.render.appendChild(this.table); this.status = {}; this.refresh(); }, /* * Create the game pad to display,and the data model's in memory; */ createPad : function(width, height) { var table = document.createElement('table'); table.className = "pad"; var tbody = document.createElement('tbody'); table.appendChild(tbody); var tableMap = []; var dataTable = []; for ( var i = 0; i < height; i++) { var tr = document.createElement("tr"); if (i < 2) { tr.style.display = "none"; } tbody.appendChild(tr); for ( var j = 0; j < width; j++) { var td = document.createElement("td"); td.className = "blank"; tr.appendChild(td); tableMap[j] = tableMap[j] || []; dataTable[j] = dataTable[j] || []; tableMap[j][i] = td; dataTable[j][i] = 0; } } return { table :table, tableMap :tableMap, dataTable :dataTable }; }, /* * Get a new bar.If the bar No. is not specified ,use an random bar. */ newBar : function(barSN) { barSN = (typeof barSN == "undefined") ? Math.floor(Math.random() * this.barData.length) : barSN; var ret ; if(!this.status.nextBar) { this.status.nextBar = this.barData[Math.floor(Math.random() * this.barData.length)]; } ret = this.status.bar = this.status.nextBar; this.status.nextBar = this.barData[barSN]; return ret; }, /* * Check if the specified step is available .Param absPos is a absolute * position array of a bar; */ validateStep : function(absPos) { var copyOfDataTable = TetrisUtil.cloneAry(this.dataTable); try { TetrisUtil.mergePos(copyOfDataTable, absPos, function() { return arguments[0] + 2; }); var toCheckAry = TetrisUtil.cloneSimpleAry(copyOfDataTable); for ( var i = 0; i < toCheckAry.length; i++) { if (toCheckAry[i] > 2) { return false; } } return true; } catch (e) { return false; } }, /* * Refresh the table to display. */ refresh : function() { for ( var i = 0; i < this.dataTable.length; i++) { for ( var j = 2; j < this.dataTable[i].length; j++) { switch (this.dataTable[i][j]) { case 0: this.tableMap[i][j].className = "blank"; break; case 1: this.tableMap[i][j].className = "fill"; break; case 2: this.tableMap[i][j].className = "active"; break; default: this.tableMap[i][j].className = "error"; break; } } } }, /* * Join the offset to the given position(bar),and returns a new one ,without * modifying the given param. */ joinOffsetToPos : function(posAry, offset) { var ret = []; for ( var i = 0; i < posAry.length; i++) { ret[i] = TetrisUtil.cloneSimpleAry(posAry[i]); ret[i][0] += offset[0]; ret[i][1] += offset[1]; } return ret; }, /* * Make a bar static,mostly used when a bar shouldn't move. */ fixBar : function(absPos) { TetrisUtil.mergePos(this.dataTable, absPos, function() { return 1; }); }, /* * Set a absolute position of the tetris dataTable active(plus 2). */ setActive : function(absPos) { TetrisUtil.mergePos(this.dataTable, absPos, function() { return 2; }); }, /* * Clears the active pos in the tetris dataTable. */ clearActive : function() { for ( var i = 0; i < this.dataTable.length; i++) { for ( var j = 0; j < this.dataTable[i].length; j++) { if (this.dataTable[i][j] == 2) { this.dataTable[i][j] = 0; } } } }, /* * Roll's the given bar into a new bar array,then return the new array; */ rollBar : function(bar) { var ret = []; var centerX = Math.round((bar[0][0] + bar[1][0] + bar[2][0] + bar[3][0]) / 4); var centerY = Math.round((bar[0][1] + bar[1][1] + bar[2][1] + bar[3][1]) / 4); for ( var i = 0; i < 4; i++) { ret[i] = []; ret[i][0] = centerX - bar[i][1] + centerY; ret[i][1] = bar[i][0] + centerY - centerX; } return ret; }, /* * Invoks the interface of the ControllFactory,and give the current tetirs * instance to the controller. */ buildController : function(controllerFactory) { return controllerFactory.getNewController(this); }, /* * Returns the max height the given bar could drop. */ getDropHeight : function(absBar) { var dropHeight = this.rect.height; for ( var i = 0; i < absBar.length; i++) { var col = this.dataTable[absBar[i][0]]; var colDropHeight = 0 for ( var j = absBar[i][1] + 1; j < col.length; j++) { if (col[j] == 0) { colDropHeight++; } else break; } if (colDropHeight < dropHeight) { dropHeight = colDropHeight; } } return dropHeight; } }); /* * Declare the basic behavior of the controllers(abstract class). */ var BasicControllerBehavior = { /* * The controller status. */ started :false, /* * Timer instance of this controller. */ timer :null, /* * The speed(inveretal) of the controller for down bar.Default is 1000. */ speed :1000, /* * Start the controller,as well as the timer in it; */ start : function() { if (this.started) { return; } this.started = true; this.timer = this.timer || new Timer(this.tetris.name, this.speed, TetrisUtil.bind(this.control, this)); this.timer.start(); this.startNewBar(); }, /* * Stop the controller,as well as the timer in it; */ stop : function() { this.started = false; Timer.get(this.tetris.name).stop(); }, /* * Trigger the gameover of the tetris. */ gameOver : function() { alert(this.tetris.name + " Game Over!"); this.stop(); }, /* * Stop the game and get a new stopped game. */ clear : function() { this.stop(); this.tetris.clear(); }, /* * Set the speed(invertal) of the game. */ setSpeed : function(speed) { this.speed = speed; }, /* * Trigger the bar go left.If cannot move ,returns false. */ left : function() { var ret = false; if (!this.started) { return false; } var _t = this.tetris; _t.clearActive(); if (!_t.status.bar) { _t.newBar(); } if (!_t.status.offset) { _t.status.offset = [ 0, 0 ]; } var tmpOffset = TetrisUtil.cloneSimpleAry(_t.status.offset); tmpOffset[0]--; var absPos = _t.joinOffsetToPos(_t.status.bar, tmpOffset); if (_t.validateStep(absPos)) { _t.status.offset[0]--; ret = true; } _t.setActive(_t.joinOffsetToPos(_t.status.bar, _t.status.offset)); _t.refresh(); return ret; }, /* * Trigger the bar go right.If cannot move ,returns false. */ right : function() { var ret = false; if (!this.started) { return false; } var _t = this.tetris; _t.clearActive(); if (!_t.status.bar) { _t.newBar(); } if (!_t.status.offset) { _t.status.offset = [ 0, 0 ]; } var tmpOffset = TetrisUtil.cloneSimpleAry(_t.status.offset); tmpOffset[0]++; var absPos = _t.joinOffsetToPos(_t.status.bar, tmpOffset); if (_t.validateStep(absPos)) { _t.status.offset[0]++; ret = true; } _t.setActive(_t.joinOffsetToPos(_t.status.bar, _t.status.offset)); _t.refresh(); return ret; }, /* * Trigger the bar go down.If cannot move ,make it static. */ down : function() { if (!this.started) { return false; } var ret; var _t = this.tetris; _t.clearActive(); if (!_t.status.bar) { _t.newBar(); } if (!_t.status.offset) { _t.status.offset = [ 0, 0 ]; } var tmpOffset = TetrisUtil.cloneSimpleAry(_t.status.offset); tmpOffset[1]++; var absPos = _t.joinOffsetToPos(_t.status.bar, tmpOffset); if (_t.validateStep(absPos)) { _t.status.offset[1]++; ret = true; } else { var _fixPos = _t.joinOffsetToPos(_t.status.bar, _t.status.offset); _t.fixBar(_fixPos); _t.clearActive(); TetrisUtil.clearLine(_t.dataTable); _t.status.offset = [ 0, 0 ]; _t.newBar(); this.startNewBar(); for ( var i = 0; i < _fixPos.length; i++) { if (_fixPos[i][1] <= 2) { this.gameOver(); return false; } } ret = false; } _t.setActive(_t.joinOffsetToPos(_t.status.bar, _t.status.offset)); _t.refresh(); return ret; }, /* * Roll the current bar..If cannot roll ,returns false. */ rollBar : function() { if (!this.started) { return false; } var _t = this.tetris; _t.clearActive(); if (!_t.status.bar) { _t.newBar(); } if (!_t.status.offset) { _t.status.offset = [ 0, 0 ]; } var tmpBar = _t.rollBar(_t.status.bar); var absPos = _t.joinOffsetToPos(tmpBar, _t.status.offset); if (_t.validateStep(absPos)) { _t.status.bar = tmpBar; _t.setActive(_t.joinOffsetToPos(_t.status.bar, _t.status.offset)); _t.refresh(); return true; } else { _t.setActive(_t.joinOffsetToPos(_t.status.bar, _t.status.offset)); return false; } }, /* * Drop the bar on to the bottom and make it static. */ drop : function() { if (!this.started) { return false; } var ret; var _t = this.tetris; _t.clearActive(); if (!_t.status.bar) { _t.newBar(); } if (!_t.status.offset) { _t.status.offset = [ 0, 0 ]; } var absPos = _t.joinOffsetToPos(_t.status.bar, _t.status.offset); _t.clearActive(); var dropHeight = _t.getDropHeight(absPos); _t.status.offset[1] += dropHeight; var _fixPos = _t.joinOffsetToPos(_t.status.bar, _t.status.offset); _t.fixBar(_fixPos); _t.clearActive(); TetrisUtil.clearLine(_t.dataTable); _t.status.offset = [ 0, 0 ]; _t.newBar(); this.startNewBar(); for ( var i = 0; i < _fixPos.length; i++) { if (_fixPos[i][1] == 0) { this.gameOver(); return false; } } _t.setActive(_t.joinOffsetToPos(_t.status.bar, _t.status.offset)); _t.refresh(); ret = false; return ret; }, /* * The function of downing bar. */ control : function() { if (this.started) { this.down(); } }, /* * Triggered by starting a new bar.Default is an empty function. */ startNewBar :TetrisUtil.emptyFunction } /* * KeyBoardController factory. For a tetris game to get a keyboard controller. */ var KeyBoardControllerFactory = { /* * Returns a new controller,with the reference of the tetris. */ getNewController : function(tetris) { return new KeyBoardController(tetris); } } /* * AIControllerFactory factory. For a tetris game to get a AI controller. */ var AIControllerFactory = { getNewController : function(tetris) { return new AIController(tetris); } } /* * AI controller class. */ var AIController = TetrisUtil.createClass(); /* * Extends the controllers' base behavior into AI controller; */ TetrisUtil.mix(AIController.prototype, BasicControllerBehavior); /* * Add the implement of the AI controller. */ TetrisUtil.mix(AIController.prototype, { /* * Init of the controller.Creates the controller and cache in pageContext. */ initialize : function(tetris) { this.tetris = tetris; this.type = Tetris.CONSTS.AI; pageContext.controller[this.tetris.name] = this; }, /* * Calculate the best position and move. */ aiMove : function() { var best = this.calcBest(); this.move(best.x, best.roll); }, /* * Calculate the best position and roll.Iterate every possible situation. */ calcBest : function() { var _t = this.tetris; var bar = TetrisUtil.cloneAry(_t.status.bar); var status = { x :0, roll :0, value :0 }; for ( var roll = 0; roll < 4; roll++) { var offset = [ 0, 0 ]; var absPos = _t.joinOffsetToPos(bar, offset); while (_t.validateStep(absPos)) { var result = this.calc(absPos); if (result > status.value) { status.x = offset[0]; status.roll = roll; status.value = result; } offset[0]--; absPos = _t.joinOffsetToPos(bar, offset); } offset = [ 1, 0 ]; absBar = _t.joinOffsetToPos(bar, offset); while (_t.validateStep(absBar)) { var result = this.calc(absBar); if (result > status.value) { status.x = offset[0]; status.roll = roll; status.value = result; } offset[0]++; absBar = _t.joinOffsetToPos(bar, offset); } bar = _t.rollBar(bar); } return status; }, /* * Calculate the value of an absolute position(didn't drop).The lager,the * better. */ calc : function(absBar) { var _t = this.tetris; var offset = [ 0, _t.getDropHeight(absBar) ]; absBar = _t.joinOffsetToPos(absBar, offset); var copyTable = TetrisUtil.cloneAry(_t.dataTable); TetrisUtil.mergePos(copyTable, absBar, function() { return 1; }); return this.calcValue(copyTable, absBar); }, /* * Calculate the value of an absolute position(dropped).The lager,the * better. */ calcValue : function(fixedTable, absBar) { var value = 1; var empty = 1; var shape = 0; var floor = 1; var beside = 1; TetrisUtil.mergePos(fixedTable, absBar, function() { return arguments[0] + 2; }); for ( var i = 0; i < absBar.length; i++) { floor += absBar[i][1]; if (typeof fixedTable[absBar[i][0]][absBar[i][1] + 1] == "undefined") { shape += 2; } else { if (fixedTable[absBar[i][0]][absBar[i][1] + 1] == 1) { shape += 2; } else if (fixedTable[absBar[i][0]][absBar[i][1] + 1] == 0) { empty++; } else if (fixedTable[absBar[i][0]][absBar[i][1] + 1] == 3) { shape -= 0.2; } for ( var j = absBar[i][1] + 2; j < fixedTable.length; j++) { if (fixedTable[absBar[i][0]][absBar[i][j]] == 0) { empty += 1; } } } if ((typeof fixedTable[absBar[i][0] + 1] == "undefined") || (typeof fixedTable[absBar[i][0] - 1] == "undefined")) { beside++; } else if (fixedTable[absBar[i][0] + 1][absBar[i][1]] == 1) { beside++; } else if (fixedTable[absBar[i][0] - 1][absBar[i][1]] == 1) { beside++; } } var rowsFilld = 0; var count = 0; for ( var j = 0; j < this.tetris.rect.height; j++) { var sum = TetrisUtil.sumAryX(fixedTable, j); if (sum > 0) { count++; } rowsFilld += sum; } rowsFilld = rowsFilld / count; var lines = TetrisUtil.clearLine(fixedTable); this.tetris.refresh(); var ret = this.AIFunction(floor, lines, shape, beside, rowsFilld, empty); return ret; }, /* * Internal function.while a new bar started ,it is invoked. */ startNewBar : function() { this.aiMove(); }, /* * Give x offset and times of rolling,to move to the specified position. */ move : function(x, roll) { var _s = this.tetris.status; for ( var i = 0; i < roll; i++) { if (!this.rollBar()) { return; } } if (x > _s.offset[0]) { while (x > _s.offset[0]) { if (!this.right()) { return; } } } else if (x < _s.offset[0]) { while (x < _s.offset[0]) { if (!this.left()) { return; } } } }, /* * The function to calculate the position weight. */ AIFunction : function(floor, lines, shape, beside, rowsFilld, empty) { return Math.pow(lines * lines + 1, 3) * Math.pow(shape, 3) * Math.pow(beside + 2, 5) * Math.pow(rowsFilld, 2) * Math.pow(floor, 5) / (Math.pow(empty, 4)); } }); /* * Keyboard controller class. */ var KeyBoardController = TetrisUtil.createClass(); /* * Extends the controllers' base behavior into Keyboard controller; */ TetrisUtil.mix(KeyBoardController.prototype, BasicControllerBehavior); /* * Implements the Keyboard controller. */ TetrisUtil.mix(KeyBoardController.prototype, { /* * Init of the controller.Creates the controller and cache in pageContext * whith a default key map. */ initialize : function(tetris) { this.tetris = tetris; this.type = Tetris.CONSTS.KEYBOARD; pageContext.controller[this.tetris.name] = this; this.setKeyMap( { UP :38, DOWN :40, LEFT :37, RIGHT :39, DROP :32 }); }, /* * Replace the old key map with a new one. */ setKeyMap : function(keyMap) { pageContext.keyMap[this.tetris.name] = keyMap; }, /* * Dispatch the event to the specified method to control the tetris. */ move : function(keyCode) { var name = this.tetris.name; switch (keyCode) { case pageContext.keyMap[name].UP: this.rollBar(); break; case pageContext.keyMap[name].DOWN: this.down(); break; case pageContext.keyMap[name].LEFT: this.left(); break; case pageContext.keyMap[name].RIGHT: this.right(); break; case pageContext.keyMap[name].DROP: this.drop(); break; } } }); /* * The keyboard event dispatcher . */ var EventDispatcher = function() { for ( var name in pageContext.controller) { if (pageContext.controller[name].type == Tetris.CONSTS.KEYBOARD) { pageContext.controller[name].move(event.keyCode); } } }; /* * Context of the page. */ var pageContext = { tetris : {}, controller : {}, keyMap : {} }; /* * Load method on page complete.AI */ function load() { var tetris = new Tetris("myTetris1", "render1", 10, 19); window.ctrl1 = tetris.buildController(AIControllerFactory); window.ctrl1.setSpeed(25); ctrl1.start(); } //Keyboard //function load() { // var tetris = new Tetris("myTetris1", "render1", 10, 19); // window.ctrl1 = tetris.buildController(KeyBoardControllerFactory); // ctrl1.setKeyMap({ // UP:87, // DOWN:83, // LEFT:65, // RIGHT:68, // DROP:18 // }); // ctrl1.start(); //}
洋洋洒洒1000行。。自己留个底吧
相关推荐
【Java版俄罗斯方块】 增加保存配置信息到文件的功能,声音设置、显示设置、关卡选择等配置信息在修改后将会保存在jar包同级目录下(以jar相同的文件名+.cfg后缀保存) 2010-10-05 【Java版俄罗斯方块】 这个程序...
本代码是俄罗斯方块游戏的Python实现,并带有一个简单的自动玩游戏的人工智能。 ## 安装依赖 - python3 - PyQt5 - NumPy ## 使用方法 * `tetris_game.py` 是主应用程序。 * `tetris_model.py` 是此游戏的数据...
C#俄罗斯方块 数十年的经典,学习游戏设计者的最爱!本程序新增了完善的配置功能,可以自己设计各种方块 C#截屏 可QQ截屏功能差不多的小工具,自己选择区域,保存位置 C#五子棋人机对战 五子棋游戏常作为棋类...
基于JAVA人工智能俄罗斯方块的简单应用
实现了一个简单的俄罗斯方块AI,用于预测并选择最优的形状放置位置,以尽可能消除更多的方块行。完整的代码下:(包含注释) tetris_game.py是主函数,主要为应用界面的主函数。 tetris_model.py是游戏的数据模型。 ...
俄罗斯方块游戏 它是Tetris Game的python实现工具,是一个简单的AI可以自动玩游戏。 需要安装python3,PyQt5和NumPy。 tetris_game.py是主要应用程序。 tetris_model.py是此游戏的数据模型。 tetris_ai.py是AI...
这是一个俄罗斯方块算法部分, 可以替换原有算法,主要用于模拟机器人玩俄罗斯方块,对于随机生成的形状,计算摆放位置,达到最优的消除效果,最终比较的结果是消除多少行。 有公开的比赛,已经可以消除非常多的行,...
java俄罗斯盒子源码最少代码100ProjectsOfCode 实用知识建设项目清单。 由于这些项目旨在增加您的知识基础,因此它们具有一定的挑战性。...主要涉及人工智能或机器学习的项目。 如果您正在考虑申请任何与 AI 相关的工
俄罗斯方块 AI 环境马特·布伦曼这是我在 2014 年秋季塔夫茨大学高级机器学习课程的最后一个项目。它是一个俄罗斯方块 AI 环境,让用户可以定义代理并轻松将它们插入系统。 这是 ML/AI 学生尝试构建游戏程序的一种...
Java版2048,这是参考 小翼 的俄罗斯方块教程做的一个小东西。界面还可以,原创,加入了简单AI,只能跑到512多一点,运气好的话可以跑到1024。有动画效果,不是生硬的直接显示。在其中运用的的MVC思想还将就。注释...
java俄罗斯盒子源码最少代码100ProjectsOfCode 完成 100ProjectsOfCode 实用知识建设项目清单。 由于这些项目旨在增加您的知识基础,因此它们具有一定的挑战性。...主要涉及人工智能或机器学习的项目。
浏览器俄罗斯方块 使用的技术: JavaScript ...面向对象的设计 玩浏览器俄罗斯方块 这是我正在研究的普通JavaScript Tetris克隆,将面向对象的设计模式与JavaScript构造函数对象,原型和...人工智能 大量抛光 多人游戏
游戏部分:用非常简单的AI获得了俄罗斯方块游戏的Matlab代码。 尝试设计一种新的AI并弄清游戏的核心功能。 第八周: 目标:实现RGB2YCrCb,YCrCb2RGB,并在计算机屏幕和投影仪上显示720 * 480图像。 在AI中添加第二...
支持解压tgz、支持在线更新、支持换肤、附带俄罗斯方块游戏(双击"关于"窗口内的程序图标启动)。==========更新信息 (*很不同 +增加功能 -去除功能 #bug修复)v 2.03+ 服务器运行模式不需要服务器额外支持...
俄罗斯方块AI设计文档 一.概要 使用了2种AI算法: 一种是经典的Pierre Dellacherie算法 一种基于基于深度搜索的算法: 由于时间因素,只测试了一次Pierre Dellacherie算法,消行数13W+ 第2种算法没有花时间去测试,理论上...
在两个播放器之间切换,或让用户玩计算机(人工智能或障碍物) 获胜的设计逻辑并以视觉方式显示哪个玩家获胜 包括单独HTML / CSS / JavaScript文件 坚持使用KISS(保持简单愚蠢)和DRY(不要重复自己)原则 使用...
俄罗斯方块:通过清除行来收集点,不要让屏幕充满块。 控件一般是上下左右和空格键; 它们不是很复杂的游戏。 单击一个游戏开始玩,然后单击其他地方暂停它。 如何构建 克隆回购 命中sbt packageJS 在您最喜欢的...
java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密 Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。 设定...
java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密 Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。 ...