/* 遊戲棋盤格*/
body{font-family :Arial;text-align:# body{font-family :Arial;text-align:#center ;}
.game{margin:0 auto;/*margin-top:40px;*/text-align:center;display:inline-block;}
.game-score{ font-size:20px;margin:20px auto;}
.game-container{background-color:#bbada0;border-radius:10px;position:relative;}
.game cell{邊框半徑:6px;背景顏色:#ccc0b3;位置:絕對;}
.game-num{寬度:0px;高度:0px;邊框半徑:6px;字體粗細:粗體;字體大小:40px;顏色:#fff;文字對齊:中心;位置:絕對;}
.game-num-2{背景:#eee4da;顏色:#776e65;}
.game -num-4{背景:#ede0c8;顏色:#776e65;}
.game-num-8{背景:#f2b179;}
.game-num-16{背景: #f59563;}
.game-num-32{背景:#f67c5f;}
.game-num-64{ 背景:#f65e3b;}#o# ## # -num-128{背景:#edcf72;font-size:35px;}
.game-num-256{背景:#edcc61;font-大小:35px;}
##o# . .game -num-512{背景:#9c0;字體大小:35px;} .game-num-1024{背景:#33b5e5;font- size:30px;}# num-2048{background:#09c;font-size:30px;} /*遊戲結束*/ .game -over{寬度:100%;高度:100%;位置:絕對;邊框半徑:10px;框大小:邊框框;z-index:1;顯示:表格;背景:rgba(123,102,85,0.5 )}# .game-over-info{display: table-cell;vertical-align:middle} .game-over p{font-size:45px;color:#fff;邊距:20px auto;}# .game-overover span{遊標:指標;背景顏色:rgba(103,82,65,0.6);顯示:塊;邊距:20px auto;寬度:180px;填滿:10px 10px;字型大小:25px;顏色:#f7f2e5;邊框半徑:10px;邊框:1pxsolid #978271;過渡:all .2s} .game-over span:hover{背景-color:rgba(103,82,65,0.7);color:#fff};color:#fff} .game-hide{display:none;}
#####
分數:0
## #
##
(function(window, document, $) { function Game2048(opt) { var prefix = opt.prefix, len = opt.len, size = opt.size, margin = opt.margin; var score = 0; var winNum = 2048; var isGameOver = true; var board = new Board(len); var view = new View(prefix, len, size, margin); view.init(); board.onGenerate = function(e) { view.addNum(e.x, e.y, e.num); }; board.onMove = function(e) { if (e.to.num >= winNum) { isGameOver = true; setTimeout(function() { view.win(); }, 300); } if (e.to.num > e.from.num) { score += e.to.num; view.updateScore(score); } view.move(e.from, e.to); }; board.onMoveComplete = function(e) { if (!board.canMove()) { isGameOver = true; setTimeout(function() { view.over(score); }, 300); } if (e.moved) { setTimeout(function(){ board.generate(); }, 200); } }; $(document).keydown(function(e) { if (isGameOver) { return false; } switch (e.which) { case 37: board.moveLeft(); break; case 38: board.moveUp(); break; case 39: board.moveRight(); break; case 40: board.moveDown(); break; } }); function start() { score = 0; view.updateScore(0); view.cleanNum(); board.init(); board.generate(); board.generate(); isGameOver = false; } $('#' + prefix + '_restart').click(start); start(); }; // 数据处理 function Board(len) { this.len = len; this.arr = []; } Board.prototype = { // 事件 onGenerate: function() {}, onMove: function() {}, onMoveComplete: function() {}, // 创建数组 init: function() { for (var arr = [], x = 0, len = this.len; x < len; ++x) { arr[x] = []; for (var y = 0; y < len; ++y) { arr[x][y] = 0; } } this.arr = arr; }, // 在随机位置增加一个随机数 generate: function() { var empty = []; for (var x = 0, arr = this.arr, len = arr.length; x < len; ++x) { for (var y = 0; y < len; ++y) { if (arr[x][y] === 0) { empty.push({x: x, y: y}); } } } if (empty.length < 1) { return false; } var pos = empty[Math.floor((Math.random() * empty.length))]; this.arr[pos.x][pos.y] = Math.random() < 0.5 ? 2 : 4; this.onGenerate({x: pos.x, y: pos.y, num: this.arr[pos.x][pos.y]}); }, // 左移 moveLeft: function() { var canMove = false; // 从上到下,从左到右 for (var x = 0, len = this.arr.length; x < len; ++x) { for (var y = 0, arr = this.arr[x]; y < len; ++y) { // 从 y + 1 位置开始,向右查找 for (var next = y + 1; next < len; ++next) { // 如果 next 单元格是 0,找下一个不是 0 的单元格 if (arr[next] === 0) { continue; } // 如果 y 数字是 0,则将 next 移动到 y 位置,然后将 y 减 1 重新查找 if (arr[y] === 0) { arr[y] = arr[next]; this.onMove({from: {x: x, y: next, num: arr[next]}, to: {x: x, y: y, num: arr[y]}}); arr[next] = 0; canMove = true; --y; // 如果 y 与 next 单元格数字相等,则将 next 移动并合并给 y } else if (arr[y] === arr[next]) { arr[y] += arr[next]; this.onMove({from: {x: x, y: next, num: arr[next]}, to: {x: x, y: y, num: arr[y]}}); arr[next] = 0; canMove = true; } break; } } } this.onMoveComplete({moved: canMove}); }, moveRight: function() { var moved = false; for (var x = 0, len = this.arr.length; x < len; ++x) { for (var y = len - 1, arr = this.arr[x]; y >= 0; --y) { for (var prev = y - 1; prev >= 0; --prev) { if (arr[prev] === 0) { continue; } if (arr[y] === 0) { arr[y] = arr[prev]; this.onMove({from: {x: x, y: prev, num: arr[prev]}, to: {x: x, y: y, num: arr[y]}}); arr[prev] = 0; moved = true; ++y; } else if (arr[y] === arr[prev]) { arr[y] += arr[prev]; this.onMove({from: {x: x, y: prev, num: arr[prev]}, to: {x: x, y: y, num: arr[y]}}); arr[prev] = 0; moved = true; } break; } } } this.onMoveComplete({moved: moved}); }, moveUp: function() { var canMove = false; for (var arr = this.arr, len = arr.length, y = 0; y < len; ++y) { for (var x = 0; x < len; ++x) { for (var next = x + 1; next < len; ++next) { if (arr[next][y] === 0) { continue; } if (arr[x][y] === 0) { arr[x][y] = arr[next][y]; this.onMove({from: {x: next, y: y, num: arr[next][y]}, to: {x: x, y: y, num: arr[x][y]}}); arr[next][y] = 0; canMove = true; --x; } else if (arr[x][y] === arr[next][y]) { arr[x][y] += arr[next][y]; this.onMove({from: {x: next, y: y, num: arr[next][y]}, to: {x: x, y: y, num: arr[x][y]}}); arr[next][y] = 0; canMove = true; } break; } } } this.onMoveComplete({moved: canMove}); }, moveDown: function() { var canMove = false; for (var arr = this.arr, len = arr.length, y = 0; y < len; ++y) { for (var x = len - 1; x >= 0; --x) { for (var prev = x - 1; prev >= 0; --prev) { if (arr[prev][y] === 0) { continue; } if (arr[x][y] === 0) { arr[x][y] = arr[prev][y]; this.onMove({from: {x: prev, y: y, num: arr[prev][y]}, to: {x: x, y: y, num: arr[x][y]}}); arr[prev][y] = 0; canMove = true; ++x; } else if (arr[x][y] === arr[prev][y]) { arr[x][y] += arr[prev][y]; this.onMove({from: {x: prev, y: y, num: arr[prev][y]}, to: {x: x, y: y, num: arr[x][y]}}); arr[prev][y] = 0; canMove = true; } break; } } } this.onMoveComplete({moved: canMove}); }, canMove: function() { for (var x = 0, arr = this.arr, len = arr.length; x < len; ++x) { for (var y = 0; y < len; ++y) { if (arr[x][y] === 0) { return true; } var curr = arr[x][y], right = arr[x][y + 1]; var down = arr[x + 1] ? arr[x + 1][y] : null; if (right === curr || down === curr) { return true; } } } return false; } }; // 视图处理 function View(prefix, len, size, margin) { this.prefix = prefix; this.len = len; // 单元格单边的数量(实际数量 len * len) this.size = size; // 每个单元格的边长 this.margin = margin; // 每个单元格的间距 this.score = $('#' + prefix + '_score'); this.container = $('#' + prefix + '_container'); var containerSize = len * size + margin * (len + 1); this.container.css({width:containerSize , height: containerSize}); this.nums = {}; } View.prototype = { // 计算位置 getPos: function(n) { return this.margin + n * (this.size + this.margin); }, init: function() { for (var x = 0, len = this.len; x < len; ++x) { for (var y = 0; y < len; ++y) { var $cell = $('<div class="' + this.prefix + '-cell"></div>'); $cell.css({ width: this.size + 'px', height: this.size + 'px', top: this.getPos(x), left: this.getPos(y) }).appendTo(this.container); } } }, addNum: function(x, y, num) { var $num = $('<div class="' + this.prefix + '-num ' + this.prefix + '-num-' + num + ' ">'); $num.text(num).css({ top: this.getPos(x) + parseInt(this.size / 2), left: this.getPos(y) + parseInt(this.size / 2) }).appendTo(this.container).animate({ width: this.size + 'px', height: this.size + 'px', lineHeight: this.size + 'px', top: this.getPos(x), left: this.getPos(y) }, 100); this.nums[x + '-' + y] = $num; }, move: function(from, to) { var fromIndex = from.x + '-' + from.y, toIndex = to.x + '-' + to.y; var clean = this.nums[toIndex]; this.nums[toIndex] = this.nums[fromIndex]; delete this.nums[fromIndex]; var prefix = this.prefix + '-num-'; var pos = {top: this.getPos(to.x), left: this.getPos(to.y)}; this.nums[toIndex].finish().animate(pos, 200, function() { if (to.num > from.num) { clean.remove(); $(this).text(to.num).removeClass(prefix + from.num).addClass(prefix + to.num); } }); }, updateScore: function(score) { this.score.text(score); }, win: function() { $('#' + this.prefix + '_over_info').html('<p>您获胜了</p>'); $('#' + this.prefix + '_over').removeClass(this.prefix + '-hide'); }, over: function(score) { $('#' + this.prefix + '_over_info').html('<p>本次得分</p><p>' + score + '</p>'); $('#' + this.prefix + '_over').removeClass(this.prefix + '-hide'); }, cleanNum: function() { this.nums = {}; $('#' + this.prefix + '_over').addClass(this.prefix + '-hide'); $('.' + this.prefix + '-num').remove(); } }; window['Game2048'] = Game2048; })(window, document, jQuery);