学生黑客联盟-官网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 237|回复: 10

【扫雷游戏】使用 javascript 编写的扫雷游戏

[复制链接]
  • TA的每日心情
    开心
    2019-7-20 17:38
  • 2

    主题

    2

    帖子

    22

    积分

    新手上路

    Rank: 1

    积分
    22
    发表于 2021-9-14 20:06:02 | 显示全部楼层 |阅读模式
    如题所示,
    本人使用javascript实现了一个扫雷游戏,基本涵盖了windows7扫雷的所有基本功能
    扫雷
    TBC新兵交流-如题所示,本人使用javascript实现了一个扫雷游戏,基本涵盖了windows7扫雷的所有基本功能扫雷(1)

    游戏程序主要技术点:
    1.【生成炸弹】[createBomb方法]
    在第一次点击地板的时候,需要确保点击的地方不是炸弹(防止第一次点击就输),因此炸弹生成在第一次点击之后。
    在第一次点击时先获取到点击落点周围9格的id,
    在所有地板id的列表中排除这些id,
    然后在剩下的id中随机抽取一定量的地板id生成炸弹
    2.【揭开地板】[show方法](个人觉得是扫雷的核心规则)
    在揭开地板时先判断是否为炸弹,为炸弹就直接判输
    如果不为炸弹,获取落点地板周围9格的地板id逐个判断是否为炸弹,
    如果有炸弹就将落点地板标上炸弹数且就此结束
    如果没有炸弹就递归遍历落点地板周围一圈8个地板重复执行此操作
    (此操作会形成一揭一大片的情况,当周围的8个地板都没有炸弹时一直往外扩散遍历,直至检测到炸弹以后将地板填入数字后停止。)
    这一步要注意将地板的状态及时更新成揭开状态,不然会无限递归导致卡死
    3.【双击地板】
    双击地板操作需要双击已经揭开、带有数字并且附近插有旗子的地板才有效。
    当落点周围8格有雷且插上旗子数等于雷的数量的时候,会自动揭开其他格子。(据我多年扫雷经验,此规则应该和win7版扫雷的左键+右键功能一致)
    如果插旗错误(对应的旗子没有插在雷上而是插在安全格子上)会直接失败,如果插旗每个都插在雷上,会自动揭开周围8格其他所有未揭开且未插旗的格子。
    本操作规则遵守揭开地板规则,遇到空地板时候会递归揭开周围的格子。

    想要运行的可以看这个
    https://www.52pojie.cn/thread-1484299-1-1.html
    本人编程时间尚短、技术力有限,本文章有错误望大佬一一指正。


    [JavaScript]  
    1. class sweep{
    2.             constructor(item) {
    3.                 this.item = document.querySelector(item)
    4.                 this.bombNum = 99   // 炸弹数量(默认)
    5.                 this.allBlock = []  // 全部地块DOM列表
    6.                 this.blockList = [] // 无炸弹地块列表
    7.                 this.bombList = []  // 有炸弹地块列表
    8.                 this.showList = []  // 揭开地块的列表
    9.                 this.blockObj = []  // 地块对象
    10.                 this.flagList = new Set()   // 旗子列表
    11.                 this.begin = false  // 开始
    12.                 this.timer = null   // 计时器
    13.                 this.init()
    14.             }
    15.             // 启动器
    16.             init () {
    17.                 this.conTextMenu()
    18.                 this.createFloor()
    19.                 this.clickBlock()
    20.             }
    21.             // 生成地形
    22.             createFloor () {
    23.                 let frg = document.createDocumentFragment()
    24.                 for(let j = 0; j < 450; j++){
    25.                     let div = document.createElement('div')
    26.                     this.blockList.push(j)
    27.                     this.blockObj.push({
    28.                         id: j,
    29.                         x: j%30,
    30.                         y: parseInt(j/30)
    31.                     })
    32.                     div.dataset.id = j
    33.                     div.className = 'block'
    34.                     this.allBlock.push(div)
    35.                     frg.appendChild(div)
    36.                 }
    37.                 this.item.appendChild(frg)
    38.             }
    39.             // 生成炸弹
    40.             createBomb (arr) {
    41.                 this.bombNum = parseInt(document.querySelector('#num').value)
    42.                 arr.forEach((item) => {
    43.                     this.blockList.splice(this.blockList.indexOf(item), 1)
    44.                 })
    45.                 for(let i = 0; i < this.bombNum; i++){
    46.                     this.bombList.push(this.blockList.splice(parseInt(Math.random() * this.blockList.length), 1)[0])
    47.                 }
    48.                 arr.forEach((item) => {
    49.                     this.blockList.push(item)
    50.                 })
    51.             }
    52.             // 点击事件
    53.             clickBlock () {
    54.                 // 单击
    55.                 this.item.addEventListener('click', (e) => {
    56.                     e = e || window.event
    57.                     let target = e.target || e.srcElement
    58.                     if(!this.begin){
    59.                         this.begin = true
    60.                         this.setTime()
    61.                         let arr = this.getBlock(target.dataset.id - 0)
    62.                         arr.push(target.dataset.id - 0)
    63.                         this.createBomb(arr)
    64.                     }
    65.                     if(target.className === 'block'){
    66.                         this.show(target)
    67.                         if(!this.blockList.some((item) => {return this.allBlock[item].className !== 'show'})){
    68.                             this.victory()
    69.                             return
    70.                         }
    71.                     }
    72.                 })
    73.                 // 选中事件
    74.                 this.item.addEventListener('selectstart', (e) => {
    75.                     e = e || window.event
    76.                     e.preventDefault()
    77.                 })
    78.                 // 双击事件
    79.                 this.item.addEventListener('dblclick', (e) => {
    80.                     e = e || window.event
    81.                     let target = e.target || e.srcElement
    82.                     if(target.className === 'show'){
    83.                         let num = target.dataset.id - 0
    84.                         let arr = this.getBlock(num)
    85.                         if(arr.some((item) => { return this.bombList.indexOf(item) !== -1 && this.allBlock[item].className !== 'bomb' })){
    86.                             if(target.innerText - 0 && arr.filter((item) => { return this.allBlock[item].className === 'bomb'}).length === target.innerText - 0){
    87.                                 this.fail()
    88.                             }
    89.                         } else {
    90.                             arr.forEach((item) => {
    91.                                 if(this.allBlock[item].className === 'block'){
    92.                                     this.show(this.allBlock[item])
    93.                                 }
    94.                             })
    95.                             if(this.showList.length === this.blockList.length) {
    96.                                 this.victory()
    97.                             }
    98.                         }
    99.                     }
    100.                 })
    101.             }
    102.             // 判断方块四周
    103.             show (item) {
    104.                 let sum = 0
    105.                 let num = parseInt(item.dataset.id)
    106.                 if(this.bombList.some((i) => { return i === parseInt(item.dataset.id) })){
    107.                     this.fail()
    108.                 } else {
    109.                     this.showList.push(parseInt(item.dataset.id))
    110.                     let arr = this.getBlock(num)
    111.                     arr.forEach((one) => {
    112.                         if(this.bombList.some((i) => {return i === one})){
    113.                             sum ++
    114.                         }
    115.                     })
    116.                     item.className = 'show'
    117.                     if(sum){
    118.                         item.innerText = sum
    119.                     } else {    // 追加 show
    120.                         arr.forEach((num) => {
    121.                             if(this.allBlock[num].className === 'block'){
    122.                                 this.show(this.allBlock[num])
    123.                             }
    124.                         })
    125.                     }
    126.                 }
    127.             }
    128.             // 获取到四周的方块
    129.             getBlock(num) {
    130.                 let arr = []
    131.                 if(num === 0){
    132.                     arr = [num + 1, num + 30, num + 31]
    133.                 } else if (num === 29){
    134.                     arr = [num - 1, num + 30, num + 29]
    135.                 } else if (num === 420){
    136.                     arr = [num + 1, num - 30, num - 29]
    137.                 } else if (num === 449){
    138.                     arr = [num - 1, num - 30, num - 31]
    139.                 } else if (num < 29){
    140.                     arr = [num + 1, num - 1, num + 30, num + 31, num + 29]
    141.                 } else if (num > 420){
    142.                     arr = [num + 1, num - 1, num - 30, num - 29, num - 31]
    143.                 } else if (num % 30 === 0){
    144.                     arr = [num + 1, num - 30, num - 29, num + 30, num + 31]
    145.                 } else if (num % 30 === 29){
    146.                     arr = [num - 1, num - 30, num - 31, num + 30, num + 29]
    147.                 } else {
    148.                     arr = [num + 1, num - 1, num + 29, num + 30, num + 31, num - 30, num - 31, num - 29]
    149.                 }
    150.                 return arr
    151.             }
    152.             // 计时器
    153.             setTime(){
    154.                 let t = document.getElementById('time')
    155.                 let s = t.innerText - 0
    156.                 this.timer = setInterval(() => {
    157.                     s ++
    158.                     t.innerText = s
    159.                 }, 1000)
    160.             }
    161.             // 失败
    162.             fail (){
    163.                 let bool = confirm('踩到雷,失败了!')
    164.                 if(bool){
    165.                     window.location.reload()
    166.                 }
    167.             }
    168.             // 成功
    169.             victory (){
    170.                 alert('成功了!成功了!带成功!')
    171.                 clearInterval(this.timer)
    172.                 alert('你的生命减少了 ' + document.querySelector('#time').innerText + ' 秒')
    173.             }
    174.             // 右键事件
    175.             conTextMenu () {
    176.                 this.item.addEventListener('contextmenu', (e) => {
    177.                     e = e || window.event
    178.                     let target = e.target || e.srcElement
    179.                     try {e.preventDefault()} catch (err) {e.returnValue = false}
    180.                     if(target.className === 'block'){
    181.                         target.className = 'bomb'
    182.                         this.flagList.add(parseInt(target.dataset.id))
    183.                     } else if (target.className === 'bomb'){
    184.                         target.className = 'block'
    185.                         this.flagList.delete(parseInt(target.dataset.id))
    186.                     }
    187.                     if(this.flagList.size === this.bombNum) {
    188.                         let flagAllBomb = this.bombList.every(item => {
    189.                             return this.flagList.has(item)
    190.                         })
    191.                         if(flagAllBomb) {
    192.                             this.victory()
    193.                         }
    194.                     }
    195.                 })
    196.             }
    197.         }
    198.         let first = new sweep('#box')
    复制代码

    该用户从未签到

    3

    主题

    1614

    帖子

    893

    积分

    高级会员

    Rank: 4

    积分
    893
    发表于 2021-9-14 20:06:58 | 显示全部楼层
    还需要dom结构和css样式呢,https://www.52pojie.cn/thread-1484299-1-1.html 看这个
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1679

    帖子

    2

    积分

    新手上路

    Rank: 1

    积分
    2
    发表于 2021-9-14 20:07:23 | 显示全部楼层
    我学了快一年,全心全力的学的话,三个月足以。这个是我好久之前写的,今天想起来就分享到论坛上
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    1571

    帖子

    1045

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1045
    发表于 2021-9-14 20:07:30 | 显示全部楼层
    大佬好强,我想问一下你大概学了多久啊?我想知道学多久可以达到这种程度
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    1571

    帖子

    1045

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1045
    发表于 2021-9-14 20:08:06 | 显示全部楼层
    挺厉害的,学习下
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    1571

    帖子

    1045

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1045
    发表于 2021-9-14 20:08:38 | 显示全部楼层
    大佬就是强,拜服了
    回复

    使用道具 举报

    该用户从未签到

    3

    主题

    1614

    帖子

    893

    积分

    高级会员

    Rank: 4

    积分
    893
    发表于 2021-9-14 20:08:50 | 显示全部楼层
    大佬牛啊
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    1571

    帖子

    1045

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1045
    发表于 2021-9-14 20:09:14 | 显示全部楼层
    66666666666666666666666666666666666
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1679

    帖子

    2

    积分

    新手上路

    Rank: 1

    积分
    2
    发表于 2021-9-14 20:09:27 | 显示全部楼层
    扫雷有什么方法吗
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1679

    帖子

    2

    积分

    新手上路

    Rank: 1

    积分
    2
    发表于 2021-9-14 20:10:11 | 显示全部楼层
    学习一下
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭Powered by ©科大讯飞语音云

    QQ|Archiver|手机版|小黑屋|TBC ( 鄂ICP备19004742号(鄂ICP备19004742号-2) )|网站地图|鄂ICP备19004742号(鄂ICP备19004742号-2) 联系站长

    GMT+8, 2021-9-23 13:11 , Processed in 0.921875 second(s), 38 queries .

    Powered by TBC! X3.4

    © 2001-2020 TBC.. 技术支持 by 复仇者黑客组织

    快速回复 返回顶部 返回列表