亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

基于JavaScript如何編寫一個翻卡游戲

發布時間:2023-02-16 09:38:29 來源:億速云 閱讀:158 作者:iii 欄目:開發技術

這篇文章主要介紹“基于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 = 20
const icons = ['a', 'b', 'c', 'd', 'e']
// => 得到集合W
const 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中的每個元素都能出現相同的最多偶數次。可以這樣得到它:

  • icons個數x2,得到完整一次配對需要多少格子

  • 總格子數 / 一次完整格子數,得到可以完整配對的最大次數n

  • 循環n次,每次循環往W里添加icons x 2

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

剩下的是需要隨機分布的部分,它代表著,某幾個元素可以在這里出現2次,剩下的則不會出現。

  • 總格子數 % icons個數x2, 得到剩下未分配的格子

  • 未分配格子 / 2, 就是需要隨機從icons中取出的元素個數n,這個n一定小于icons的個數

  • 從icons中隨機取n個數,可以采用每取一個數,將該數從原集合刪除,重復n次的方法

  • 將得到的n個數x2,往W里添加

第(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如何編寫一個翻卡游戲”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

赤峰市| 建始县| 冷水江市| 陈巴尔虎旗| 页游| 耒阳市| 杂多县| 慈溪市| 平顶山市| 麻江县| 麟游县| 祁连县| 普安县| 隆子县| 济阳县| 和顺县| 庆阳市| 松滋市| 汉沽区| 芒康县| 博兴县| 英吉沙县| 资源县| 淮北市| 海晏县| 牡丹江市| 衡水市| 吉水县| 秀山| 青龙| 顺义区| 新蔡县| 东莞市| 吴川市| 巴青县| 和田市| 琼中| 敦煌市| 宣汉县| 大邑县| 来凤县|