Ext.define('mobile2048.view.maincontainer', { extend: 'Ext.Container', requires: [ 'Ext.Panel', 'Ext.field.Text', 'Ext.Button' ], config: { height: 400, itemId: 'maincontainer', style: 'background:#bbada0', width: 326, layout: 'fit', items: [ { xtype: 'container', layout: 'vbox', items: [ { xtype: 'panel', height: 80, style: '', layout: 'hbox', items: [ { xtype: 'container', border: 2, centered: false, height: 68, itemId: 'g11', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g12', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g13', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g14', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 } ] }, { xtype: 'panel', height: 80, layout: 'hbox', items: [ { xtype: 'container', border: 2, centered: false, height: 68, itemId: 'g21', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g22', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g23', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g24', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 } ] }, { xtype: 'panel', height: 80, layout: 'hbox', items: [ { xtype: 'container', border: 2, centered: false, height: 68, itemId: 'g31', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g32', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, height: 68, itemId: 'g33', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g34', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 } ] }, { xtype: 'panel', height: 80, layout: 'hbox', items: [ { xtype: 'container', border: 2, centered: false, height: 68, itemId: 'g41', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g42', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g43', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 }, { xtype: 'container', baseCls: '', border: 2, centered: false, cls: 'backgroud-color:blue', height: 68, itemId: 'g44', margin: 5, padding: 28, style: 'background:rgba(238, 228, 218, 0.35)', width: 71 } ] }, { xtype: 'textfield', itemId: 'score', label: '分数', value: 100, readOnly: true }, { xtype: 'button', itemId: 'reset', width: 121, text: '重新开始' } ] } ] } });
2 控制器
Ext.define('mobile2048.controller.main', { extend: 'Ext.app.Controller', config: { refs: { main: '#maincontainer' }, control: { "container#maincontainer": { initialize: 'onMaincontainerInitialize' }, "button#reset": { tap: 'onResetTap' } } }, onMaincontainerInitialize: function(component, eOpts) { var com = component; this.initGrid(com); com.renderElement.addListener('swipe',this.handleSwipe,this); return false; }, onResetTap: function(button, e, eOpts) { this.initGrid(); return false; }, initGrid: function(com) { // console.log('initGrid'); this.resetGame(); this.generateRandomNum(); return false; }, handleSwipe: function(e,node,options) { if(this.gameOver()){ Ext.Msg.show({ title: '游戏结束,请重新开始', buttons: Ext.Msg.OK }); return; } var direc = e.direction; switch(direc){ case 'up': this.processUp(); break; case 'down': this.processDown(); break; case 'left': this.processLeft(); break; case 'right': this.processRight(); break; } return false; }, processUp: function() { console.log('up'); for(var i=1;i<=4;i++){ var row = this.fetchRow(i,1); this.reArrange(i,row,'UP'); } this.generateRandomNum(); return false; }, processDown: function() { console.log('down'); for(var i=1;i<=4;i++){ var row = this.fetchRow(i,1).reverse(); this.reArrange(i,row,'DOWN'); } this.generateRandomNum(); return false; }, processLeft: function() { console.log('left'); for(var i=1;i<=4;i++){ var row = this.fetchRow(i,0); this.reArrange(i,row,'LEFT'); } this.generateRandomNum(); return false; }, processRight: function() { console.log('right'); for(var i=1;i<=4;i++){ var row = this.fetchRow(i,0).reverse(); this.reArrange(i,row,'RIGHT'); } this.generateRandomNum(); return false; }, generateRandomNum: function(num) { var main = this.getMain(); var randomNum = Math.floor((Math.random() * 2) + 2); var count = 0; var roundNum = Math.min(randomNum, this.getEmptyCellNum()); while(count<roundNum){ var col = Math.floor((Math.random() * 4) + 1); var row = Math.floor((Math.random() * 4) + 1); var cub = main.down('#g'+row+col); if(Ext.isEmpty(cub.get('html'))){ randomNum = Math.floor((Math.random() * 2)) * 2 + 2; cub.set('html',randomNum); this.totalScore += randomNum; // console.log(row,col,randomNum,count); cub.set('style',mobile2048.Color[randomNum]); count++; } } this.updateScore(); return false; }, gameOver: function() { var main = this.getMain(),cell_a,a_v,cell_b,b_v, over = true; if(this.getEmptyCellNum() !== 0){ return false; } for(var i=1;i<=4;i++){ var k=1; for(var j=1;j<=4 && k<=4;j++){ var k = j+1; cell_a = main.down('#g' + i + j); cell_b = main.down('#g' + i + k); a_v = (cell_a && cell_a.get('html')) ? cell_a.get('html') : null; b_v = cell_b && cell_b.get('html') ? cell_b.get('html') : null; if(a_v === b_v){ over = false; break; } } if(!over) break; } if(over){ for(var i=1;i<=4;i++){ var k=1; for(var j=1;j<=4 && k<=4;j++){ var k = j+1; cell_a = main.down('#g' + j + i); cell_b = main.down('#g' + k + i); a_v = (cell_a && cell_a.get('html')) ? cell_a.get('html') : null; b_v = cell_b && cell_b.get('html') ? cell_b.get('html') : null; if(a_v === b_v){ over = false; break; } } if(!over) break; } } return over; }, fetchRow: function(rowNum, flag) { var row = [], main = this.getMain(),cube; for(var i=1;i<5;i++){ if(flag === 0){ cube = main.down('#g' + rowNum + i); }else{ cube = main.down('#g' + i + rowNum); } var val = cube.get('html'); val = val?val:0; row.push(val); } // console.log('fetched '+row); return row; }, updateScore: function() { var main = this.getMain(); main.down('#score').setValue(this.totalScore); }, reArrange: function(rownum,row,direction) { var main = this.getMain(); if(row){ switch(direction){ case 'LEFT': row = this.merge(row); break; case 'RIGHT': row = this.merge(row).reverse(); break; case 'UP': row = this.merge(row); break; case 'DOWN': row = this.merge(row).reverse(); break; } // console.log('rearrange ' + row); var len = row.length,cell; for(var i=1;i<=len;i++){ if(direction === 'LEFT' || direction === 'RIGHT'){ cel = main.down('#g'+rownum+i); }else{ cel = main.down('#g'+i+rownum); } var val = row[i-1]; cel.set('html',val !== 0 ? val : null); cel.set('style',val !== 0 ? mobile2048.Color[val] : mobile2048.Color.defaultStyle); } } }, merge: function(row) { for(var i=0;i<row.length;i++){ if(row[i] === 0) continue; for(var j = i+1;j<row.length;j++){ if(row[i] === row[j] && j === i+1){ row[i] += row[j]; row[j] = 0; i++; } } } var count = 0; var len = row.length; var arr = []; for(var i=0; i<len;i++){ if(row[i] !== 0){ arr.push(row[i]); } } while(arr.length<len){ arr.push(0); } return arr; }, getEmptyCellNum: function() { var row,num = 0; for(var i=1;i<=4;i++){ row = this.fetchRow(i); for(var j = 0;j<row.length;j++){ if(row[j] === 0) num++; } } console.log('Empty num of cell:' + num); return num; }, resetGame: function() { var main = this.getMain(); this.totalScore = 0; for(var i=1;i<5;i++){ for(j=1;j<5;j++){ cell = main.down('#g' + i + j); cell.set('html',null); cell.set('style',mobile2048.Color.defaultStyle); } } }, getScore: function(row) { var score = 0; for(var i=0;i<row.length;i++){ score += row[i]; } return score; }, init: function(application) { }, launch: function() { this.totalScore = 0; } });
3 application
// @require @packageOverrides Ext.Loader.setConfig({ }); Ext.application({ views: [ 'maincontainer' ], controllers: [ 'main' ], name: 'mobile2048', launch: function() { Ext.define('mobile2048.Color', { singleton: true, 'defaultStyle': 'background:rgba(238, 228, 218, 0.35)', '2': 'background:#eee4da', '4':'background:#ede0c8', '8':'background:#f2b179', '16':'background:#f59563', '32':'background:#f67c5f', '64':'background:#f65e3b', '128':'background:#edcf72', '256':'background:#edcc61', '512': 'background:#edc850', '1024': 'background:#edc53f', '2048':'background:edc22e' }); Ext.create('mobile2048.view.maincontainer', {fullscreen: true}); } });
4 效果: