掃雷遊戲javascript html


<html>

    <head>
        <meta charset="utf-8" />
        <title>地雷遊戲</title>

        <style>
            .guoshengcontentdiv{
                width:1255px;
                height:600px;
                margin:auto;
            }
            .guoshengonediv {
                position: relative;
                width: 1000px;
                height: 600px;
                float: left;
            }
            
            .canvasguosheng {
                width: 1000px;
                height: 600px;
                position: absolute;
                left: 0px;
                top: 0px;
                border: 1px #aaa solid;
            }
            
            .guoshengtwodiv {
                float: left;
                width: 250px;
                height: 600px;
                border: 1px #aaa solid;
            }
        </style>

    </head>

    <body>

        <div class="guoshengcontentdiv">
            
            <div class="guoshengonediv">
                <canvas id="guoshengcanvas" width="1000" height="600" style="position:absolute;left:0px;top:0px;border:1px #aaa solid"></canvas>
            </div>

            <div class="guoshengtwodiv">
                <h2 align="center">掃雷-郭勝</h2>
                <hr />
                <table width="100%">
                    <tr align="center">
                        <td>10*10&nbsp;&nbsp;(bombers*20)</td>    
                        <td>
                            <input type="button" id="mod1" value="選擇" οnclick="init(10,10,20);" />
                        </td>
                    </tr>
                    <tr align="center">
                        <td>20*10&nbsp;&nbsp;(bombers*60)</td>    
                        <td>
                            <input type="button" id="mod2" value="選擇" οnclick="init(15,20,60);" />
                        </td>
                    </tr>
                    <tr align="center">
                        <td>30*20&nbsp;&nbsp;(bombers*100)</td>    
                        <td>
                            <input type="button" id="mod3" value="選擇" οnclick="init(20,30,100);" />
                        </td>
                    </tr>
                </table>
                <hr />
                
                <!--
                    作者:offline
                    時間:2018-01-11
                    描述:自定義模塊  郭勝
                -->
                <fieldset>
                    <legend>自定義</legend>
                    列數:<input type="text" id="cols" value="20"><br />
                    行數:<input type="text" id="rows" value="10"/><br />
                    炸彈數:<input type="text" id="bomber" value="50" /><br />
                    <input type="button" value="確定" id="custom" />
                </fieldset>
                <hr />
                
                <table>
                    <tr>
                        <td>時間:</td>
                        <td><input type="text" id="time" value="0" readonly="true" style="border:none"/></td>
                    </tr>
                    <tr>
                        <td>雷數:</td>
                        <td><input type="text" id="bombernum" value="0" readonly="true" style="border:none"/></td>
                    </tr>
                </table>
                <hr />
                <div >
                    <p>有問題的人歡迎聯繫我</p>
                    <p>艾尚編程工作室(郭經理):18795465900</p>
                </div>
            </div>
            
        </div>
    </body>

</html>
<script type="text/javascript">
    /*
     * 加載完頁面後執行
     * 郭勝
     */
    window.onload = function(){
        init(15,20,40);
    }
    
    var $id = function(idname){return document.getElementById(idname);}
    var s;
    var yougess;
    var bombnum;
    
    /*
     * 顯示時間
     * 郭勝
     */
    function showtime(){
        $id("time").value = Number($id("time").value)+1;
    }
    
    /*
     * 數據驗證
     * 郭勝
     */
    $id("cols").onblur = function(){
        if(!isNaN($id("cols").value)){//是否是數字
            if(Number($id("cols").value)>30 || Number($id("cols").value)<0){
                alert("數字必須在0~30之間!記住!記住!記住!");
                $id("cols").value = 20;
            }
        }else{
            alert("是不是瞎?是不是瞎?是不是瞎?輸入數字!是數字!TMD是數字啊!!!");
            $id("cols").value = 20;
        }
    }
    
    /*
     * 數據驗證
     * 郭勝
     */
    $id("rows").onblur = function(){
        if(!isNaN($id("rows").value)){//是否是數字
            if(Number($id("rows").value)>20 || Number($id("rows").value)<0){
                alert("數字必須在0~30之間!記住!記住!記住!");
                $id("rows").value = 10;
            }
        }else{
            alert("是不是瞎?是不是瞎?是不是瞎?輸入數字!是數字!TMD是數字啊!!!");
            $id("rows").value = 10;
        }
    }
    
    /*
     * 數據驗證
     * 郭勝
     */
    $id("bomber").onblur = function(){
        if(!isNaN($id("bomber").value)){//是否是數字
            if(Number($id("bomber").value)> Number($id("rows").value)*Number($id("cols").value)*0.85 || Number($id("bomber").value)<0){
                alert("數字必須在0~"+Number($id("rows").value)*Number($id("cols").value)*0.85+"之間!記住!記住!記住!");
                $id("bomber").value = 50;
            }
        }else{
            alert("是不是瞎?是不是瞎?是不是瞎?輸入數字!是數字!TMD是數字啊!!!");
            $id("bomber").value = 50;
        }
    }
    
    /*
     * 自定義初值
     */
    $id("custom").onclick = function(){
        init(Number($id("cols").value),Number($id("rows").value),Number($id("bomber").value));
    }
    
    var nowI = -1, nowJ = -1, preI = -1, preJ = -1;
    
    /*
     * 初始化
     */
    function init(cols,rows,bomb){
        bombnum = bomb;
        clearInterval(s);//清除上次的時間
        $id("time").value = 0;//時間更新爲0
        s = setInterval(showtime(),1000);
        $id("bombernum").value = bombnum;
        var gamedata = new doubleArray(rows,cols);
        var i = bombnum;
        while(i>0){//初始化炸彈信息,炸彈值爲-1
            //Math.ceil向上取整,Math.floor,捨棄取整,向下取整
            var randnum = Math.ceil(Math.random()*rows*cols);
            if(Math.floor(randnum/cols)==randnum/cols){//列的整數倍
                var tmpx = Math.floor(randnum/cols) -1;//不能超過行數
            }else{
                var tmpx = Math.floor(randnum/cols);
            }
            var tempy = randnum - tmpx * cols -1;
            if(gamedata[tmpx][tempy] != -1){
                gamedata[tmpx][tempy] = -1;
                i--;
            }
        }
        //初始化除了炸彈之外的數據
        for(var i = 0;i<rows;i++){
            for(var j = 0;j<cols;j++){
                if(gamedata[i][j] != -1){
                    /*
                     * 值爲0:上下左右都沒有炸彈
                     * 值爲1:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有一個炸彈
                     * 值爲2:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有兩個炸彈
                     * 值爲3:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有三個炸彈
                     * 值爲4:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有四個炸彈
                     * 值爲5:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有五個炸彈
                     * 值爲6:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有六個炸彈
                     * 值爲7:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有七個炸彈
                     * 值爲8:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有八個炸彈
                     * 郭勝
                     */
                    gamedata[i][j] = (exist(gamedata,i-1,j-1) == 1?1:0) //左下
                                    + (exist(gamedata,i-1,j) == 1?1:0)  //正左
                                    + (exist(gamedata,i-1,j+1) == 1?1:0) //左上
                                    +(exist(gamedata,i,j-1) == 1?1:0) //正下
                                    + (exist(gamedata,i,j+1) == 1?1:0) //正上
                                    +(exist(gamedata,i+1,j-1) == 1?1:0) //右上
                                    +(exist(gamedata,i+1,j) == 1?1:0)//正右
                                    +(exist(gamedata,i+1,j+1) == 1?1:0);//右下
                }
            }
        }
        var ctx = $id("guoshengcanvas").getContext("2d");
        //返回之前保存過的路徑狀態和屬性
        ctx.restore();
        //在給定的矩形內清除指定的像素
        ctx.clearRect(0,0,1000,600);
        //保存當前環境的狀態
        ctx.save();
        
        //重新映射畫布上的 (0,0) 位置
        ctx.translate(500 - 15*cols,300-15*rows);
        //起始一條路徑,或重置當前路徑
        ctx.beginPath();
        //繪製“被填充”的矩形
        ctx.fillRect(0,0,30*cols,30*rows);
        gamestart(ctx,gamedata);//開始遊戲
    }
    
    /*
     * 開始遊戲
     * 郭勝
     */
    function gamestart(ctx,gamedata){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        var placestate = new doubleArray(rows,cols);//各個點的狀態,翻轉與否
        for(var i=0;i<rows;i++){//初始化
            for(var j = 0;j<cols;j++){
                placestate[i][j] = "0";
            }
        }
        
        //完全初始化
        for(var i=0;i<rows;i++){
            for(var j=0;j<cols;j++){
                startprint(ctx,gamedata,i,j);
            }
        }
        
        //移動模擬
        $id("guoshengcanvas").onmousemove = function(e){
            havor(ctx,gamedata,placestate,e.offsetX,e.offsetY);
        }
        
        //按鍵模擬
        $id("guoshengcanvas").onmousedown = function(e){
            if(e.button == 0){
                show(ctx,gamedata,placestate,e.offsetX,e.offsetY);
            }else{//標記炸彈
                addmark(ctx,gamedata,placestate,e.offsetX,e.offsetY);
            }
        }
    }
    
    /*
     * 點擊之後顯示的結果
     * 將座標值轉化爲確定的值
     * 郭勝
     */
    function show(ctx,gamedata,placestate,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        if(x>500-15*cols && y>300-15*rows && x<500+15*cols && y<300+15*rows){
            findspace(ctx,gamedata,placestate, Math.floor((y-(300 -15*rows))/30), Math.floor((x-(500-15*cols))/30) );
        }
    }
    
    /*
     * 尋找可以一起翻開的空格
     * 郭勝
     */
    function findspace(ctx ,gamedata,placestate,x,y){
        //x,y是指整數位置
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        var X = y*30;
        var Y = x*30;
        //XY是標準的座標偏移量
        ctx.fillStyle = "rgb(189,199,224)";
        ctx.fillRect(X,Y,29,29);
        placestate[x][y] = "1";//先翻開再說
        var tmp = gamedata[x][y];
        switch(tmp){
            case 1: ctx.fillStyle = "rgb(60,80,182)"; break;
            case 2: ctx.fillStyle = "rgb(35,100,6)"; break;
            case 3: ctx.fillStyle = "rgb(174,4,9)"; break;
            case 4: ctx.fillStyle = "rgb(8,8,130)"; break;
            case 5: ctx.fillStyle = "rgb(95,12,18)"; break;
            case 6: ctx.fillStyle = "rgb(255,128,0)"; break;
            case 7: ctx.fillStyle = "rgb(152,33,254)"; break;
            case 8: ctx.fillStyle = "rgb(51,84,62)"; break;
        }
        if(tmp == -1){//是炸彈
            for(var i = 0;i<rows;i++){
                for(var j = 0;j<cols;j++){
                    addbomber(ctx,gamedata,i,j);
                }
            }
            clearInterval(s);
            if(confirm("沒有一點熊用,這麼簡單的遊戲還輸了!!!") == true){
                init(15,20,40);
                return false;
            }else{
                return false;
            }
        }else{//不是炸彈,則畫出數字
            ctx.font = "28px Adobe Gothic Std B";
            ctx.fillText(tmp,X+7,Y+23);
        }
        //雙重循環,循環本次位置的左上,左下,右上,右下
        for(var i = -1;i<= 1;i++){
            for(var j= -1;j<=1;j++){
                if(i != 0 || j != 0){
                    if(exist(gamedata,x+i,y+j) != "notexist"){//位置存在
                        if(exist(gamedata,x,y) != 0){//位置存在,且值不是12345678,保證不把炸彈翻出來,當前位置
                            if(placestate[x+i][y+j] == "0"){//未翻開,遞歸繼續
                                findspace(ctx,gamedata,placestate,x+i,y+j)
                            }
                        }else{//下一個位置未翻看並且下一個位置的值爲0,代表着該位置的周圍八個位置都沒有炸彈,下個位置
                            if(placestate[x+i][y+j] == "0" && exist(gamedata,x+i,y+j) == "none"){
                                findspace(ctx,gamedata,placestate,x+i,y+j)
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    
    /*
     * 繪製炸彈
     * 郭勝
     */
    function addbomber(ctx,gamedata,i,j){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        ctx.fillStyle = "red";
        ctx.save();
        ctx.translate(j*30,i*30);//重新定位座標
        if(gamedata[i][j] == -1){
            ctx.save();
            ctx.shadowOffsetX = 2;
            ctx.shadowOffsetY = 2;
            ctx.shadowBlur = 2;
            ctx.shadowColor = "rgba(0,0,0,0.5)";
            ctx.translate(15,15);//重新定位圓點座標
            ctx.beginPath();
            ctx.arc(0,0,10,0,Math.PI*2,false);
            ctx.fill();
            ctx.restore();
        }
        ctx.restore();
    }
    
    /*
     * 添加標記
     * 郭勝
     */
    function addmark(ctx,gamedata,placestate,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        var i = Math.floor((y-(300-15*rows))/30);//畫布中方塊的位置
        var j = Math.floor((x-(500-15*cols))/30);//畫布中方塊的位置
        ctx.fillStyle = "green";
        ctx.save();
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;
        ctx.shadowBlur = 2;
        ctx.shadowColor = "rgba(0,0,0,0.5)";
        ctx.translate(j*30,i*30);
        if(placestate[i][j] == "0"){//未翻轉
            ctx.translate(15,15);
            ctx.beginPath();
            ctx.arc(0,0,10,0,Math.PI*2,false);
            ctx.fill();
        }
        ctx.restore();
        placestate[i][j] = "1";
        if(gamedata[i][j] == -1){
            bombnum --;
        }
        if(bombnum == 0){
            clearInterval(s);
            if(confirm("臭小子,你用了"+$id("time").value+"秒贏了遊戲,不要驕傲!要不要再來一次,鞏固一下基礎?") == true){
                init(15,20,40);
            }
        }
    }
    
    
    /*
     * 懸浮之後樣式的變化
     * 郭勝
     * x,y是相對瀏覽器中的座標
     * 要計算出畫布中的座標
     * 畫布相對於瀏覽器的起始座標是(500-15*cols),300 - 15*rows,但是對於畫布則是(0,0)
     *
     */
    function havor(ctx,gamedata,placestate,x,y){
        var rows  = gamedata.length;
        var cols = gamedata[0].length;
        if(x>500 - 15*cols && y>300-15*rows &&x<500+15*cols && y<300+15*rows){//判斷鼠標點擊所在的左邊是否在遊戲主界面內
            ctx.fillStyle = "rgb(255,128,0)";
            //計算出鼠標所在的畫布中的方塊的起始座標
            nowJ = Math.floor((y-(300-15*rows))/30)*30;//新位置的絕對座標
            nowI = Math.floor((x-(500 - 15*cols))/30)*30;//新位置的絕對座標
            if(nowI != preI || nowJ != preJ){
                if(placestate[Math.round(nowJ/30)][Math.round(nowI/30)] == "0"){//判斷該位置是否已翻開,0爲未翻開
                    ctx.fillRect(nowI,nowJ,29,29);
                }
                //將原來的沒翻開的方塊還原
                if(preI != -1 && placestate[Math.round(preJ/30)][Math.round(preI/30)] == "0"){
                    //設置顏色漸變
                    var radgrad = ctx.createRadialGradient(30,30,1,45,45,(rows>cols?rows:cols)*30);
                    radgrad.addColorStop(0,'#C4E1FF');
                    radgrad.addColorStop(0.9,'rgb(36,66,147)');
                    ctx.fillStyle = radgrad;
                    ctx.fillRect(preI,preJ,29,29);
                }
                preI = nowI;//老位置的絕對座標
                preJ = nowJ;//老位置的絕對座標
            }
        }
    }
    
    /*
     * 圖形上特定位置初始化
     * 郭勝
     */
    function startprint(ctx,gamedata,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        //創建放射狀/環形的漸變(用在畫布內容上)createRadialGradient()
        var radgrad = ctx.createRadialGradient(30,30,1,45,45,(rows>cols?rows:cols)*30);
        radgrad.addColorStop(0,'#C4E1FF');
        radgrad.addColorStop(0.9,'rgb(36,66,147)');
        //設置或返回用於填充繪畫的顏色、漸變或模式
        ctx.fillStyle = radgrad;
        ctx.fillRect(30*y,30*x,29,29);
    }
    
    /*
     * 檢測位置是否存在,並判斷有沒有雷
     * 郭勝
     */
    function exist(gamedata,x,y){
        var rows = gamedata.length;
        var cols = gamedata[0].length;
        if(x>= 0 && y>=0 && x<rows && y<cols){
            if(gamedata[x][y] == -1){//存在,並且是炸彈,返回1
                return Number(1);
            }else if(gamedata[x][y] == 0){//存在,值爲0,安全值,留給遞歸查詢出來
                return "none";
            }else{//存在,其它情況即:12345678
                return Number(0);
            }
        }else{
            return "notexist";
        }
    }
    
    /*
     * 創建二維數組
     * 郭勝
     */
    function doubleArray(m,n){
        var arr = new Array(m);//先創建一個一維數組arr
        for(var i= 0;i<m;i++){
            var arrtmp = new Array(n);
            arr[i] = arrtmp;//爲arr每個元素再創建一個數組arrtmp
        }
        return arr;//返回二維數組
    }
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章