javascriptでマインスイーパの初級を作る

1.マインスイーパのアルゴリズム

左クリックでマスを開ける

もしそのマスに旗が立っていないなら

もしそのマスに爆弾があるならゲームオーバー

でなければそのマスの周囲にある爆弾の数を表示

右クリックでマスに旗を立てる

もし残りのマスが71マスだったらクリア

2.完成したプログラム

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Minesweeper</title>
    <style>
        .color{
            background-color: dimgray;
            width: 30px;
            height:30px;
            color: red;
        }
        .color0{
            background-color: white;
            width: 30px;
            height:30px;
            color:white
        }
        .color1{
            background-color: white;
            color: blue;
            width: 30px;
            height:30px;
        }
        .color2{
            background-color: white;
            color: green;
            width: 30px;
            height:30px;
        }
        .color3{
            background-color: white;
            color: red;
            width: 30px;
            height:30px;
        }
        .color4{
            background-color: white;
            color: darkblue;
            width: 30px;
            height:30px;
        }
        .color5{
            background-color: white;
            color: brown;
            width: 30px;
            height:30px;
        }
        .color6{
            background-color: white;
            color: cyan;
            width: 30px;
            height:30px;
        }
        .color7{
            background-color: white;
            color: black;
            width: 30px;
            height:30px;
        }
        .color8{
            background-color: white;
            color: grey;
            width: 30px;
            height:30px;
        }
    </style>
</head>
<body>
    ⏱<a id="timer">0</a><img src='./img/hata.png' style='width: 20px;height: 20px;'><a id="hata"></a><br>
    <table id="masu" border="1" oncontextmenu="return false;" style="text-align: center;"></table>
    <a id="str"></a>
    <script>
        //変数を定義
        var gameover = 0
        var bakudannokazu = 0
        var saisyo = true
        var masu_list = new Array(9)
        var flag = new Array(9)
        var bom = new Array(9)
        var hata_list = new Array(9)
        var nokori = 0
        var hatanokazu = 0
        var start = 0
        var clear = 0
        for (var i = 0; i < 9;++i){
            flag[i] = new Array(9)
            bom[i] = new Array(9)
            masu_list[i] = new Array(9)
            hata_list[i] = new Array(9)
            for (var x = 0; x < 9;++x){
                flag[i][x] = 0
                bom[i][x] = 0
                hata_list[i][x] = ""
                masu_list[i][x] = ""
            }
        }
        //関数 setto を定義
        function setto(x,y){
            if (x != -1 && x != 9 && y != -1 && y != 9 && flag[x][y] == 0){
                bom[x][y] = 2
            }
        }
        //マスを絵画
        var masu_html = ""
        for (var x = 0;x < 9; ++ x){
            masu_html += "<tr>"
            for (var y = 0;y < 9; ++y){
                if (gameover == 1 && bom[x][y] == 1 && hata_list[x][y] == ""){
                    masu_html += "<td id='str" + x + "_" + y + "' style='background-color: dimgray;'>💣</td>"
                }else{
                    masu_html += "<td class='color" + masu_list[x][y] + "' onclick=akeru(" + x + "," + y + ")>" + masu_list[x][y] + "</td>"
                }
                if (flag[x][y] == 1){
                    akeru(x,y)
                }
            }
            masu_html += "</tr>"
        }
        document.getElementById("masu").innerHTML = masu_html
        //関数 hata を定義
        function hata(x,y){
            if (flag[x][y] == 0 && hata_list[x][y] == ""){
                ++hatanokazu
                hata_list[x][y] = "<img src='./img/hata.png' style='width: 20px;height: 20px;' oncontextmenu='hata(" + x + "," + y + ")'>"
            }else if (flag[x][y] == 0 && hata_list[x][y] == "<img src='./img/hata.png' style='width: 20px;height: 20px;' oncontextmenu='hata(" + x + "," + y + ")'>"){
                hata_list[x][y] = ""
                --hatanokazu
            }
            var masu_html = ""
            for (var x = 0;x < 9; ++ x){
                masu_html += "<tr>"
                for (var y = 0;y < 9; ++y){
                    if (gameover == 1 && bom[x][y] == 1 && hata_list[x][y] == ""){
                        masu_html += "<td id='str" + x + "_" + y + "' style='background-color: dimgray;'>💣</td>"
                    }else{
                        masu_html += "<td class='color" + masu_list[x][y] + "' onclick=akeru(" + x + "," + y + ") oncontextmenu='hata(" + x + "," + y + ")'>" + masu_list[x][y] + hata_list[x][y] + "</td>"
                    }
                }
                masu_html += "</tr>"
            }
            document.getElementById("masu").innerHTML = masu_html
            saisyo = false
        }
        //関数 akeru2 を定義
        function akeru2(x,y){
            if (x != -1 && x != 9 && y != -1 && y != 9){
                if (bom[x][y] == 1){
                    bakudannokazu += 1
                }
            }
        }
        //関数 akeru3 を定義
        function akeru3(x,y){
            if (x != -1 && x != 9 && y != -1 && y != 9 && flag[x][y] == 0){
                flag[x][y] = 1
            }
        }
        //関数 akeru を定義
        function akeru(x,y){
            if (hata_list[x][y] == "" && bom[x][y] != 1){
                if (saisyo){
                    var t = 0
                    setto(x+1,y+1)
                    setto(x+1,y)
                    setto(x+1,y-1)
                    setto(x,y+1)
                    setto(x,y)
                    setto(x,y-1)
                    setto(x-1,y+1)
                    setto(x-1,y)
                    setto(x-1,y-1)
                    while (t < 10){
                        k = Math.floor(Math.random() * 9)
                        g = Math.floor(Math.random() * 9)
                        if (bom[k][g] == 0){
                            if (bom[k][g] == 0){
                                bom[k][g] = 1
                                ++t
                            }
                        }
                    }
                    start = new Date()
                    console.log(1);
                }
                bakudannokazu = 0
                akeru2(x-1,y-1)
                akeru2(x,y-1)
                akeru2(x+1,y-1)
                akeru2(x-1,y+1)
                akeru2(x,y+1)
                akeru2(x+1,y+1)
                akeru2(x-1,y)
                akeru2(x+1,y)
                masu_list[x][y] = bakudannokazu
                if (bakudannokazu == 0){
                    akeru3(x-1,y-1)
                    akeru3(x,y-1)
                    akeru3(x+1,y-1)
                    akeru3(x-1,y+1)
                    akeru3(x,y+1)
                    akeru3(x+1,y+1)
                    akeru3(x-1,y)
                    akeru3(x+1,y)
                }
                flag[x][y] = 2
                ++nokori
            }
            if (bom[x][y] == 1 && hata_list[x][y] == ""){
                gameover = 1
                document.getElementById("str").innerText = "gameover"
            }
            var masu_html = ""
            for (var x = 0;x < 9; ++ x){
                masu_html += "<tr>"
                for (var y = 0;y < 9; ++y){
                    if (gameover == 1 && bom[x][y] == 1 && hata_list[x][y] == ""){
                        masu_html += "<td id='str" + x + "_" + y + "' style='background-color: dimgray;'>💣</td>"
                    }else{
                        masu_html += "<td class='color" + masu_list[x][y] + "' onclick=akeru(" + x + "," + y + ") oncontextmenu='hata(" + x + "," + y + ")'>" + masu_list[x][y] + hata_list[x][y] + "</td>"
                    }
                }
                masu_html += "</tr>"
            }
            document.getElementById("masu").innerHTML = masu_html
            saisyo = false
        }
        //関数 kaiga を定義
        function kaiga(){
            for (var x = 0;x < 9; ++ x){
                for (var y = 0;y < 9;++y){
                    if (flag[x][y] == 1){
                        akeru(x,y)
                    }
                }
            }
            if (!saisyo && clear == 0 && gameover == 0){
                document.getElementById("timer").innerText = Math.floor((new Date() - start) / 1000)
            }
            document.getElementById("hata").innerText = 10-hatanokazu
            if (nokori == 71 && gameover == 0){
                document.getElementById("str").innerText = "clear"
                clear = 1
            }
        }
        //関数 hata を1msごとに呼び出す
        setInterval(kaiga,1)
    </script>
</body>
</html>

リンク

3.難しかったこと

もともとkaigaでマスを表示していたけど早すぎてonclickが反応しなかったのでもしマスの状態に変化があるならマスを表示するということにした。

爆弾の場所を指定するときに最初にあけたときの周囲には爆弾が設置されないようにするという定義が難しかった。

多次元配列がよくわからなかった。

コメント

タイトルとURLをコピーしました