<html> 
    <head>    
        <title>R</title>    
        <style> 
            div {

            }   
            #board tr td{    
                width: 30px;    
                height: 30px; 
                border: 1px;   
            }  
            #main{  
                float: left;
                background-color: black;

                margin-left: 20px;            }  
            #preBoard tr td{  
                width: 30px;   
                height: 30px;
                background-color: black;
            } 
            .button {
                background-color: #54CD59;
                width:50px;
                height:25px;
                border-radius: 200px;
                margin-left: 15px;
            } 
            #begin{
                background-color: #54CD59;
                width:100px;
                height:50px;
                border-radius: 200px;
                margin-top: 20px;
                margin-left: 20px;
            }
        </style>   
        <meta charset="UTF-8"/>
    </head>    
    <script language="javascript">
        var TIME = 1000;
        var color = "#54CD59";
        var preTime;
        var mainTb;  
        //预览窗口  
        var preTb;   
        //游戏状态 0: 未开始;1 运行; 2 中止;   
        var status = 0;    
        //定时器, 定时器内将做moveDown操作   
        var timer; 
        //分数   
        var score = 0;   
        //board是一个18*10的数组,也和页面的table对应.   
        //用来标注那些方格已经被占据. 初始时都为0, 如果被占据则为1   
        var board = new Array(18);   
        for(var i=0;i<18;i++){   
            board[i] = new Array(10);    
        }   
        for(var i=0;i<18;i++){    
            for(var j=0; j<10; j++){    
                board[i][j] = 0;    
            }    
        }    
        //当前活动的方块, 它可以左右下移动, 变型.当它触底后, 将会更新board;   
        var activeBlock;  
        //下一个图形  
        var nextBlock;  
        //下一个图形预览  
        var previewBlock;  
       //生产方块形状, 有7种基本形状.   
        function initBlock(){    
            var block = new Array(4);    
            //均衡获取0-6之间的随机数
            var t = Math.floor(Math.random()*7);    
            switch(t){  
                case 0:{    
                    block[0] = {x:0, y:4};    
                    block[1] = {x:1, y:4};    
                    block[2] = {x:0, y:5};    
                    block[3] = {x:1, y:5};    
                    break;    
                }    
                case 1:{    
                    block[0] = {x:0, y:3};    
                    block[1] = {x:0, y:4};    
                    block[2] = {x:0, y:5};    
                    block[3] = {x:0, y:6};    
                    break;    
                }    
                case 2:{    
                    block[0] = {x:0, y:5};    
                    block[1] = {x:1, y:4};    
                    block[2] = {x:1, y:5};    
                    block[3] = {x:2, y:4};    
                    break;    
                }    
                case 3:{    
                    block[0] = {x:0, y:4};    
                    block[1] = {x:1, y:4};    
                    block[2] = {x:1, y:5};    
                    block[3] = {x:2, y:5};    
                    break;    
                }    
                case 4:{    
                    block[0] = {x:0, y:4};    
                    block[1] = {x:1, y:4};    
                    block[2] = {x:1, y:5};    
                    block[3] = {x:1, y:6};    
                    break;    
                }    
                case 5:{    
                    block[0] = {x:0, y:4};    
                    block[1] = {x:1, y:4};    
                    block[2] = {x:2, y:4};    
                    block[3] = {x:2, y:5};    
                    break;    
                }    
                case 6:{    
                    block[0] = {x:0, y:5};    
                    block[1] = {x:1, y:4};    
                    block[2] = {x:1, y:5};    
                    block[3] = {x:1, y:6};    
                    break;    
                }   
            }  
            return block;   
        }   
        //向下移动   
        function moveDown(){   
            //检查底边界.   
          if(checkBorder("down")){    
            //没有触底, 则擦除当前图形
              paint(mainTb,activeBlock,"black");    
              //更新当前图形坐标   
              for(var i=0; i<4; i++){   
                  activeBlock[i].x = activeBlock[i].x + 1;    
              }   
              //重画当前图形   
              paint(mainTb,activeBlock,color);    
          }   
          //触底,    
          else{   
            //停止当前的定时器, 也就是停止自动向下移动.   
            clearInterval(timer);   
            //标记触底单元格.   
            updateBoard();   
            //消行   
            var lines = deleteLine();   
            //如果有消行, 则   
            if(lines!=0){
                //更新分数   
                //一次消多行则分数加倍  
                if(lines==2){  
                    lines=3;  
                }
                else if(lines==3){  
                    lines=6;  
                }  
                else if(lines==4){  
                    lines=10;  
                }  
                score = score + lines;   
                updateScore();  
                //擦除整个面板   
                eraseBoard();   
                //重绘面板   
                paintBoard();   
            }  
            //erasePreview(); 
            paint(preTb,previewBlock,"black"); 
            //产生一个新图形并判断是否可以放在最初的位置.   
            if(!validateBlock(nextBlock)){  
                alert("Game over!");   
                status = 2;  
                return;   
            };  
            activeBlock = nextBlock;
            nextBlock = initBlock();
            previewBlock = copyBlock(nextBlock);  
            paint(mainTb,activeBlock,color);  
            //定时器, 每隔一秒执行一次moveDown  
            applyPreview();  
            paint(preTb,previewBlock,color);  
            timer = setInterval(moveDown,TIME);
          }    
        }  
        function validateBlock(block){  
            if(!block){    
                return false;  
            }  
          for(var i=0; i<4; i++){   
              if(!isCellValid(block[i].x, block[i].y)){
                  return false;   
              }   
          }  
          return true;  
        }  

        function move(direction){
            if(checkBorder(direction)){
                paint(mainTb,activeBlock,"black");
                for(var i=0; i<4; i++){ 
                    if(direction == "left"){
                        activeBlock[i].y = activeBlock[i].y - 1; 
                    }else if(direction == "right"){
                        activeBlock[i].y = activeBlock[i].y + 1; 
                    }  
                }  
                paint(mainTb,activeBlock,color);
            }
        }   
        //旋转, 因为旋转之后可能会有方格覆盖已有的方格.   
        //先用一个tmpBlock,把activeBlock的内容都拷贝到tmpBlock,   
        //对tmpBlock尝试旋转, 如果旋转后检测发现没有方格产生冲突,则   
        //把旋转后的tmpBlock的值给activeBlock.   
        function rotate(){    
            var tmpBlock = copyBlock(activeBlock);   
            //先算四个点的中心点,则这四个点围绕中心旋转90度。  
            var cx = Math.round((tmpBlock[0].x + tmpBlock[1].x + tmpBlock[2].x + tmpBlock[3].x)/4);    
            var cy = Math.round((tmpBlock[0].y + tmpBlock[1].y + tmpBlock[2].y + tmpBlock[3].y)/4);    
            //旋转的主要算法. 可以这样分解来理解。  
            //先假设围绕源点旋转。然后再加上中心点的坐标。
            for(var i=0; i<4; i++){    
                tmpBlock[i].x = cx+cy-activeBlock[i].y;//逆时针旋转90度   
                tmpBlock[i].y = cy-cx+activeBlock[i].x;   
            }    
            //检查旋转后方格是否合法.   
            for(var i=0; i<4; i++){    
                if(!isCellValid(tmpBlock[i].x,tmpBlock[i].y)){   
                    return;   
                }   
            }   
            //如果合法, 擦除
            paint(mainTb,activeBlock,"black");   
            //对activeBlock重新赋值.   
            for(var i=0; i<4; i++){    
                activeBlock[i].x = tmpBlock[i].x;    
                activeBlock[i].y = tmpBlock[i].y;    
            }   
            //重画.   
            paint(mainTb,tmpBlock,color);    
        }    
        function checkBorder(direction){    
            for(var i=0; i<activeBlock.length; i++){    
                if(direction == "left"){
                    var flag = isCellValid(activeBlock[i].x, activeBlock[i].y-1);
                }else if(direction == "right"){
                    var flag = isCellValid(activeBlock[i].x+1, activeBlock[i].y+1);
                }else if(direction == "down"){
                    var flag = isCellValid(activeBlock[i].x+1, activeBlock[i].y);
                } 
                if(!flag){
                    return false;
                }
            }    
            return true;    
        }   
        //检查坐标为(x,y)的是否在board种已经存在, 存在说明这个方格不合法.   
        function isCellValid(x, y){    
            if(x>17||x<0||y>9||y<0){    
                return false;    
            }    
            if(board[x][y]==1){    
                return false;    
            }    
            return true;    
        }    

        function paint(el,shap,color){
            //绿色为活动图形,黑色为擦除的图形    
            for(var i=0; i<4; i++){    
                el.rows[shap[i].x].cells[shap[i].y].style.backgroundColor= color;    
            }    
        } 
        //更新board数组   
        function updateBoard(){    
            for(var i=0; i<4; i++){    
                board[activeBlock[i].x][activeBlock[i].y]=1;    
            }    
        }   
        //消行   
        function deleteLine(){   
            var lines = 0;   
            for(var i=0; i<18; i++){   
                var j=0;
                //检测满行   
                for(; j<10; j++){   
                    if(board[i][j]==0){   
                        break;   
                    }   
                }   
                if(j==10){   
                    lines++;   
                    if(i!=0){   
                        for(var k=i-1; k>=0; k--){
                            //上一行赋值给下一行
                            board[k+1] = board[k];   
                        }   
                    }   
                    board[0] = generateBlankLine();   
                }   
            }   
            return lines;   
        }   
        //擦除整个面板   
        function eraseBoard(){   
            for(var i=0; i<18; i++){   
                for(var j=0; j<10; j++){   
                    mainTb.rows[i].cells[j].style.backgroundColor = "black";   
                }   
            }   
        }   
        //重绘整个面板   
        function paintBoard(){   
            for(var i=0;i<18;i++){   
                for(var j=0; j<10; j++){    
                  if(board[i][j]==1){   
                    mainTb.rows[i].cells[j].style.backgroundColor = color;   
                  }   
                }    
            }    
        }   
        //产生一个空白行.   
        function generateBlankLine(){   
            var line = new Array(10);   
            for(var i=0; i<10; i++){   
                line[i] = 0;   
            }   
            return line;   
        }   
        //更新分数  
        function updateScore(){  
            document.getElementById("score").innerText=" " + score;  
        }  
        //键盘控制   
        function keyControl(){    
            if(status!=1){   
                return;   
            }    
            var code = event.keyCode;    
            switch(code){    
                case 37:{   
                    move("left");   
                    break;    
                }    
                case 38:{   
                    rotate();    
                    break;    
                }    
                case 39:{    
                    move("right");    
                    break;   
                }    
                case 40:{    
                    moveDown();    
                    break;    
                }    
            }    
        }  
        //辅助函数,拷贝一个图形。  
        function copyBlock(old){  
            var o = new Array(4);  
            for(var i=0; i<4; i++){    
                o[i] = {x:0, y:0};    
            }  
            for(var i=0; i<4; i++){    
                o[i].x = old[i].x;    
                o[i].y = old[i].y;    
            }  
            return o;  
        }  
        //调整previewBlock的坐标以适应预览窗口 
        function applyPreview(){  
            var t = 100;  
            for(var i=0; i<4; i++){  
                if(previewBlock[i].y<t){  
                    t = previewBlock[i].y;  
                }  
            }  
            //原图形是18X10,预览是4X4,需要在列上左移一个最小单位
            for(var i=0; i<4; i++){  
                previewBlock[i].y-=t;  
            }  

        }  
        function init(){
            activeBlock = initBlock();  
            nextBlock = initBlock();  
            previewBlock = copyBlock(nextBlock);
            paint(mainTb,activeBlock,color);   
            applyPreview();
            paint(preTb,previewBlock,color);  
            timer = setInterval(moveDown,TIME); 
        }
        //开始  
        function begin(e){   
            e.disabled = true;   
            status = 1;    
            mainTb = document.getElementById("board");  
            preTb = document.getElementById("preBoard");  
            init();  
        }  
        document.onkeydown=keyControl;
        function hard(){
            TIME = 200;
            document.getElementById("hard").disabled = true;
        }
        function easy(){
            TIME = 1000;
            document.getElementById("easy").disabled = true;
        }
        function middle(){
            TIME = 500;
            document.getElementById("middle").disabled = true;
        }
    </script>    
    <body>
        <Input type="button" value="难" id="hard"  class="button" onclick="hard();"/>
        <Input type="button" value="中" id="middle" class="button" onclick="middle();"/>
        <Input type="button" value="易" id="easy" class="button" onclick="easy();"/>
           Score: <span id="score">  0</span>  <br><br>  
        <div id="main">  
            <table id="board" cellspacing=0 cellpadding=0 border=1 style="border-collapse:collapse;">    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
                <tr>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                    <td></td>    
                </tr>    
            </table>    
      </div>  
      <div style="float: left; width: 5px;">  
        </div>  
        <div id="pre">  
            <table id="preBoard" cellspacing=0 cellpadding=0 border=1 style="border-collapse:collapse;">  
                <tr>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                </tr>  
                <tr>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                </tr>  
                <tr>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                </tr>  
                <tr>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                    <td></td>  
                </tr>  
            </table>  
        </div> 
        <Input type="button" value="Ready Go" id="begin" onclick="begin(this);"/>
    </body>    
</html>