吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2102|回复: 15
收起左侧

[其他转载] 【扫雷游戏】使用 javascript 编写的扫雷游戏

  [复制链接]
Fullmoonbaka 发表于 2021-7-28 17:36
本帖最后由 Fullmoonbaka 于 2021-7-28 21:31 编辑

如题所示,
本人使用javascript实现了一个扫雷游戏,基本涵盖了windows7扫雷的所有基本功能

扫雷

扫雷


游戏程序主要技术点:
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] 纯文本查看 复制代码
        class sweep{
            constructor(item) {
                this.item = document.querySelector(item)
                this.bombNum = 99   // 炸弹数量(默认)
                this.allBlock = []  // 全部地块DOM列表
                this.blockList = [] // 无炸弹地块列表
                this.bombList = []  // 有炸弹地块列表
                this.showList = []  // 揭开地块的列表
                this.blockObj = []  // 地块对象
                this.flagList = new Set()   // 旗子列表
                this.begin = false  // 开始
                this.timer = null   // 计时器

                this.init()
            }

            // 启动器
            init () {
                this.conTextMenu()
                this.createFloor()
                this.clickBlock()
            }

            // 生成地形
            createFloor () {
                let frg = document.createDocumentFragment()
                for(let j = 0; j < 450; j++){
                    let div = document.createElement('div')
                    this.blockList.push(j)
                    this.blockObj.push({
                        id: j,
                        x: j%30,
                        y: parseInt(j/30)
                    })
                    div.dataset.id = j
                    div.className = 'block'
                    this.allBlock.push(div)
                    frg.appendChild(div)
                }
                this.item.appendChild(frg)
            }

            // 生成炸弹
            createBomb (arr) {
                this.bombNum = parseInt(document.querySelector('#num').value)
                arr.forEach((item) => {
                    this.blockList.splice(this.blockList.indexOf(item), 1)
                })
                for(let i = 0; i < this.bombNum; i++){
                    this.bombList.push(this.blockList.splice(parseInt(Math.random() * this.blockList.length), 1)[0])
                }
                arr.forEach((item) => {
                    this.blockList.push(item)
                })
            }

            // 点击事件
            clickBlock () {
                // 单击
                this.item.addEventListener('click', (e) => {
                    e = e || window.event
                    let target = e.target || e.srcElement
                    if(!this.begin){
                        this.begin = true
                        this.setTime()
                        let arr = this.getBlock(target.dataset.id - 0)
                        arr.push(target.dataset.id - 0)
                        this.createBomb(arr)
                    }
                    if(target.className === 'block'){
                        this.show(target)
                        if(!this.blockList.some((item) => {return this.allBlock[item].className !== 'show'})){
                            this.victory() 
                            return
                        }
                    }
                })

                // 选中事件
                this.item.addEventListener('selectstart', (e) => {
                    e = e || window.event
                    e.preventDefault()
                })

                // 双击事件
                this.item.addEventListener('dblclick', (e) => {
                    e = e || window.event
                    let target = e.target || e.srcElement
                    if(target.className === 'show'){
                        let num = target.dataset.id - 0
                        let arr = this.getBlock(num)
                        if(arr.some((item) => { return this.bombList.indexOf(item) !== -1 && this.allBlock[item].className !== 'bomb' })){
                            if(target.innerText - 0 && arr.filter((item) => { return this.allBlock[item].className === 'bomb'}).length === target.innerText - 0){
                                this.fail()
                            }
                        } else {
                            arr.forEach((item) => {
                                if(this.allBlock[item].className === 'block'){
                                    this.show(this.allBlock[item])
                                }
                            })
                            if(this.showList.length === this.blockList.length) {
                                this.victory()
                            }
                        }
                    }
                })
            }

            // 判断方块四周
            show (item) {
                let sum = 0
                let num = parseInt(item.dataset.id)
                if(this.bombList.some((i) => { return i === parseInt(item.dataset.id) })){
                    this.fail()
                } else {
                    this.showList.push(parseInt(item.dataset.id))
                    let arr = this.getBlock(num)
                    arr.forEach((one) => {
                        if(this.bombList.some((i) => {return i === one})){
                            sum ++
                        }
                    })
                    item.className = 'show'
                    if(sum){
                        item.innerText = sum
                    } else {    // 追加 show
                        arr.forEach((num) => {
                            if(this.allBlock[num].className === 'block'){
                                this.show(this.allBlock[num])
                            }
                        })
                    }
                }
            }

            // 获取到四周的方块
            getBlock(num) {
                let arr = []
                if(num === 0){
                    arr = [num + 1, num + 30, num + 31]
                } else if (num === 29){
                    arr = [num - 1, num + 30, num + 29]
                } else if (num === 420){
                    arr = [num + 1, num - 30, num - 29]
                } else if (num === 449){
                    arr = [num - 1, num - 30, num - 31]
                } else if (num < 29){
                    arr = [num + 1, num - 1, num + 30, num + 31, num + 29]
                } else if (num > 420){
                    arr = [num + 1, num - 1, num - 30, num - 29, num - 31]
                } else if (num % 30 === 0){
                    arr = [num + 1, num - 30, num - 29, num + 30, num + 31]
                } else if (num % 30 === 29){
                    arr = [num - 1, num - 30, num - 31, num + 30, num + 29]
                } else {
                    arr = [num + 1, num - 1, num + 29, num + 30, num + 31, num - 30, num - 31, num - 29]
                }
                return arr
            }

            // 计时器
            setTime(){
                let t = document.getElementById('time')
                let s = t.innerText - 0
                this.timer = setInterval(() => {
                    s ++
                    t.innerText = s
                }, 1000)
            }

            // 失败
            fail (){
                let bool = confirm('踩到雷,失败了!')
                if(bool){
                    window.location.reload()
                }
            }

            // 成功
            victory (){
                alert('成功了!成功了!带成功!')
                clearInterval(this.timer)
                alert('你的生命减少了 ' + document.querySelector('#time').innerText + ' 秒')
            }

            // 右键事件
            conTextMenu () {
                this.item.addEventListener('contextmenu', (e) => {
                    e = e || window.event
                    let target = e.target || e.srcElement
                    try {e.preventDefault()} catch (err) {e.returnValue = false}
                    if(target.className === 'block'){
                        target.className = 'bomb'
                        this.flagList.add(parseInt(target.dataset.id))
                    } else if (target.className === 'bomb'){
                        target.className = 'block'
                        this.flagList.delete(parseInt(target.dataset.id))
                    }
                    if(this.flagList.size === this.bombNum) {
                        let flagAllBomb = this.bombList.every(item => {
                            return this.flagList.has(item)
                        })
                        if(flagAllBomb) {
                            this.victory()
                        }
                    }
                })
            }
        }

        let first = new sweep('#box')

免费评分

参与人数 7吾爱币 +7 热心值 +6 收起 理由
wwxwang + 1 + 1 好兄弟,我拿你代码学习学习
wwaaffll + 1 我很赞同!
lxc666debug + 1 + 1 太厉害了!
y_w_o + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
寻找乐趣 + 1 + 1 我很赞同!
laughtosky0 + 1 + 1 谢谢@Thanks!
blindcat + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Fullmoonbaka 发表于 2021-7-28 21:28
luliucheng 发表于 2021-7-28 21:14
这怎么运行呀?贴到Html里没有用呀?

还需要dom结构和css样式呢,https://www.52pojie.cn/thread-1484299-1-1.html 看这个
 楼主| Fullmoonbaka 发表于 2021-7-28 18:38
976431852qwe 发表于 2021-7-28 18:19
大佬好强,我想问一下你大概学了多久啊?我想知道学多久可以达到这种程度

我学了快一年,全心全力的学的话,三个月足以。这个是我好久之前写的,今天想起来就分享到论坛上
blindcat 发表于 2021-7-28 18:22
xhy13721357088 发表于 2021-7-28 18:31
大佬就是强,拜服了
rescal 发表于 2021-7-28 19:25
大佬牛啊
Sunshine0804 发表于 2021-7-28 19:43
66666666666666666666666666666666666
baiqpl0123 发表于 2021-7-28 19:46
扫雷有什么方法吗
Brillant 发表于 2021-7-28 19:55
学习一下
ytlk0535 发表于 2021-7-28 20:21
计算这个雷的数量是比较费脑的
bqcar168 发表于 2021-7-28 20:30
可以边工作边玩游戏
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-5 03:15

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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