1. 程式人生 > >javascript版 2048小遊戲

javascript版 2048小遊戲

<!DOCTYPE html>
<html lang="zn">
<head>
    <meta charset="UTF-8">
    <title>2048</title>
    <link rel="stylesheet" href="css/css.css">
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        header{
            display: block;
            width: 200px;
            height: 100px;
            margin: 0 auto;
            text-align: center;
        }
        header h1{
            font-family: Arial;
            font-size: 40px;
            font-weight: bold;
        }
        header #score{
            font-family: Arial;
            font-size: 25px;
        }
        header time{
            display: block;
        }
        header #ng{
            display: block;
            text-decoration: none;
            width: 100px;
            margin: 0 auto;
            padding: 10px 10px;
            background-color: #8f7a66;
            font-family: Arial;
            color: white;
            border-radius: 10px;
        }
        header #ng:hover{
            background-color: #e39851;
        }
        #map{
            width: 450px;
            height: 450px;
            position: relative;
            background-color: #BBA695;
            border-radius: 5px;
            margin: 50px auto;
        }
        .box{
            width: 100px;
            height: 100px;
            background-color: #CBC3B6;
            position: absolute;
            text-align: center;
            line-height: 100px;
            font-family: Arial;
            font-size: 32px;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <header><!-- 語義標籤 -->
        <h1>2048</h1>
        <scan id="score">分數:0</scan>
        <time id="timing">計時:00</time>
        <a href="javascript:game.update()" id="ng">New Game</a>
    </header>
</body>
</html>
window.onload = function(){
    game.init();
    window.onkeydown = function(ev){
        var ev = ev||window.event;
        game.key(ev);
    }
}
var base={
    get:function(id){
        return document.getElementById(id);
    },
    create:function(name){
        return document.createElement(name);
    },
    cdiv:function(id,classname){
        var div = this.create('div');
        if(id!=null){
            div.id = id;
        }
        if(classname!=null){
            div.className = classname;
        }
        return div;
    },
    appch:function(id,name){
        this.get(id).appendChild(name);
    },
    removeall:function(id){for(var i=this.get(id).children.length-1;i>-1;i--){this.get(id).removeChild(this.get(id).children[i]);}},    
}
var game={
    row:4,//行
    column:4,//列
    width:100,
    height:100,
    board:[],
    timer:null,//定時器
    t:0,//計時值
    open:true,//計時開關
    score:0,
    drawMap:function(){//繪製地圖
        var map = base.cdiv('map',null);
        document.body.appendChild(map);

    },
    drawBox:function(){//繪製盒子
        for(var i=0;i<this.column;i++){
            this.board[i] = [];//border[i] = new Array();
            for (var j = 0; j < this.row; j++) {
                this.board[i][j] = 0;
                var box = base.cdiv(null,'box');
                box.setAttribute('id',i*this.column+j);
                box.setAttribute('style','left:'+(j*this.width+10*(j+1))+'px;top:'+(i*this.height+10*(i+1))+'px;');
                base.appch('map',box);
            }
        }
    },
    drawNum:function(n){//新增數字
        for(var i=0;i<n;i++){
            var x = parseInt(Math.floor(Math.random()*4));
            var y = parseInt(Math.floor(Math.random()*4));

            if(support.space(game.board)){
                while(true){
                    if(this.board[x][y]==0){
                        break;
                    }
                    var x = parseInt(Math.floor(Math.random()*4));
                    var y = parseInt(Math.floor(Math.random()*4));            
                }                
            }
            var number = Math.random()<0.5?2:4;
            this.board[x][y] = number;
            this.showBox(x,y,number); 
        }     
    },
    showBox(x,y,number){//顯示盒子
        var boxs = base.get(x*this.column+y);
        boxs.setAttribute('style','left:'+(y*this.width+10*(y+1))+'px;top:'+(x*this.height+10*(x+1))+'px;');
        boxs.style.background = this.boxColor(number);
        if(number==0){
            boxs.innerHTML = '';
        }else{
            boxs.innerHTML = number;
        }
        
    },
    boxColor:function(n){//不同數字的盒子的顏色
        switch(n){
            case 0:return '#CBC3B6' ;break;
            case 2:return '#EEE5DE' ;break;
            case 4:return '#EDE2C2';break;
            case 8:return '#F0B478';break;
            case 16:return '#F59666';break;
            case 32:return '#F67D62';break;
            case 64:return '#F75F38';break;
            case 128:return '#EECE67';break;
            case 256:return '#F1D341';break;
            case 512:return '#EDC64F';break;
            case 1024:return '#EFC53F';break;
            case 2048:return '#09c';break;
            case 4096:return '#93c';break;
        }
    },
    key:function(ev){
        if(this.open){
            this.timing();
            this.open = false;
        }
        var n = ev.keyCode;
        switch(n){
            case 38:
                if(support.move(38,game.board)){//判斷是否可以移動
                    this.drawNum(1);//隨機產生一個數字.2/4
                    support.gameover();//判斷是否結束遊戲
                }    
            break;
            case 39:
                if(support.move(39,game.board)){
                    this.drawNum(1);
                    support.gameover();
                }    
            break;
            case 40:
                if(support.move(40,game.board)){
                    this.drawNum(1);
                    support.gameover();
                }    
            break;
            case 37:
                if(support.move(37,game.board)){
                    this.drawNum(1);
                    support.gameover();
                }    
            break;                                    
        }
    },
    update:function(){
        this.endtime();
        this.t=0;
        this.open = true;
        base.get('timing').innerHTML = '計時:'+this.t;
        this.score = 0;
        base.get('score').innerHTML = '分數:'+this.score;
        base.removeall('map');
        this.drawBox();
        this.drawNum(2);
    },
    timing:function(){
        base.get('timing').innerHTML = '計時:'+this.t;
        this.t++;
        this.timer=setTimeout('game.timing()',1000);
    },
    endtime:function(){
        clearTimeout(this.timer);
    },
    init:function(){
        this.drawMap();
        this.drawBox();
        this.drawNum(2);
    }
}
var support={
    move:function(n,board){
        switch(n){
            case 38:
                if(!this.judge(38,board)){
                    return false;
                }
                //movedup
                for(var j=0;j<game.row;j++){
                    for(var i=1;i<game.column;i++){
                        if(board[i][j]!=0){
                            for(var k=0;k<i;k++){
                                if(board[k][j]==0&&this.betweenBar(board,i,j,k,n)){
                                    board[k][j] = board[i][j];
                                    board[i][j] = 0;
                                    this.show(i,j,k,n,game.board);
                                }else if(board[k][j]!=0&&board[k][j]==board[i][j]&&this.betweenBar(board,i,j,k,n)){
                                    board[k][j] += board[i][j];
                                    board[i][j] = 0;
                                    game.score += board[k][j];
                                    base.get('score').innerHTML = '分數:'+game.score; 
                                    this.show(i,j,k,n,game.board);
                                }
                            }
                        }
                    }
                }
                return true;                                    
            break;
            case 39:
                if(!this.judge(39,board)){
                    return false;
                }
                //moveright
                for(var i=0;i<game.column;i++){
                    for(var j=game.row-2;j>-1;j--){
                        if(board[i][j]!=0){
                            for(var k=game.column-1;k>j;k--){
                                // console.log(k);
                                //相鄰位置 含空 
                                if(board[i][k]==0&&this.betweenBar(board,i,j,k,n)){
                                    board[i][k] = board[i][j];
                                    board[i][j] = 0
                                    this.show(i,j,k,n,game.board);
                                    // continue;

                                }else if(board[i][k]!=0&&board[i][j]==board[i][k]&&this.betweenBar(board,i,j,k,n)){//相鄰位置 不空 但相等
                                    board[i][k] +=board[i][j];
                                    board[i][j] = 0;
                                    game.score += board[i][k];
                                    base.get('score').innerHTML = '分數:'+game.score;                                     
                                    this.show(i,j,k,n,game.board);
                                    // continue;
                                }
                                
                            }
                        }
                    }
                }
            return true;                                        
            break;
            case 40:
                if(!this.judge(40,board)){
                    return false;
                }
                //movedown
                for(var j=0;j<game.row;j++){
                    for(var i=game.column-2;i>-1;i--){
                        if(board[i][j]!=0){
                            for(var k=game.row-1;k>i;k--){
                                if(board[k][j]==0&&this.betweenBar(board,i,j,k,n)){
                                    board[k][j] = board[i][j];
                                    board[i][j] = 0;
                                    this.show(i,j,k,n,game.board);
                                }else if(board[k][j]!=0&&board[k][j]==board[i][j]&&this.betweenBar(board,i,j,k,n)){
                                    board[k][j] += board[i][j];
                                    board[i][j] = 0;
                                    game.score += board[k][j];
                                    base.get('score').innerHTML = '分數:'+game.score;                                     
                                    this.show(i,j,k,n,game.board);
                                }
                            }
                        }
                    }
                }
                return true;
            break;
            case 37:
                if(!this.judge(37,board)){
                    return false;

                }
                //moveleft
                for(var i=0;i<game.column;i++){
                    for(var j=1;j<game.row;j++){
                        if(board[i][j]!=0){
                            for(var k=0;k<j;k++){
                                //相鄰位置 含空 
                                if(board[i][k]==0&&this.betweenBar(board,i,j,k,n)){
                                    board[i][k] = board[i][j];
                                    board[i][j] = 0
                                    this.show(i,j,k,n,game.board);
                                    // continue;

                                }else if(board[i][k]!=0&&board[i][j]==board[i][k]&&this.betweenBar(board,i,j,k,n)){//相鄰位置 不空 但相等
                                    board[i][k] +=board[i][j];
                                    board[i][j] = 0;
                                    game.score += board[i][k];
                                    base.get('score').innerHTML = '分數:'+game.score;                                     
                                    this.show(i,j,k,n,game.board);
                                    // continue;
                                }
                                
                            }
                        }
                    }
                }
                return true;
        }
    },
    judge:function(n,board){//能否移動 
        switch(n){
            case 38:
                for(var j=0;j<game.row;j++){
                    for(var i=1;i<game.column;i++){
                        if(board[i][j]!=0){
                            if(board[i-1][j]==0||board[i-1][j]==board[i][j]){
                                return true;
                            }
                        }
                    }
                }
                return false;
            break;
            case 39:
                for(var i=0;i<game.column;i++){
                    for(var j=0;j<game.row-1;j++){
                        if(board[i][j]!=0){
                            if(board[i][j+1]==0||board[i][j+1]==board[i][j]){
                                return true;
                            }
                        }
                    }
                }
                return false;
            break;
            case 40:
                for(var j=0;j<game.row;j++){
                    for(var i=0;i<game.column-1;i++){
                        if(board[i][j]!=0){
                            if(board[i+1][j]==0||board[i+1][j]==board[i][j]){
                                return true;
                            }
                        }
                    }
                }
                return false;
            break;
            case 37:
                for(var i=0;i<game.column;i++){
                    for(var j=1;j<game.row;j++){
                        if(board[i][j]!=0){
                            if(board[i][j-1]==0||board[i][j-1]==board[i][j]){
                                return true;
                            }
                        }
                    }
                    
                }
                return false;
            break;                                    
        }        
    },
    show:function(i,j,k,n,board){
        switch(n){
            case 38:
                game.showBox(k,j,board[k][j]);
                game.showBox(i,j,board[i][j]); 
            break;
            case 39:
                game.showBox(i,k,board[i][k]);
                game.showBox(i,j,board[i][j]);            
            break;
            case 40:
                game.showBox(k,j,board[k][j]);
                game.showBox(i,j,board[i][j]);            
            break;
            case 37:
                game.showBox(i,k,board[i][k]);
                game.showBox(i,j,board[i][j]);            
            break;
        }

    },
    betweenBar:function(board,i,j,k,n){
        switch(n){
            case 38:
                for(var m=k+1;m<i;m++){
                    if(board[m][j]!=0){
                        return false;
                    }
                }
                return true;
            break;
            case 39:
                for(var m=k-1;m>j;m--){
                    if(board[i][m]!=0){
                        return false;
                    }
                }
                return true;
            break;
            case 40:
                for(var m=k-1;m>i;m--){
                    if(board[m][j]!=0){
                        return false;
                    }
                }
                return true;
            break;

            case 37:
                for(var m=k+1;m<j;m++){
                    if(board[i][m]!=0){
                        return false;
                    }
                }
                return true;
            break;
        }
    },
    space:function(board){//board陣列是否含有0
        for(var i=0;i<game.column;i++){
            for(var j=0;j<game.row;j++){
                if(board[i][j]==0){
                    return true;
                }
            }
        }
        return false;
    },
    gameover:function(){
       if(!this.judge(38,game.board)&&!this.judge(31,game.board)&&!this.judge(40,game.board)&&!this.judge(37,game.board)&&!this.space(game.board)){
            game.endtime(game.timer);
            alert('再來一次');
            game.update();

       }
    }  
}