文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

基于JavaScript如何编写一个翻卡游戏

2023-07-05 04:07

关注

这篇文章主要介绍“基于JavaScript如何编写一个翻卡游戏”,在日常操作中,相信很多人在基于JavaScript如何编写一个翻卡游戏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”基于JavaScript如何编写一个翻卡游戏”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

翻卡动画

假如我们的盒子模型不是个二维的平面,而是有个三维的体积,让它可以有正反两面,那我们在做的时候是不是只要将它真实的翻个面就可以了。让我们来想想将它变成三维的方法。 之后发现了这个属性:

transform: translateZ(1px);

使用了它,就可以把盒子内部的元素与盒子的底部撑出个高度。

<!-- html --> <div class="card">    <div class="top">我是正面哦~</div></div>

只用给叫做“top”的子盒子一个“距离父亲的距离”,再将叫做“card”的父盒子预先翻转180度rotateY(180deg),等到点击的时候给它翻回来transform: rotateY(0)就可以了。

.card{  ...  height: 100%;  width: 100%;  position: relative;  transform-style: preserve-3d;  transform: rotateY(180deg);  transition: all 600ms;  background: pink;  &.select {    transform: rotateY(0);  }  .top{    ...    height: 100%;    width: 100%;    position: absolute;    top: 0;    left: 0;    box-sizing: border-box;    background: white;    border: 2px solid #b6a6dc;    transform: translateZ(1px);  }}

生成随机分布数组

我们先来说下在理想环境中,每个元素都能匀均出现(次数相等)的情况。再来说下不能均匀出现的情况下,怎样最大限度的均匀。

均匀元素下的随机算法

此算法脑内模型由西塔(&theta;)先生友情提供

假设我们一共需要20个元素,有5个不同类型的格子,正好每个格子出现4次。我们就有了一个待分配元素的集合W:

const total = 20const icons = ['a', 'b', 'c', 'd', 'e']// => 得到集合Wconst W = ['a', 'a', 'a', 'a',           'b', 'b', 'b', 'b',           'c', 'c', 'c', 'c',           'd', 'd', 'd', 'd',           'e', 'e', 'e', 'e']

混淆集合

有个指针p从下标0开始,在长度为20的数组格子里面负责填图案,填图案的规律是从集合w中随机取一个元素,取完后删除该元素,p移动到下一个格子里,迭代至完成。

function createRandomList(W: string[], total: number) {    const list: any[] = []    function it(time: number): any {        if (time === 0) return list        // 随机每次集合元素下标        const randomNum = Math.floor(Math.random() * (W.length))        list.push(W[randomNum]) // 新数组中加入随机到的元素        W.splice(randomNum, 1) // 删除集合中的元素        return it(--time)    }    return it(total)}

我们再让这个方法灵活一点,使它的返回结果能够随便指定格式:

// fn非必传项,默认返回原数据function createRandomList(W: string[], total: number, fn: (<T>(icon: string, index?: number) => T) = icon => icon) {    const list: any[] = []    // 迭代器    function it(time: number): any {        if (time === 0) return list        // 随机每次集合元素下标        const randomNum = Math.floor(Math.random() * (W.length))        list.push(fn(W[randomNum], total-time)) // 将元素和下标传入fn中,将fn的计算结果加入到新数组中        W.splice(randomNum, 1) // 删除集合中的元素        return it(--time)    }    return it(total)}

不均匀元素下的随机算法

const W = []

不均匀元素,其实就是集合W里的元素分布规则改变了,混淆算法仍然不受影响。之后,让我们来思考下怎么定义一个“不均匀中的最大程度均匀”的集合。 将集合W分为两个部分: 最大可均匀分布部分 + 随机部分

最大可均匀分布的部分,它代表着icons中的每个元素都能出现相同的最多偶数次。可以这样得到它:

// 得到最大重复次数const times = Math.floor(total / (icons.length * 2))for (let index = 0; index < times; index++)    W.push(...icons, ...icons)

剩下的是需要随机分布的部分,它代表着,某几个元素可以在这里出现2次,剩下的则不会出现。

第(3)条是不是听起来很耳熟,好像前面做过,没错就是前面写的createRandomList函数,W集合变成了icons,total变成了需要的个数n。

// 剩下未分配的格子个数const lastCount = total % (icons.length * 2)// 从icons中随机获取n个数const lastList = createRandomList(icons, lastCount / 2)W.push(...lastList, ...lastList)

合在一起就是就是创建W的方法:

function createW(icons: string[], total: number) {    const times = Math.floor(total / (icons.length * 2))    const lastCount = total % (icons.length * 2)    const W = []    for (let index = 0; index < times; index++)        W.push(...icons, ...icons)    const lastList = createRandomList(icons, lastCount / 2)    W.push(...lastList, ...lastList)    return W}

生成最终数组

完整的生成随机数组代码:

function createW(icons: string[], total: number) {    const times = Math.floor(total / (icons.length * 2))    const lastCount = total % (icons.length * 2)    const W = []    for (let index = 0; index < times; index++)        W.push(...icons, ...icons)    const lastList = createRandomList(icons, lastCount / 2)    W.push(...lastList, ...lastList)    return W}function createRandomList(W: string[], total: number, fn: (<T>(icon: string, index?: number) => T) = icon => icon) {    const list: any[] = []    function it(time: number): any {        if (time === 0) return list        const randomNum = Math.floor(Math.random() * (W.length))        list.push(fn(W[randomNum], total-time))        W.splice(randomNum, 1)        return it(--time)    }    return it(total)}// ['a', 'b', 'c', "d"] => ['c', 'd'...x15...'b', 'c', 'a']createRandomList(createW(icons, total), total)

点击事件

乱序的随机数组有了,点一点还不简单吗! 先让生成的数组属性更丰富一些,来帮助我们展示内容。

type CardItem = { icon: string; isDel: boolean; isSelect: boolean, index: number }let list: CardItem[] = []// isSelect属性判断是否翻转,isDel属性判断是否已经消除,icon属性标注元素属性,index用来快速找到点击元素位于数组中的位置list = createRandomList(createW(icons, total), total, (icon: string, index) => ({ icon, isDel: false, isSelect: false, index }))

这下可以用生成的数组去展示了。接下来我们写个点击事件,接收参数是点击的数组元素:

// isLock用来锁定动画完成前不能进行别的操作function handlerTap(card: CardItem) {    if (isLock) return    list[card.index].isSelect = true    const selectors = list.filter(item => item.isSelect && !item.isDel)    // 假如选择元素<2,直接返回,不走之后流程    if (selectors.length <= 1) return    isLock = true    const [item1, item2] = selectors    // 翻转动画完成后进行操作    setTimeout(() => {        // 如果选择的元素相同,则消除属性等于true        if (item1.icon === item2.icon) {            list[item1.index].isDel = true            list[item2.index].isDel = true        }        //将所有卡牌翻转过背面        list = list.map(item => ({...item, isSelect: false}))        isLock = false        // 判断是否所有卡牌都已经翻转完成        if (list.every(item => item.isDel)) console.log( "your win!")    }, 800)}

完整代码

100行整)。

<script lang="ts">    type CardItem = { icon: string; isDel: boolean; isSelect: boolean, index: number }    const icons = ['a', 'b', 'c', "d"]    const total = 20    let list: CardItem[] = []    let isLock = false    function handlerTap(card: CardItem) {        if (isLock) return        list[card.index].isSelect = true        const selectors = list.filter(item => item.isSelect && !item.isDel)        if (selectors.length <= 1) return        isLock = true        const [item1, item2] = selectors        setTimeout(() => {            if (item1.icon === item2.icon) {                list[item1.index].isDel = true                list[item2.index].isDel = true            }            list = list.map(item => ({...item, isSelect: false}))            isLock = false            if (list.every(item => item.isDel)) console.log( "your win!")        }, 800)    }    function createW(icons: string[], total: number) {        const times = Math.floor(total / (icons.length * 2))        const lastCount = total % (icons.length * 2)        const W = []        for (let index = 0; index < times; index++)            W.push(...icons, ...icons)        const lastList = createRandomList(icons, lastCount / 2)        W.push(...lastList, ...lastList)        return W    }    function createRandomList(W: string[], total: number, fn: (<T>(icon: string, index?: number) => T) = icon => icon) {        const list: any[] = []        function it(time: number): any {            if (time === 0) return list            const randomNum = Math.floor(Math.random() * (W.length))            list.push(fn(W[randomNum], total-time))            W.splice(randomNum, 1)            return it(--time)        }        return it(total)    }    list = createRandomList(createW(icons, total),            total,            (icon: string, index) => ({ icon, isDel: false, isSelect: false, index }))</script><div class="game-box">    {#each list as item}        <div class="grid">            {#if !item.isDel}                <div class="card {item.isSelect && 'select'}" on:click="{() => handlerTap(item)}">                    <div class="top">{item.icon}</div>                </div>            {/if}        </div>    {/each}</div><style lang="less">    .game-box{      margin: 10px auto 0;      width: 90vw;      height: 80vh;      display: grid;      grid-template-columns: repeat(4, calc(100% / 4 - 3px));      grid-template-rows: repeat(5, calc(100% / 5 - 3px));      grid-row-gap:3px;      grid-column-gap: 3px;      .card{        height: 100%;        width: 100%;        box-sizing: border-box;        position: relative;        transform-style: preserve-3d;        transform: rotateY(180deg);        transition: all 600ms;        background: pink;        &.select {          transform: rotateY(0);        }        .top{          height: 100%;          width: 100%;          position: absolute;          top: 0;          left: 0;          box-sizing: border-box;          display: flex;          justify-content: center;          align-items: center;          background: white;          border: 2px solid #b6a6dc;          transform: translateZ(1px);        }      }    }</style>

到此,关于“基于JavaScript如何编写一个翻卡游戏”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯