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が反応しなかったのでもしマスの状態に変化があるならマスを表示するということにした。
爆弾の場所を指定するときに最初にあけたときの周囲には爆弾が設置されないようにするという定義が難しかった。
多次元配列がよくわからなかった。
コメント