也分享自己做的JS掃雷小游戲


看了草根程序猿分享的JS掃雷小游戲

想起去年的時候自己也做了一個

於是也拿出來分享之

先上截圖~

引用了jQuery,節省了很多鼠標點擊上的判斷

界面顯然都是照搬Windows的掃雷啦

詳細的內容注釋里都有,我就不啰嗦啦~

【JS部分】

var mineArray,  //地雷數組
    lastNum,  //剩余雷數
    countNum,  //未被揭開的方塊數
    inGame = 0,  //游戲狀態,0為結束,1為進行中,2為初始化完畢但未開始
    startTime;  //開始時間
    //以下操作1表示揭開一個方塊,操作2表示標記一個小旗,操作3表示標記一個問號,操作4表示若某個方塊周圍的地雷全都標記完,則將其周圍剩下的方塊挖開
$(function(){
    $('#main').mouseup(function(e) {
        var clicked = $(e.target),
            id = clicked.attr('id'),
            cX = parseInt(id.substring(1, id.indexOf('-'))),  //所點擊方格的X坐標
            cY = parseInt(id.substring(id.indexOf('-') + 1));  //所點擊方格的Y坐標
        if(inGame == 1) {
            if(e.which == 1) {
                if(clicked.hasClass('hidden') && !clicked.hasClass('flag')) {
                    openBlock(cX,cY);  //左鍵點擊未揭開且未插旗方塊即執行操作1
                } else if(!clicked.hasClass('hidden')) {
                    openNearBlock(cX,cY);  //由於同時點擊左右鍵實現起來比較麻煩,所以改成用點擊左鍵實現操作4
                }
            } else if(e.which == 3 && clicked.hasClass('hidden')) {  //右鍵點擊操作2,如果允許使用問號標記,則可執行操作3
                if(clicked.hasClass('flag')) {
                    clicked.removeClass('flag');
                    if($('#check').attr('checked')) clicked.addClass('check');
                    lastNum ++;
                    countNum ++;
                } else if(clicked.hasClass('check')) {
                    clicked.removeClass('check');
                } else {
                    clicked.addClass('flag');
                    lastNum --;
                    countNum --;
                }
                $('#lastnum').text(lastNum);
            }
            if(lastNum == countNum) endGame(1);  //因為最后剩下的方塊均為雷時應直接結束游戲,因此設置為剩余雷數和未被揭開的方塊數相等的時候結束游戲
        } else if(inGame == 2) {
            if(e.which == 1) {  //初始化完畢后只允許點擊左鍵開始游戲
                openBlock(cX,cY);
                inGame = 1;
                var now = new Date();
                startTime = now.getTime();
                timer();
            }
        }
    });
    $('#main').bind('contextmenu', function(){ return false; });  //阻止默認右擊事件
});
//初始化
function init(x, y, mine) {
    countNum = x * y;
    inGame = 2;
    lastNum = mine;
    mineArray = new Array(y + 2);
    $.each(mineArray, function(key) {
        mineArray[key] = new Array(x + 2);
    });
    for(var i = 1; i <= y; i ++) {
        for(var j = 1; j <= x; j ++) {
            mineArray[i][j] = 0;
        }
    }
    while(mine > 0) {  //隨機布雷,-1為有雷
        var i = Math.ceil(Math.random() * y);
        var j = Math.ceil(Math.random() * x);
        if(mineArray[i][j] != -1) {
            mineArray[i][j] = -1;
            mine --;
        }
    }
    for(var i = 1; i <= y; i ++) {  //遍歷地雷數組,統計每個格子四周地雷的數量
        for(var j = 1; j <= x; j ++) {
            if(mineArray[i][j] != -1) {
                if(i > 1 && j > 1 && mineArray[i - 1][j - 1] == -1) mineArray[i][j] ++;
                if(i > 1 && mineArray[i - 1][j] == -1) mineArray[i][j] ++;
                if(i > 1 && j < x && mineArray[i - 1][j + 1] == -1) mineArray[i][j] ++;
                if(j < x && mineArray[i][j + 1] == -1) mineArray[i][j] ++;
                if(i < y && j < x && mineArray[i + 1][j + 1] == -1) mineArray[i][j] ++;
                if(i < y && mineArray[i + 1][j] == -1) mineArray[i][j] ++;
                if(i < y && j > 1 && mineArray[i + 1][j - 1] == -1) mineArray[i][j] ++;
                if(j > 1 && mineArray[i][j - 1] == -1) mineArray[i][j] ++;
            }
        }
    }
    var block = '';
    for(var i = 1, row = mineArray.length - 1; i < row; i ++) {
        for(var j = 1, col = mineArray[0].length - 1; j < col; j ++) {
            block += '<div id="b' + i + '-' + j + '" style="left:' + (j - 1) * 20 + 'px;top:' + (i - 1) * 20 + 'px;" class="hidden"></div>';
        }
    }
    $('#main').html(block).width(x * 20 + 1).height(y * 20 + 1).show();  //繪圖
    $('#warning').html('');
    $('#submenu').show();
    $('#lastnum').text(lastNum);
}
//揭開方塊
function openBlock(x, y) {
    var current = $('#b' + x + '-' + y);
    if(mineArray[x][y] == -1) {
        if(inGame == 1) {  //觸雷時如游戲進行中,則失敗結束游戲
            current.addClass('cbomb');
            endGame();
        } else if(inGame == 2) {  //如游戲初始化后還未開始,則重新初始化地雷陣,再揭開此方塊,以保證第一次點擊不觸雷
            init(mineArray[0].length - 2, mineArray.length - 2, lastNum);
            openBlock(x, y);
        } else {  //游戲結束時需揭開全部方塊,標記地雷位置
            if(!current.hasClass('flag')) current.addClass('bomb');
        }
    } else if(mineArray[x][y] > 0) {
        if(current.hasClass('flag')) {  //若在無雷的方塊上標記了小旗,如果周圍的廣場執行操作4時波及到此方塊,則觸發失敗結束游戲
            current.addClass('wrong');
            if(inGame) endGame();
        } else {
            current.html(mineArray[x][y]).addClass('num' + mineArray[x][y]).removeClass('hidden');  //顯示周邊的地雷數量
            if(current.hasClass('check')) current.removeClass('check');
            if(inGame) countNum --;
        }
    } else {
        if(current.hasClass('flag')) {  //同上
            current.addClass('wrong');
            if(inGame) endGame();
        } else {
            current.removeClass('hidden');
            if(current.hasClass('check')) current.removeClass('check');
            if(inGame) {  //點擊到周邊無雷的方塊時,自動揭開周圍方塊
                countNum --;
                var row = mineArray.length - 2, col = mineArray[0].length - 2;
                if(x > 1 && y > 1 && $('#b' + (x - 1) + '-' + (y - 1)).hasClass('hidden')) openBlock(x - 1, y - 1);
                if(x > 1 && $('#b' + (x - 1) + '-' + y).hasClass('hidden')) openBlock(x - 1, y);
                if(x > 1 && y < col && $('#b' + (x - 1) + '-' + (y + 1)).hasClass('hidden')) openBlock(x - 1, y + 1);
                if(y < col && $('#b' + x + '-' + (y + 1)).hasClass('hidden')) openBlock(x, y + 1);
                if(x < row && y < col && $('#b' + (x + 1) + '-' + (y + 1)).hasClass('hidden')) openBlock(x + 1, y + 1);
                if(x < row && $('#b' + (x + 1) + '-' + y).hasClass('hidden')) openBlock(x + 1, y);
                if(x < row && y > 1 && $('#b' + (x + 1) + '-' + (y - 1)).hasClass('hidden')) openBlock(x + 1, y - 1);
                if(y > 1 && $('#b' + x + '-' + (y - 1)).hasClass('hidden')) openBlock(x, y - 1);
            }
        }
    }
}
//揭開格子鄰近確認無雷的方塊
function openNearBlock(x, y) {
    var flagNum = 0, hiddenNum = 0;
    for(i = x - 1; i < x + 2; i ++) {
        for(j = y - 1; j < y + 2; j ++) {
            if(mineArray[i][j] != undefined) {
                if($('#b' + i + '-' + j).hasClass('flag')) flagNum ++;  //統計方塊周圍的旗幟數和未揭開的方塊數
                if($('#b' + i + '-' + j).hasClass('hidden')) hiddenNum ++;
            }
        }
    }
    if(flagNum == mineArray[x][y] && hiddenNum > flagNum) {  //旗幟數和雷數相等且有未揭開方塊且未插旗的方塊時,則揭開它
        for(i = x - 1; i < x + 2; i ++) {
            for(j = y - 1; j < y + 2; j ++) {
                if(mineArray[i][j] >= 0 && $('#b' + i + '-' + j).hasClass('hidden')) openBlock(i, j);
            }
        }
    }
}
//計時
function timer(){
    if(inGame == 1) {  //只在游戲進行中計時
        var now = new Date(),
            ms = now.getTime();
        $('#time').text(Math.ceil((ms - startTime) / 1000));
        if(inGame == 1) setTimeout(function() { timer(); }, 500);
    } else if(inGame == 2) {
        $('#time').text('0');
    }
}
//結束游戲
function endGame(isWin) {
    inGame = 0;
    for(var i = 1, row = mineArray.length - 1; i < row; i ++) {
        for(var j = 1, col = mineArray[0].length - 1; j < col; j ++) {
            if(isWin) {
                if($('#b' + i + '-' + j).hasClass('hidden') && !$('#b' + i + '-' + j).hasClass('flag')) $('#b' + i + '-' + j).addClass('flag');
                lastNum = 0;
                $('#lastnum').text(lastNum);
            } else {
                openBlock(i, j);
            }
        }
    }
    $('#warning').text(isWin ? 'You Win!' : 'You Lose!');
}

【HTML部分】

<div id="menu">
    <a href="javascript:;" onclick="init(10,10,10);">初級</a>
    <a href="javascript:;" onclick="init(16,16,40);">中級</a>
    <a href="javascript:;" onclick="init(30,16,99);">高級</a>
    <input type="checkbox" id="check" /><label for="check">是否使用標記(?)</label>
</div>
<div id="submenu">
    剩余雷數:<span id="lastnum"></span>
    時間:<span id="time"></span><span id="warning"></span>
</div>
<div id="main"></div>

【CSS部分】

body{background:#fff;font-size:14px;}
#submenu{display:none;}
#warning{color:#ff0000;}
#main{background:#ddd;border:1px solid #888;display:none;position:relative;}
#main div{border:1px solid #888;font-weight:bold;height:19px;height:21px\9;line-height:18px;cursor:default;position:absolute;text-align:center;width:19px;width:21px\9;}
.hidden{background:url(mine.gif) 0 0;}
.flag{background:url(mine.gif) -19px 0;}
.check{background:url(mine.gif) -38px 0;}
.bomb{background:url(mine.gif) -57px 0;}
.cbomb{background:url(mine.gif) -57px 0 #ff0000;}
.wrong{background:url(mine.gif) -76px 0;}
.num1{color:#0000ff;}
.num2{color:#008000;}
.num3{color:#ff0000;}
.num4{color:#000080;}
.num5{color:#800000;}
.num6{color:#008080;}
.num7{color:#000000;}
.num8{color:#808080;}

最后是運行效果,點擊下邊的不同難度等級就可以開始游戲了~

因為和博客園網頁代碼沖突的原因,做了些小改動……

 

初級 中級 高級 幫助
游戲規則:掃雷就是要把所有非地雷的格子揭開即勝利;踩到地雷格子就算失敗。
游戲操作:游戲主區域由很多個方格組成。
使用 鼠標左鍵點擊一個方格,方格即被打開並顯示出方格中的數字;方格中數字則表示其周圍的8個方格隱藏了幾顆雷;
如果點開的格子為空白格,即其周圍有0顆雷,則其周圍格子自動打開;如果其周圍還有空白格,則會引發連鎖反應;
在你認為有雷的格子上, 點擊鼠標右鍵即可標記雷;
如果一個已打開格子周圍所有的雷已經正確標出,則可以在此格上 點擊鼠標左鍵打開其周圍剩余的無雷格。

巴里切羅 http://www.baliqieluo.com/
剩余雷數:   時間:   
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM