<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
首先將這個遊戲需求拆分成三個部分:
假如我們的盒子模型不是個二維的平面,而是有個三維的體積,讓它可以有正反兩面,那我們在做的時候是不是隻要將它真實的翻個面就可以了。讓我們來想想將它變成三維的方法。 之後發現了這個屬性:
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); } }
我們先來說下在理想環境中,每個元素都能勻均出現(次數相等)的情況。再來說下不能均勻出現的情況下,怎樣最大限度的均勻。
此演演算法腦內模型由西塔(θ)先生友情提供
假設我們一共需要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中的每個元素都能出現相同的最多偶數次。可以這樣得到它:
// 得到最大重複次數 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編寫一個翻卡遊戲的詳細內容,更多關於JavaScript翻卡遊戲的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45