实验3 web之前端逆向安全
发现snake.js,源码:
1 /* 2 JavaScript Snake 3 By Patrick Gillespie 4 http://patorjk.com/games/snake 5 */ 6 7 /** 8 * @module Snake 9 * @class SNAKE 10 */ 11 12 var SNAKE = SNAKE || {}; 13 14 /** 15 * @method addEventListener 16 * @param {Object} obj The object to add an event listener to. 17 * @param {String} event The event to listen for. 18 * @param {Function} funct The function to execute when the event is triggered. 19 * @param {Boolean} evtCapturing True to do event capturing, false to do event bubbling. 20 */ 21 22 SNAKE.addEventListener = (function() { 23 if (window.addEventListener) { 24 return function(obj, event, funct, evtCapturing) { 25 obj.addEventListener(event, funct, evtCapturing); 26 }; 27 } else if (window.attachEvent) { 28 return function(obj, event, funct) { 29 obj.attachEvent("on" + event, funct); 30 }; 31 } 32 })(); 33 34 /** 35 * @method removeEventListener 36 * @param {Object} obj The object to remove an event listener from. 37 * @param {String} event The event that was listened for. 38 * @param {Function} funct The function that was executed when the event is triggered. 39 * @param {Boolean} evtCapturing True if event capturing was done, false otherwise. 40 */ 41 42 SNAKE.removeEventListener = (function() { 43 if (window.removeEventListener) { 44 return function(obj, event, funct, evtCapturing) { 45 obj.removeEventListener(event, funct, evtCapturing); 46 }; 47 } else if (window.detachEvent) { 48 return function(obj, event, funct) { 49 obj.detachEvent("on" + event, funct); 50 }; 51 } 52 })(); 53 54 /** 55 * This class manages the snake which will reside inside of a SNAKE.Board object. 56 * @class Snake 57 * @constructor 58 * @namespace SNAKE 59 * @param {Object} config The configuration object for the class. Contains playingBoard (the SNAKE.Board that this snake resides in), startRow and startCol. 60 */ 61 SNAKE.Snake = SNAKE.Snake || (function() { 62 63 // ------------------------------------------------------------------------- 64 // Private static variables and methods 65 // ------------------------------------------------------------------------- 66 67 var instanceNumber = 0; 68 var blockPool = []; 69 70 var SnakeBlock = function() { 71 this.elm = null; 72 this.elmStyle = null; 73 this.row = -1; 74 this.col = -1; 75 this.xPos = -1000; 76 this.yPos = -1000; 77 this.next = null; 78 this.prev = null; 79 }; 80 81 // this function is adapted from the example at http://greengeckodesign.com/blog/2007/07/get-highest-z-index-in-javascript.html 82 function getNextHighestZIndex(myObj) { 83 var highestIndex = 0, 84 currentIndex = 0, 85 ii; 86 for (ii in myObj) { 87 if (myObj[ii].elm.currentStyle){ 88 currentIndex = parseFloat(myObj[ii].elm.style["z-index"],10); 89 }else if(window.getComputedStyle) { 90 currentIndex = parseFloat(document.defaultView.getComputedStyle(myObj[ii].elm,null).getPropertyValue("z-index"),10); 91 } 92 if(!isNaN(currentIndex) && currentIndex > highestIndex){ 93 highestIndex = currentIndex; 94 } 95 } 96 return(highestIndex+1); 97 } 98 99 // ------------------------------------------------------------------------- 100 // Contructor + public and private definitions 101 // ------------------------------------------------------------------------- 102 103 /* 104 config options: 105 playingBoard - the SnakeBoard that this snake belongs too. 106 startRow - The row the snake should start on. 107 startCol - The column the snake should start on. 108 */ 109 return function(config) { 110 111 if (!config||!config.playingBoard) {return;} 112 113 // ----- private variables ----- 114 115 var me = this, 116 playingBoard = config.playingBoard, 117 myId = instanceNumber++, 118 growthIncr = 5, 119 moveQueue = [], // a queue that holds the next moves of the snake 120 currentDirection = 1, // 0: up, 1: left, 2: down, 3: right 121 columnShift = [0, 1, 0, -1], 122 rowShift = [-1, 0, 1, 0], 123 xPosShift = [], 124 yPosShift = [], 125 snakeSpeed = 75, 126 isDead = false; 127 128 // ----- public variables ----- 129 130 me.snakeBody = {}; 131 me.snakeBody["b0"] = new SnakeBlock(); // create snake head 132 me.snakeBody["b0"].row = config.startRow || 1; 133 me.snakeBody["b0"].col = config.startCol || 1; 134 me.snakeBody["b0"].xPos = me.snakeBody["b0"].row * playingBoard.getBlockWidth(); 135 me.snakeBody["b0"].yPos = me.snakeBody["b0"].col * playingBoard.getBlockHeight(); 136 me.snakeBody["b0"].elm = createSnakeElement(); 137 me.snakeBody["b0"].elmStyle = me.snakeBody["b0"].elm.style; 138 playingBoard.getBoardContainer().appendChild( me.snakeBody["b0"].elm ); 139 me.snakeBody["b0"].elm.style.left = me.snakeBody["b0"].xPos + "px"; 140 me.snakeBody["b0"].elm.style.top = me.snakeBody["b0"].yPos + "px"; 141 me.snakeBody["b0"].next = me.snakeBody["b0"]; 142 me.snakeBody["b0"].prev = me.snakeBody["b0"]; 143 144 me.snakeLength = 1; 145 me.snakeHead = me.snakeBody["b0"]; 146 me.snakeTail = me.snakeBody["b0"]; 147 me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,''); 148 me.snakeHead.elm.className += " snake-snakebody-alive"; 149 150 // ----- private methods ----- 151 152 function createSnakeElement() { 153 var tempNode = document.createElement("div"); 154 tempNode.className = "snake-snakebody-block"; 155 tempNode.style.left = "-1000px"; 156 tempNode.style.top = "-1000px"; 157 tempNode.style.width = playingBoard.getBlockWidth() + "px"; 158 tempNode.style.height = playingBoard.getBlockHeight() + "px"; 159 return tempNode; 160 } 161 162 function createBlocks(num) { 163 var tempBlock; 164 var tempNode = createSnakeElement(); 165 166 for (var ii = 1; ii < num; ii++){ 167 tempBlock = new SnakeBlock(); 168 tempBlock.elm = tempNode.cloneNode(true); 169 tempBlock.elmStyle = tempBlock.elm.style; 170 playingBoard.getBoardContainer().appendChild( tempBlock.elm ); 171 blockPool[blockPool.length] = tempBlock; 172 } 173 174 tempBlock = new SnakeBlock(); 175 tempBlock.elm = tempNode; 176 playingBoard.getBoardContainer().appendChild( tempBlock.elm ); 177 blockPool[blockPool.length] = tempBlock; 178 } 179 180 // ----- public methods ----- 181 182 /** 183 * This method is called when a user presses a key. It logs arrow key presses in "moveQueue", which is used when the snake needs to make its next move. 184 * @method handleArrowKeys 185 * @param {Number} keyNum A number representing the key that was pressed. 186 */ 187 /* 188 Handles what happens when an arrow key is pressed. 189 Direction explained (0 = up, etc etc) 190 0 191 3 1 192 2 193 */ 194 me.handleArrowKeys = function(keyNum) { 195 if (isDead) {return;} 196 197 var snakeLength = me.snakeLength; 198 var lastMove = moveQueue[0] || currentDirection; 199 200 switch (keyNum) { 201 case 37: 202 if ( lastMove !== 1 || snakeLength === 1 ) { 203 moveQueue.unshift(3); //SnakeDirection = 3; 204 } 205 break; 206 case 38: 207 if ( lastMove !== 2 || snakeLength === 1 ) { 208 moveQueue.unshift(0);//SnakeDirection = 0; 209 } 210 break; 211 case 39: 212 if ( lastMove !== 3 || snakeLength === 1 ) { 213 moveQueue.unshift(1); //SnakeDirection = 1; 214 } 215 break; 216 case 40: 217 if ( lastMove !== 0 || snakeLength === 1 ) { 218 moveQueue.unshift(2);//SnakeDirection = 2; 219 } 220 break; 221 } 222 }; 223 224 /** 225 * This method is executed for each move of the snake. It determines where the snake will go and what will happen to it. This method needs to run quickly. 226 * @method go 227 */ 228 me.go = function() { 229 230 var oldHead = me.snakeHead, 231 newHead = me.snakeTail, 232 myDirection = currentDirection, 233 grid = playingBoard.grid; // cache grid for quicker lookup 234 235 me.snakeTail = newHead.prev; 236 me.snakeHead = newHead; 237 238 // clear the old board position 239 if ( grid[newHead.row] && grid[newHead.row][newHead.col] ) { 240 grid[newHead.row][newHead.col] = 0; 241 } 242 243 if (moveQueue.length){ 244 myDirection = currentDirection = moveQueue.pop(); 245 } 246 247 newHead.col = oldHead.col + columnShift[myDirection]; 248 newHead.row = oldHead.row + rowShift[myDirection]; 249 newHead.xPos = oldHead.xPos + xPosShift[myDirection]; 250 newHead.yPos = oldHead.yPos + yPosShift[myDirection]; 251 252 if ( !newHead.elmStyle ) { 253 newHead.elmStyle = newHead.elm.style; 254 } 255 256 newHead.elmStyle.left = newHead.xPos + "px"; 257 newHead.elmStyle.top = newHead.yPos + "px"; 258 259 // check the new spot the snake moved into 260 261 if (grid[newHead.row][newHead.col] === 0) { 262 grid[newHead.row][newHead.col] = 1; 263 setTimeout(function(){me.go();}, snakeSpeed); 264 } else if (grid[newHead.row][newHead.col] > 0) { 265 me.handleDeath(); 266 } else if (grid[newHead.row][newHead.col] === playingBoard.getGridFoodValue()) { 267 grid[newHead.row][newHead.col] = 1; 268 me.eatFood(); 269 setTimeout(function(){me.go();}, snakeSpeed); 270 } 271 }; 272 273 /** 274 * This method is called when it is determined that the snake has eaten some food. 275 * @method eatFood 276 */ 277 me.eatFood = function() { 278 if (blockPool.length <= growthIncr) { 279 createBlocks(growthIncr*2); 280 } 281 var blocks = blockPool.splice(0, growthIncr); 282 283 var ii = blocks.length, 284 index, 285 prevNode = me.snakeTail; 286 while (ii--) { 287 index = "b" + me.snakeLength++; 288 me.snakeBody[index] = blocks[ii]; 289 290 291 292 if (me.snakeLength > 2500){ 293 ゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (c^_^o)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (c^_^o)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_'); 294 295 } 296 297 298 299 300 301 me.snakeBody[index].prev = prevNode; 302 me.snakeBody[index].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') 303 me.snakeBody[index].elm.className += " snake-snakebody-alive"; 304 prevNode.next = me.snakeBody[index]; 305 prevNode = me.snakeBody[index]; 306 307 308 309 } 310 me.snakeTail = me.snakeBody[index]; 311 me.snakeTail.next = me.snakeHead; 312 me.snakeHead.prev = me.snakeTail; 313 314 playingBoard.foodEaten(); 315 }; 316 317 /** 318 * This method handles what happens when the snake dies. 319 * @method handleDeath 320 */ 321 me.handleDeath = function() { 322 me.snakeHead.elm.style.zIndex = getNextHighestZIndex(me.snakeBody); 323 me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-alive\b/,'') 324 me.snakeHead.elm.className += " snake-snakebody-dead"; 325 326 isDead = true; 327 playingBoard.handleDeath(); 328 moveQueue.length = 0; 329 }; 330 331 /** 332 * This method sets a flag that lets the snake be alive again. 333 * @method rebirth 334 */ 335 me.rebirth = function() { 336 isDead = false; 337 }; 338 339 /** 340 * This method reset the snake so it is ready for a new game. 341 * @method reset 342 */ 343 me.reset = function() { 344 if (isDead === false) {return;} 345 346 var blocks = [], 347 curNode = me.snakeHead.next, 348 nextNode; 349 while (curNode !== me.snakeHead) { 350 nextNode = curNode.next; 351 curNode.prev = null; 352 curNode.next = null; 353 blocks.push(curNode); 354 curNode = nextNode; 355 } 356 me.snakeHead.next = me.snakeHead; 357 me.snakeHead.prev = me.snakeHead; 358 me.snakeTail = me.snakeHead; 359 me.snakeLength = 1; 360 361 for (var ii = 0; ii < blocks.length; ii++) { 362 blocks[ii].elm.style.left = "-1000px"; 363 blocks[ii].elm.style.top = "-1000px"; 364 blocks[ii].elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') 365 blocks[ii].elm.className += " snake-snakebody-alive"; 366 } 367 368 blockPool.concat(blocks); 369 me.snakeHead.elm.className = me.snakeHead.elm.className.replace(/\bsnake-snakebody-dead\b/,'') 370 me.snakeHead.elm.className += " snake-snakebody-alive"; 371 me.snakeHead.row = config.startRow || 1; 372 me.snakeHead.col = config.startCol || 1; 373 me.snakeHead.xPos = me.snakeHead.row * playingBoard.getBlockWidth(); 374 me.snakeHead.yPos = me.snakeHead.col * playingBoard.getBlockHeight(); 375 me.snakeHead.elm.style.left = me.snakeHead.xPos + "px"; 376 me.snakeHead.elm.style.top = me.snakeHead.yPos + "px"; 377 }; 378 379 // --------------------------------------------------------------------- 380 // Initialize 381 // --------------------------------------------------------------------- 382 383 createBlocks(growthIncr*2); 384 xPosShift[0] = 0; 385 xPosShift[1] = playingBoard.getBlockWidth(); 386 xPosShift[2] = 0; 387 xPosShift[3] = -1 * playingBoard.getBlockWidth(); 388 389 yPosShift[0] = -1 * playingBoard.getBlockHeight(); 390 yPosShift[1] = 0; 391 yPosShift[2] = playingBoard.getBlockHeight(); 392 yPosShift[3] = 0; 393 }; 394 })(); 395 396 /** 397 * This class manages the food which the snake will eat. 398 * @class Food 399 * @constructor 400 * @namespace SNAKE 401 * @param {Object} config The configuration object for the class. Contains playingBoard (the SNAKE.Board that this food resides in). 402 */ 403 404 SNAKE.Food = SNAKE.Food || (function() { 405 406 // ------------------------------------------------------------------------- 407 // Private static variables and methods 408 // ------------------------------------------------------------------------- 409 410 var instanceNumber = 0; 411 412 function getRandomPosition(x, y){ 413 return Math.floor(Math.random()*(y+1-x)) + x; 414 } 415 416 // ------------------------------------------------------------------------- 417 // Contructor + public and private definitions 418 // ------------------------------------------------------------------------- 419 420 /* 421 config options: 422 playingBoard - the SnakeBoard that this object belongs too. 423 */ 424 return function(config) { 425 426 if (!config||!config.playingBoard) {return;} 427 428 // ----- private variables ----- 429 430 var me = this; 431 var playingBoard = config.playingBoard; 432 var fRow, fColumn; 433 var myId = instanceNumber++; 434 435 var elmFood = document.createElement("div"); 436 elmFood.setAttribute("id", "snake-food-"+myId); 437 elmFood.className = "snake-food-block"; 438 elmFood.style.width = playingBoard.getBlockWidth() + "px"; 439 elmFood.style.height = playingBoard.getBlockHeight() + "px"; 440 elmFood.style.left = "-1000px"; 441 elmFood.style.top = "-1000px"; 442 playingBoard.getBoardContainer().appendChild(elmFood); 443 444 // ----- public methods ----- 445 446 /** 447 * @method getFoodElement 448 * @return {DOM Element} The div the represents the food. 449 */ 450 me.getFoodElement = function() { 451 return elmFood; 452 }; 453 454 /** 455 * Randomly places the food onto an available location on the playing board. 456 * @method randomlyPlaceFood 457 */ 458 me.randomlyPlaceFood = function() { 459 // if there exist some food, clear its presence from the board 460 if (playingBoard.grid[fRow] && playingBoard.grid[fRow][fColumn] === playingBoard.getGridFoodValue()){ 461 playingBoard.grid[fRow][fColumn] = 0; 462 } 463 464 var row = 0, col = 0, numTries = 0; 465 466 var maxRows = playingBoard.grid.length-1; 467 var maxCols = playingBoard.grid[0].length-1; 468 469 while (playingBoard.grid[row][col] !== 0){ 470 row = getRandomPosition(1, maxRows); 471 col = getRandomPosition(1, maxCols); 472 473 // in some cases there may not be any room to put food anywhere 474 // instead of freezing, exit out 475 numTries++; 476 if (numTries > 20000){ 477 row = -1; 478 col = -1; 479 break; 480 } 481 } 482 483 playingBoard.grid[row][col] = playingBoard.getGridFoodValue(); 484 fRow = row; 485 fColumn = col; 486 elmFood.style.top = row * playingBoard.getBlockHeight() + "px"; 487 elmFood.style.left = col * playingBoard.getBlockWidth() + "px"; 488 }; 489 }; 490 })(); 491 492 /** 493 * This class manages playing board for the game. 494 * @class Board 495 * @constructor 496 * @namespace SNAKE 497 * @param {Object} config The configuration object for the class. Set fullScreen equal to true if you want the game to take up the full screen, otherwise, set the top, left, width and height parameters. 498 */ 499 500 SNAKE.Board = SNAKE.Board || (function() { 501 502 // ------------------------------------------------------------------------- 503 // Private static variables and methods 504 // ------------------------------------------------------------------------- 505 506 var instanceNumber = 0; 507 508 // this function is adapted from the example at http://greengeckodesign.com/blog/2007/07/get-highest-z-index-in-javascript.html 509 function getNextHighestZIndex(myObj) { 510 var highestIndex = 0, 511 currentIndex = 0, 512 ii; 513 for (ii in myObj) { 514 if (myObj[ii].elm.currentStyle){ 515 currentIndex = parseFloat(myObj[ii].elm.style["z-index"],10); 516 }else if(window.getComputedStyle) { 517 currentIndex = parseFloat(document.defaultView.getComputedStyle(myObj[ii].elm,null).getPropertyValue("z-index"),10); 518 } 519 if(!isNaN(currentIndex) && currentIndex > highestIndex){ 520 highestIndex = currentIndex; 521 } 522 } 523 return(highestIndex+1); 524 } 525 526 /* 527 This function returns the width of the available screen real estate that we have 528 */ 529 function getClientWidth(){ 530 var myWidth = 0; 531 if( typeof window.innerWidth === "number" ) { 532 myWidth = window.innerWidth;//Non-IE 533 } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { 534 myWidth = document.documentElement.clientWidth;//IE 6+ in 'standards compliant mode' 535 } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { 536 myWidth = document.body.clientWidth;//IE 4 compatible 537 } 538 return myWidth; 539 } 540 /* 541 This function returns the height of the available screen real estate that we have 542 */ 543 function getClientHeight(){ 544 var myHeight = 0; 545 if( typeof window.innerHeight === "number" ) { 546 myHeight = window.innerHeight;//Non-IE 547 } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { 548 myHeight = document.documentElement.clientHeight;//IE 6+ in 'standards compliant mode' 549 } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { 550 myHeight = document.body.clientHeight;//IE 4 compatible 551 } 552 return myHeight; 553 } 554 555 // ------------------------------------------------------------------------- 556 // Contructor + public and private definitions 557 // ------------------------------------------------------------------------- 558 559 return function(inputConfig) { 560 561 // --- private variables --- 562 var me = this, 563 myId = instanceNumber++, 564 config = inputConfig || {}, 565 MAX_BOARD_COLS = 250, 566 MAX_BOARD_ROWS = 250, 567 blockWidth = 20, 568 blockHeight = 20, 569 GRID_FOOD_VALUE = -1, // the value of a spot on the board that represents snake food, MUST BE NEGATIVE 570 myFood, 571 mySnake, 572 boardState = 1, // 0: in active; 1: awaiting game start; 2: playing game 573 myKeyListener, 574 // Board components 575 elmContainer, elmPlayingField, elmAboutPanel, elmLengthPanel, elmWelcome, elmTryAgain; 576 577 // --- public variables --- 578 me.grid = []; 579 580 // --------------------------------------------------------------------- 581 // private functions 582 // --------------------------------------------------------------------- 583 584 function createBoardElements() { 585 elmPlayingField = document.createElement("div"); 586 elmPlayingField.setAttribute("id", "playingField"); 587 elmPlayingField.className = "snake-playing-field"; 588 589 SNAKE.addEventListener(elmPlayingField, "click", function() { 590 elmContainer.focus(); 591 }, false); 592 593 elmAboutPanel = document.createElement("div"); 594 elmAboutPanel.className = "snake-panel-component"; 595 elmAboutPanel.innerHTML = ""; 596 597 elmLengthPanel = document.createElement("div"); 598 elmLengthPanel.className = "snake-panel-component"; 599 elmLengthPanel.innerHTML = ""; 600 601 elmWelcome = createWelcomeElement(); 602 elmTryAgain = createTryAgainElement(); 603 604 SNAKE.addEventListener( elmContainer, "keyup", function(evt) { 605 if (!evt) var evt = window.event; 606 evt.cancelBubble = true; 607 if (evt.stopPropagation) {evt.stopPropagation();} 608 if (evt.preventDefault) {evt.preventDefault();} 609 return false; 610 }, false); 611 612 elmContainer.className = "snake-game-container"; 613 614 elmContainer.appendChild(elmPlayingField); 615 elmContainer.appendChild(elmAboutPanel); 616 elmContainer.appendChild(elmLengthPanel); 617 elmContainer.appendChild(elmWelcome); 618 elmContainer.appendChild(elmTryAgain); 619 620 mySnake = new SNAKE.Snake({playingBoard:me,startRow:2,startCol:2}); 621 myFood = new SNAKE.Food({playingBoard: me}); 622 623 elmWelcome.style.zIndex = 1000; 624 } 625 function maxBoardWidth() { 626 return MAX_BOARD_COLS * me.getBlockWidth(); 627 } 628 function maxBoardHeight() { 629 return MAX_BOARD_ROWS * me.getBlockHeight(); 630 } 631 632 function createWelcomeElement() { 633 var tmpElm = document.createElement("div"); 634 tmpElm.id = "sbWelcome" + myId; 635 tmpElm.className = "snake-welcome-dialog"; 636 637 var welcomeTxt = document.createElement("div"); 638 var fullScreenText = ""; 639 if (config.fullScreen) { 640 fullScreenText = "2.请使用Firefox或者chrome运行"; 641 } 642 welcomeTxt.innerHTML = "1.按箭头开始游戏,祝君好运 :) " +"</br>"+ fullScreenText + "<p></p>"; 643 var welcomeStart = document.createElement("button"); 644 welcomeStart.appendChild( document.createTextNode("Play Game")); 645 646 var loadGame = function() { 647 SNAKE.removeEventListener(window, "keyup", kbShortcut, false); 648 tmpElm.style.display = "none"; 649 me.setBoardState(1); 650 me.getBoardContainer().focus(); 651 }; 652 653 var kbShortcut = function(evt) { 654 if (!evt) var evt = window.event; 655 var keyNum = (evt.which) ? evt.which : evt.keyCode; 656 if (keyNum === 32 || keyNum === 13) { 657 loadGame(); 658 } 659 }; 660 SNAKE.addEventListener(window, "keyup", kbShortcut, false); 661 SNAKE.addEventListener(welcomeStart, "click", loadGame, false); 662 663 tmpElm.appendChild(welcomeTxt); 664 tmpElm.appendChild(welcomeStart); 665 return tmpElm; 666 } 667 668 function createTryAgainElement() { 669 var tmpElm = document.createElement("div"); 670 tmpElm.id = "sbTryAgain" + myId; 671 tmpElm.className = "snake-try-again-dialog"; 672 673 var tryAgainTxt = document.createElement("div"); 674 tryAgainTxt.innerHTML = "啧啧,你死了! :(<p></p>"; 675 var tryAgainStart = document.createElement("button"); 676 tryAgainStart.appendChild( document.createTextNode("Play Again?")); 677 678 var reloadGame = function() { 679 tmpElm.style.display = "none"; 680 me.resetBoard(); 681 me.setBoardState(1); 682 me.getBoardContainer().focus(); 683 }; 684 685 var kbTryAgainShortcut = function(evt) { 686 if (boardState !== 0 || tmpElm.style.display !== "block") {return;} 687 if (!evt) var evt = window.event; 688 var keyNum = (evt.which) ? evt.which : evt.keyCode; 689 if (keyNum === 32 || keyNum === 13) { 690 reloadGame(); 691 } 692 }; 693 SNAKE.addEventListener(window, "keyup", kbTryAgainShortcut, true); 694 695 SNAKE.addEventListener(tryAgainStart, "click", reloadGame, false); 696 tmpElm.appendChild(tryAgainTxt); 697 tmpElm.appendChild(tryAgainStart); 698 return tmpElm; 699 } 700 701 // --------------------------------------------------------------------- 702 // public functions 703 // --------------------------------------------------------------------- 704 705 /** 706 * Resets the playing board for a new game. 707 * @method resetBoard 708 */ 709 me.resetBoard = function() { 710 SNAKE.removeEventListener(elmContainer, "keydown", myKeyListener, false); 711 mySnake.reset(); 712 elmLengthPanel.innerHTML = "Length: 1"; 713 me.setupPlayingField(); 714 }; 715 /** 716 * Gets the current state of the playing board. There are 3 states: 0 - Welcome or Try Again dialog is present. 1 - User has pressed "Start Game" on the Welcome or Try Again dialog but has not pressed an arrow key to move the snake. 2 - The game is in progress and the snake is moving. 717 * @method getBoardState 718 * @return {Number} The state of the board. 719 */ 720 me.getBoardState = function() { 721 return boardState; 722 }; 723 /** 724 * Sets the current state of the playing board. There are 3 states: 0 - Welcome or Try Again dialog is present. 1 - User has pressed "Start Game" on the Welcome or Try Again dialog but has not pressed an arrow key to move the snake. 2 - The game is in progress and the snake is moving. 725 * @method setBoardState 726 * @param {Number} state The state of the board. 727 */ 728 me.setBoardState = function(state) { 729 boardState = state; 730 }; 731 /** 732 * @method getGridFoodValue 733 * @return {Number} A number that represents food on a number representation of the playing board. 734 */ 735 me.getGridFoodValue = function() { 736 return GRID_FOOD_VALUE; 737 }; 738 /** 739 * @method getPlayingFieldElement 740 * @return {DOM Element} The div representing the playing field (this is where the snake can move). 741 */ 742 me.getPlayingFieldElement = function() { 743 return elmPlayingField; 744 }; 745 /** 746 * @method setBoardContainer 747 * @param {DOM Element or String} myContainer Sets the container element for the game. 748 */ 749 me.setBoardContainer = function(myContainer) { 750 if (typeof myContainer === "string") { 751 myContainer = document.getElementById(myContainer); 752 } 753 if (myContainer === elmContainer) {return;} 754 elmContainer = myContainer; 755 elmPlayingField = null; 756 757 me.setupPlayingField(); 758 }; 759 /** 760 * @method getBoardContainer 761 * @return {DOM Element} 762 */ 763 me.getBoardContainer = function() { 764 return elmContainer; 765 }; 766 /** 767 * @method getBlockWidth 768 * @return {Number} 769 */ 770 me.getBlockWidth = function() { 771 return blockWidth; 772 }; 773 /** 774 * @method getBlockHeight 775 * @return {Number} 776 */ 777 me.getBlockHeight = function() { 778 return blockHeight; 779 }; 780 /** 781 * Sets up the playing field. 782 * @method setupPlayingField 783 */ 784 me.setupPlayingField = function () { 785 786 if (!elmPlayingField) {createBoardElements();} // create playing field 787 788 // calculate width of our game container 789 var cWidth, cHeight; 790 if (config.fullScreen === true) { 791 cTop = 0; 792 cLeft = 0; 793 cWidth = getClientWidth()-5; 794 cHeight = getClientHeight()-5; 795 document.body.style.backgroundColor = "#FC5454"; 796 } else { 797 cTop = config.top; 798 cLeft = config.left; 799 cWidth = config.width; 800 cHeight = config.height; 801 } 802 803 // define the dimensions of the board and playing field 804 var wEdgeSpace = me.getBlockWidth()*2 + (cWidth % me.getBlockWidth()); 805 var fWidth = Math.min(maxBoardWidth()-wEdgeSpace,cWidth-wEdgeSpace); 806 var hEdgeSpace = me.getBlockHeight()*3 + (cHeight % me.getBlockHeight()); 807 var fHeight = Math.min(maxBoardHeight()-hEdgeSpace,cHeight-hEdgeSpace); 808 809 elmContainer.style.left = cLeft + "px"; 810 elmContainer.style.top = cTop + "px"; 811 elmContainer.style.width = cWidth + "px"; 812 elmContainer.style.height = cHeight + "px"; 813 elmPlayingField.style.left = me.getBlockWidth() + "px"; 814 elmPlayingField.style.top = me.getBlockHeight() + "px"; 815 elmPlayingField.style.width = fWidth + "px"; 816 elmPlayingField.style.height = fHeight + "px"; 817 818 // the math for this will need to change depending on font size, padding, etc 819 // assuming height of 14 (font size) + 8 (padding) 820 var bottomPanelHeight = hEdgeSpace - me.getBlockHeight(); 821 var pLabelTop = me.getBlockHeight() + fHeight + Math.round((bottomPanelHeight - 30)/2) + "px"; 822 823 elmAboutPanel.style.top = pLabelTop; 824 elmAboutPanel.style.width = "450px"; 825 elmAboutPanel.style.left = Math.round(cWidth/2) - Math.round(450/2) + "px"; 826 827 elmLengthPanel.style.top = pLabelTop; 828 elmLengthPanel.style.left = cWidth - 120 + "px"; 829 830 // if width is too narrow, hide the about panel 831 if (cWidth < 700) { 832 elmAboutPanel.style.display = "none"; 833 } else { 834 elmAboutPanel.style.display = "block"; 835 } 836 837 me.grid = []; 838 var numBoardCols = fWidth / me.getBlockWidth() + 2; 839 var numBoardRows = fHeight / me.getBlockHeight() + 2; 840 841 for (var row = 0; row < numBoardRows; row++) { 842 me.grid[row] = []; 843 for (var col = 0; col < numBoardCols; col++) { 844 if (col === 0 || row === 0 || col === (numBoardCols-1) || row === (numBoardRows-1)) { 845 me.grid[row][col] = 1; // an edge 846 } else { 847 me.grid[row][col] = 0; // empty space 848 } 849 } 850 } 851 852 myFood.randomlyPlaceFood(); 853 854 // setup event listeners 855 856 myKeyListener = function(evt) { 857 if (!evt) var evt = window.event; 858 var keyNum = (evt.which) ? evt.which : evt.keyCode; 859 860 if (me.getBoardState() === 1) { 861 if ( !(keyNum >= 37 && keyNum <= 40) ) {return;} // if not an arrow key, leave 862 863 // This removes the listener added at the #listenerX line 864 SNAKE.removeEventListener(elmContainer, "keydown", myKeyListener, false); 865 866 myKeyListener = function(evt) { 867 if (!evt) var evt = window.event; 868 var keyNum = (evt.which) ? evt.which : evt.keyCode; 869 870 mySnake.handleArrowKeys(keyNum); 871 872 evt.cancelBubble = true; 873 if (evt.stopPropagation) {evt.stopPropagation();} 874 if (evt.preventDefault) {evt.preventDefault();} 875 return false; 876 }; 877 SNAKE.addEventListener( elmContainer, "keydown", myKeyListener, false); 878 879 mySnake.rebirth(); 880 mySnake.handleArrowKeys(keyNum); 881 me.setBoardState(2); // start the game! 882 mySnake.go(); 883 } 884 885 evt.cancelBubble = true; 886 if (evt.stopPropagation) {evt.stopPropagation();} 887 if (evt.preventDefault) {evt.preventDefault();} 888 return false; 889 }; 890 891 // Search for #listenerX to see where this is removed 892 SNAKE.addEventListener( elmContainer, "keydown", myKeyListener, false); 893 }; 894 895 /** 896 * This method is called when the snake has eaten some food. 897 * @method foodEaten 898 */ 899 me.foodEaten = function() { 900 elmLengthPanel.innerHTML = "Length: " + mySnake.snakeLength; 901 myFood.randomlyPlaceFood(); 902 }; 903 904 /** 905 * This method is called when the snake dies. 906 * @method handleDeath 907 */ 908 me.handleDeath = function() { 909 var index = Math.max(getNextHighestZIndex( mySnake.snakeBody), getNextHighestZIndex( {tmp:{elm:myFood.getFoodElement()}} )); 910 elmContainer.removeChild(elmTryAgain); 911 elmContainer.appendChild(elmTryAgain); 912 elmTryAgain.style.zIndex = index; 913 elmTryAgain.style.display = "block"; 914 me.setBoardState(0); 915 }; 916 917 // --------------------------------------------------------------------- 918 // Initialize 919 // --------------------------------------------------------------------- 920 921 config.fullScreen = (typeof config.fullScreen === "undefined") ? false : config.fullScreen; 922 config.top = (typeof config.top === "undefined") ? 0 : config.top; 923 config.left = (typeof config.left === "undefined") ? 0 : config.left; 924 config.width = (typeof config.width === "undefined") ? 400 : config.width; 925 config.height = (typeof config.height === "undefined") ? 400 : config.height; 926 927 if (config.fullScreen) { 928 SNAKE.addEventListener(window,"resize", function() { 929 me.setupPlayingField(); 930 }, false); 931 } 932 933 me.setBoardState(0); 934 935 if (config.boardContainer) { 936 me.setBoardContainer(config.boardContainer); 937 } 938 939 }; // end return function 940 941 })();
其中有段加密js代码:
直接将加密代码放入控制台执行:
PS:这里的flag是错误的!!!
在DOM树发现flag:
火狐浏览器在这里
PS:需要勾选这些(输入日志类里)
谷歌浏览器在这里:
MU5735 R.I.P