Day20 實作結算牌堆元件(四) 實作移入7牌堆的拖曳&遊戲重置
前言 今天會先實作結算牌堆的牌要可以拖曳至7牌堆, 另外因為每次要重新開始都要切換頁面或按F5重新整理也會實作一個重置遊戲的按鈕 拖曳結算牌堆的牌 至 7牌堆 原本以為會花點時間想怎麼做,但實際上思考、實作都沒花多少時間就完成。 因為結算牌堆拖曳的牌一次只會拖曳一張,且拖曳到7牌堆的過程判斷基本上抄之前7牌堆自己的拖曳判斷方法就差不多完成,只多了一個先判斷拖曳的目標牌堆是否為七牌堆,甚至不用像其他牌堆拖曳:move還要額外去寫『拖曳成功後要觸發修改陣列』的函數changeOption.vlaue。 以下是對應結算牌堆<FinishedArea >內元件的屬性:move實作程式碼: // DragDemo.vue /** 結算牌堆移動 */ function finishedCardMove(evt) { const to = getDomName(evt.to); const { futureIndex, element } = evt.draggedContext; let result = validNames.includes(to); // 只能移動至目標牌堆的最後一張牌 result = result && futureIndex == cardStacks[to].length; // 檢查疊牌順序、花色是否正確 result = result && checkNextOk(cardStacks[to], element); return result; } 調整樣板<FinishedArea >的屬性:moveCard="finishedCardMove"即可套用上方的函數。 <!-- DragDemo.vue --> <div class="text">結算牌堆</div> <FinishedArea :fourCards="cardStacks" :moveCard="finishedCardMove" @doms="setFourCardDoms" :change="cardChange" /> 實作重置遊戲的按鈕 因為遊戲初始化就是寫在onMounted但重設的部分不夠完整,至少並沒有考慮到結算牌堆的部分,舊版初始化程式碼如下: onMounted(() => { const data = geneateShuffleDeck(52); const everyIndex = [0, 1, 3, 6, 10, 15, 21, 28]; validNames.forEach((name, idx) => { cardStacks[name] = data.slice(everyIndex[idx], everyIndex[idx + 1]); }); cardStacks.dealerStacks = data.slice(28).map(card => ({ ...card, isOpen: true })); }); 所以乾脆將初始化遊戲寫成函數resetGame(),這樣點擊重置按鈕、渲染元件onMounted時都可以呼叫同個函數。 // DragDemo.vue onMounted(() => { resetGame(); }); 意外發現發牌區<DealerArea>開牌到第幾張的狀態是包在元件內不利於初始化,決定先將狀態提升父元件的程式碼中DragDemo.vue,將開牌到第幾張的索引改用props方式傳入通知元件<DealerArea>要更新索引。 // DragDemo.vue <script setup> let dealer = reactive({ index: 0 }); </script> <template> <div class="text">發牌區</div> <DealerArea :dealer="dealer" :deck="cardStacks.dealerStacks" :moveCard="dealerMove" /> </template> 為了讓<DealerArea>取得發牌索引的變化,在definProps新增屬性dealer對應一個reactive物件,當物件dealer參考變動時則發牌區的索引index會被設值 【變動後dealer的index】,參考下方程式碼: ...