Minesweeper GroupA Team P’Arin
✨ Thanawat Jantawong
<!-- Powered by https://caijin.tech/blog/ https://www.101computing.net/minesweeper-in-javascript/ ดูแนวทางคิดรูปแบบเป็น Ref ครับ--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>minesweep</title> <link rel="stylesheet" href="style.css"> <style> @import url('https://fonts.googleapis.com/css2?family=Cabin+Sketch:wght@700&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Itim&display=swap'); *{ font-family: 'Itim', sans-serif; } body { text-align: center; position: relative; background: url('https://i.pinimg.com/originals/8b/7f/bc/8b7fbc2e623720393ad7ffa7e4896eac.gif') no-repeat; background-size: cover; } h1 { font-family: 'Cabin Sketch', cursive; font-size:10vh; color: purple; animation:colorchange 2s infinite; } h1:hover{ font-family: 'Cabin Sketch', cursive; font-size:10vh; color: #d73179; } .level { margin-top: 30px; font-size: 18px; } .level button { padding: 5px 20px; background: rgb(67, 183, 189); /* border: 1px solid rgb(129, 129, 129); */ border: none; box-shadow: 3px 2px 5px hsl(183, 48%, 40%); color: white; font-size: 20px; border-radius: 3px; outline: none; cursor:pointer; } .level button:hover { animation-name:dengdueng; animation-duration: .75s; background: rgb(23, 132, 138); } .row { margin: 0; padding: 0; overflow: hidden; letter-spacing: -8px; } .col { display: inline-block; background: radial-gradient(closest-side, hsl(278, 100%, 90%), #cf7cff); /* border: 2px solid #008aff; */ border: 1.5px solid white; box-shadow: 2px 1px 5px hsl(278, 100%, 40%); margin: 1.5px; width: 20px; height: 20px; letter-spacing: normal; position: relative; border-radius: 5px; transition: .3s; } .col span { display: inline-block; position: relative; top: 0px; opacity: 0; font-weight: bold; cursor:default; } .col:hover { background: #d73179; transform:scale(0.9); } .gameBox { margin-top: 30px; } .img-flag { position: absolute; top: 3px; left: 3.5px; width: 15px; height: 15px; } .hide { display: none; } .boom { background: url('https://i.gifer.com/4xjg.gif') no-repeat 5px 5px; background-color: white; background-size: 20px 20px; background-position-x:0px; background-position-y:0px; } .div-boom { font-size: 30px; position: fixed; top: 50px; left: 50%; } .info { margin-top: 30px; } .info p { display: inline-block; font-size:25px; width: 200px; margin: 0 10px; } .info p span { font-family: 'Cabin Sketch', cursive; color: #d73179; } .info p span:hover { font-size:30px; cursor:pointer; } .num-1 { color: rgb(8, 153, 235); } .num-2 { color: rgb(255, 45, 178); } .num-3 { color: rgb(109, 224, 176); } .num-4 { color: rgb(8, 153, 235); } .num-5 { color: rgb(255, 167, 45); } .num-6 { color: rgb(49, 140, 102); } .num-7 { color: rgb(168, 55, 237); } .num-8 { color: rgb(15, 254, 154); } @keyframes dengdueng { from { transform: scale3d(0.75, 1, 1); } 30% { transform: scale3d(1.15, 0.75, 1); } 40% { transform: scale3d(0.75, 1.25, 1); } 50% { transform: scale3d(1.05, 0.85, 1); } 65% { transform: scale3d(.95, 1.05, 1); } 75% { transform: scale3d(1.05, .95, 1); } to { transform: scale3d(1, 1, 1); } } @keyframes colorchange{ from { color:purple; 0 } 40%{ color:#d73179; transform:rotateY(-10deg) } 80%{ color:#d73179; transform:rotateY(10deg) } to{ color:purple; transform:rotateY(0deg) } } </style> </head> <body> <header> <h1 id="changetext" onmouseover="textre()" onmouseout="textback()">Minesweepers</h1> </header> <div class="level"> <button type="button" name="button" class="choice-level">ง่าย</button> <button type="button" name="button" class="choice-level">ปานกลาง</button> <button type="button" name="button" class="choice-level">ยาก</button> <button type="button" name="button" class="restart">เริ่มเกมใหม่</button> </div> <div class="gameBox"></div> <div class="info"> <p class=""> จำนวนระเบิด : <span class="residue"></span> </p> <p> เวลา : <span class="tick"></span> วินาที </p> </div> <script charset="utf-8"> /* เกมมายสวีปเปอออออออออออออออออออออออออออออออออออออออวิชามัลติมิเดียคึ ง่าย:ระเบิด 10 9*9 ปานกลาง:ระเบิด 40 16*16 ยาก:ระเบิด 99 28*28 ขั้นแรก: เอาต์พุตหนึ่ง [ [1, 9, 2, 1], [2, 4, 9, 2], [9, 4, 9, 2], [2, 9, 2, 1], ] อาร์เรย์ดังกล่าวค่าที่ต้องการคือ 1 จำนวนระเบิด 2 จำนวนแถวและคอลัมน์ ขั้นตอน: 1. สร้างอาร์เรย์หลายมิติตามจำนวนแถวและคอลัมน์ (ใช้สำหรับการซ้อนแบบวนซ้ำ) 2. จากนั้นใช้ Math random a [x] [x] เพื่อเขียนตำแหน่งของระเบิด (ใช้ for loop อีกครั้งเขียน 1) หากมีobjectในช่องนั้นอยู่แล้วให้ทำการสุ่มใหม่แล้วเขียน 3. ดูข้อ1-2 กระบวนการ: 1 อย่างแรกสร้างบรรทัดแรก 2. คัดลอกลงในคอลัมน์ 3. สิ่งของในเหมือง 4. เขียนการใช้งานฟังก์ชัน: ถ้าค่าของตำแหน่งอาร์เรย์เป็น 1 ให้เพิ่ม 1 ในค่าของวงกลมด้านข้างหรือรอบๆ */ var IsGameOver = true; // 1,คำนวณตารางระเบิด var mineSweepingMap = function (r, c, num) { var map = [] // กำหนดจำนวนแถวให้สร้างอาร์เรย์ 1 มิติ var row = function (r) { for (var i = 0; i < r; i++) { map[i] = new Array() } } // กำหนดจำนวนคอลัมน์ให้สร้างอาร์เรย์ 2 มิติ var column = function (col) { for (var i = 0; i < map.length; i++) { for (var j = 0; j < col; j++) { map[i][j] = 0 } } } // Generate map ว่างๆมาใส่ตัวเลข col row var blankMap = function (r, col) { row(r) column(col) } // สร้างแผนที่ว่างสำหรับจำนวนคอลัมน์และแถว var writeInMine = function (num) { // เขียนตำแหน่งสุ่ม var randomLocation = function () { var x = Math.floor(Math.random() * r) var y = Math.floor(Math.random() * c) // console.log( ':', x, y); if (map[x][y] !== 9) { map[x][y] = 9 } else { randomLocation() } } for (var i = 0; i < num; i++) { randomLocation() } } // ใช้ loop เพื่อบวกค่า 1 ให้ตัวเลขรอบๆช่อง ยกเว้นช่องนั้นกดเปิดไปแล้ว var plus = function (array, x, y) { if (x >= 0 && x < r && y >= 0 && y < c) { if (array[x][y] !== 9) { array[x][y] += 1 } } } var writeInHint = function () { for (var x = 0; x < map.length; x++) { for (var y = 0; y < map[0].length; y++) { if (map[x][y] === 9) { // บนล่าง for (var i = -1; i < 2; i++) { plus(map, x - 1, y + i) plus(map, x + 1, y + i) } // ซ้ายขวา plus(map, x, y + 1) plus(map, x, y - 1) } } } } blankMap(r, c) writeInMine(num) writeInHint() return map } // 2,สร้าง ตาราง var writeHtml = function (map) { // เขียน ul ผ่านจำนวนแกน y แล้วเขียน li ผ่านจำนวนแกน x var x = document.querySelector('.gameBox') for (var i = 0; i < map.length; i++) { x.innerHTML = x.innerHTML + `<ul class="row x-${i}" data-x="${i}"></ul>` } var z = document.querySelectorAll('.row') for (var i = 0; i < z.length; i++) { for (var j = 0; j < map[0].length; j++) { var m = map[i][j] if (m === 0) { m = '' } z[i].innerHTML = z[i].innerHTML + ` <li class="col y-${j} num-${m}" data-y="${j}"> <span>${m}</span> <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5d/White_flag_icon.svg/375px-White_flag_icon.svg.png" class="img-flag hide"> </li>` } } } // เช็คชนะ var changeClearMineNum = function (clearMineNum) { // console.log('zmzmzmzm'); // console.log('zz', zz); if (clearMineNum === ((col * row) - num)) { var all = document.querySelectorAll('.col') var allNum = 0 var stop = setInterval(function () { var r = Math.floor(Math.random() * 256) var g = Math.floor(Math.random() * 256) var b = 210 // var b = Math.floor(Math.random() * 256) all[allNum].children[0].style.opacity = `0` all[allNum].children[1].style.opacity = '0' all[allNum].style.background = `rgba(${r},${g},${b},0.6)` allNum++ if (allNum === all.length) { clearInterval(stop) if (zz === 0) { alert('ยินดีด้วย คุณชนะแล้ว!') initializeGame(row, col, num) } initializeGame(row, col, num) } }, 20) } } // 3,เคลียระเบิดตอนชนะ var clearMine = function (row, col, num) { var clearMineNum = 0 var makeWhite = function (x, y) { if (x < row && y < col && x >= 0 && y >= 0) { var el = document.querySelector(`.x-${x}`).children[y] // ต้องใส่ตรง !== 'white' เพราะถ้าไม่เพิ่มมันจะเป็น infinite loop งงตรงนี้ลองเล่นให้ชนะ if (el.style.background !== 'white') { el.style.background = 'white' el.children[0].style.opacity = '1' el.children[1].classList.add('hide') clearMineNum++ // console.log(clearMineNum, 'clearMineNum'); changeClearMineNum(clearMineNum) if (el.innerText === '') { showNoMine(x, y) } } } } // เคลียค่า var showNoMine = function (x, y) { // console.log(x, y, 'x,y'); makeWhite(x - 1, y + 1) makeWhite(x - 1, y - 1) makeWhite(x - 1, y) makeWhite(x + 1, y + 1) makeWhite(x + 1, y - 1) makeWhite(x + 1, y) makeWhite(x, y + 1) makeWhite(x, y - 1) } // เชื่อม event click กับช่องทั้งหมดว่าช่องนั้นจะเป็นตัวเลขหรือระเบิด var show = function () { // var x = document.querySelectorAll('.col') var x = document.querySelectorAll('.row') for (var i = 0; i < x.length; i++) { x[i].addEventListener('click', function (event) { if (IsGameOver) return; var el = event.target if (el.tagName != 'LI') { // ถ้าคลิกจะเข้า span el = event.target.parentElement } // คลิกไม่ได้ถ้าคลิกflagแล้ว var flag = el.children[1].classList.contains('hide') if (el.tagName === 'LI' && flag) { if (IsGameOver) return; if (el.children[0].innerText !== '9' && el.style.background !== 'white') { el.children[0].style.opacity = '1' el.style.background = 'white' clearMineNum++ changeClearMineNum(clearMineNum) // console.log(clearMineNum, 'clearMineNum'); } else if (el.children[0].innerText === '9') { // el.children[0].style.opacity = '1' zz = 1 IsGameOver = true; el.classList.add('boom') alert('ตู้มต้าม! ลองเล่นใหม่อีกทีนะ~') var all = document.querySelectorAll('.col') var ff = [] var allNum = 0 // แอนิเมชั่นนิดหน่อยตอนโชว์ระเบิดทั้งหมด for (var i = 0; i < all.length; i++) { if (all[i].children[0].innerText === '9') { // all[i].style.background = 'red' ff[allNum] = all[i] allNum++ } } allNum = 0 var time = 60 if (num > 50) { time = 10 } else if (num > 10) { time = 25 } var stop = setInterval(function () { ff[allNum].classList.add('boom') allNum++ if (allNum === ff.length) { clearInterval(stop) // console.log('stop'); } }, time) // var box = document.querySelector('.gameBox') // box.innerHTML = '' // var level = event.target.innerHTML // var body = document.querySelector('body') // initializeGame(row, col, num) } // ถ้าคลิกช่องว่างๆที่ไม่มีอะไรกำหนดช่องข้างๆที่มีค่าเหมือนกันก็จะถูกเปิด if (el.children[0].innerText === '') { // รับตำแหน่ง var x = parseInt(el.parentElement.dataset.x) var y = parseInt(el.dataset.y) // console.log(x,y, 'data'); // เปลี่ยนเป็นสีขาว showNoMine(x, y) } } }) } for (var i = 0; i < x.length; i++) { var mineNum = num x[i].addEventListener('contextmenu', function (event) { event.preventDefault(); var btnNum = event.button var el = event.target if (el.tagName != 'LI') { el = event.target.parentElement } if (el.tagName === 'LI') { if (IsGameOver) return; var classList = el.children[1].classList // คลิกช่องที่คลิกแล้วไม่ได้ if (classList.contains('hide') && el.style.background !== 'white') { var residue = document.querySelector('.residue') if (mineNum !== 0) { mineNum-- } residue.innerText = `${mineNum}` classList.remove('hide') } else if (el.style.background !== 'white') { classList.add('hide') } } }) } } show() } // 4,ล้างตารางแล้วเขียนใหม่ var stopTime var initializeGame = function (row, col, num) { IsGameOver = false; var residue = document.querySelector('.residue') residue.innerText = `${num}` var time = document.querySelector('.tick') time.innerText = `0` var i = 1 clearInterval(stopTime) stopTime = setInterval(function () { time.innerText = `${i++}` }, 1000) // zz zz = 0 // ขั้นแรกล้างแผนที่เดิมจากนั้นเริ่มต้นใหม่ var box = document.querySelector('.gameBox') box.innerHTML = '' var body = document.querySelector('body') body.style.minWidth = `${27 * col}px` var map = mineSweepingMap(row, col, num) writeHtml(map) clearMine(row, col, num) } // 5,เลือกความยาก connect เข้า button var Btn = function () { var level = document.querySelectorAll('.choice-level') for (var i = 0; i < level.length; i++) { level[i].addEventListener('click', function (event) { var level = event.target.innerHTML if (level === 'ง่าย') { row = 9 col = 9 num = 10 initializeGame(row, col, num) } else if (level === 'ปานกลาง') { row = 16 col = 16 num = 40 initializeGame(row, col, num) } else if (level === 'ยาก') { row = 16 col = 30 num = 99 initializeGame(row, col, num) } }) } var restart = document.querySelector('.restart') restart.addEventListener('click', function (event) { initializeGame(row, col, num) }) } Btn() // 6,เริ่มเกม // zz ใช้ตรวจสอบช่อง var zz = 0 var row = 9 var col = 9 var num = 10 initializeGame(row, col, num) // ต้องทำเครื่องหมายทุ่นระเบิดทั้งหมดจนเหลือ array เพียง 9 array จบเกม </script> </body> </html>