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....

September 29, 2023 · 2 min · 宗嘉

Day 19 實作結算牌堆元件(三)整合至接龍頁面

前言 今天會實作發牌區、7牌堆的牌可以拖曳到結算牌堆,且拖曳的過程需遵守結算牌堆的同色疊牌由A至K的規則。 整理重複的函數 先將昨天在DealerAreaView.vue撰寫的程式碼移動到拖曳練習的頁面DragDemo.vue。 樣板的部分是沒什麼問題,只是發現有太多函數宣告出現在DragDemo.vue,所以將常數FOUR_SUITS和判斷結算牌堆規則的checkNextOk2函數先移入工具目錄utils/內的程式碼,DragDemo.vue改用import的方式載入通用的常數、函數。 // DragDemo.vue import { FOUR_SUITS } from '../utils/constants'; import { geneateShuffleDeck, checkNextOk, checkNextOk2 } from "../utils/poker-helper"; 設定結算牌堆用的資料 在原本的cardStack中添加針對結算牌堆四花色的撲克牌陣列 // DragDemo.vue const cardStacks = reactive({ // 略... /** @type {Card[]} */ club: [], /** @type {Card[]} */ diamond: [], /** @type {Card[]} */ heart: [], /** @type {Card[]} */ spade: [] }); 因為<FinishedArea />的屬性:fourCard只有要求傳入的物件需要有對應花色名稱的KEY就可以,沒有硬性要求不能有其他屬性, 所以樣板的傳值我就簡單設定cardStacks傳入,如下程式碼: <!-- DragDemo.vue --> <div> <div class="text">發牌區</div> <DealerArea :deck="cardStacks.dealerStacks" :moveCard="dealerMove" /> <div class="text">結算牌堆</div> <FinishedArea :fourCards="cardStacks" @doms="setFourCardDoms" :change="cardChange" /> </div> 在DragDemo....

September 28, 2023 · 2 min · 宗嘉

Day 18 實作結算牌堆元件(二) 整合拖曳相容不同規則

前言 昨天完成結算牌堆樣版的部分,今天接著處理整合拖曳到接龍之前的步驟, 先調整結算牌堆的內部結構、方法。 調整結算牌堆 FinishedArea 先調整結算牌堆<FinishedArea />內部需要的props結構,就底下這三種: props.fourCards對應四個牌堆的陣列 props.moveCard對應<draggable>元件的屬性:move判斷是否可以拖曳成功的函數 props.change對應<draggable>內的列表更新時觸發的函數(這部分等等再說明) 程式碼如下: // FinishedArea.vue const props = defineProps({ fourCards: { type: Object, required: true, validator: (value) => { return ( value.hasOwnProperty('club') && value.hasOwnProperty('diamond') && value.hasOwnProperty('heart') && value.hasOwnProperty('spade') ); }, }, moveCard: { type: Function, default: () => { return false; } }, change: { type: Function, default: () => { return false; } } }) 然後結算牌堆就像發牌區一樣,卡牌陣列都是由外部props傳入且props的陣列內容都會變動, 所以也需要watch監控props.fourCards變化調整元件內的fourCards內的值。 // FinishedArea.vue const fourCards = ref({ club: [], diamond: [], heart: [], spade: [], }); watch(props....

September 27, 2023 · 2 min · 宗嘉

Day 17 實作結算牌堆元件(一)樣板&資料結構

前言 今日要製作結算牌堆,跟中間的7疊牌不同,結算牌堆只有4堆且只能允許同花色疊在上面,必須由小到大(A->K)放上去,放上去的牌會擋住底下的牌。 修正發牌區拖曳Bug 在開發今日功能前,測試遊玩發牌區到中間七牌堆發現能任意插到七牌堆的中間, 在函數dealerMove中補上evt.draggedContext.futureIndex == cardStacks[to].length的判斷後才正常,以下是修正後的程式碼: /** 發牌區移動 */ function dealerMove(evt) { const to = getDomName(evt.to); const dealerCard = evt.draggedContext.element; // 只能移動至目標牌堆的最後一張牌 let result = futureIndex == cardStacks[to].length; // 檢查疊牌順序、花色是否正確 result = result && checkNextOk(cardStacks[to], dealerCard); if (result) { changeOption.value = () => { cardStacks.dealerStacks = cardStacks.dealerStacks.filter(card => card.value !== dealerCard.value); changeOption.value = null; }; } return result; } 製作結算牌堆樣板 看一下草稿圖,接著想像畫面應該會有四個長方塊並排,四個長方都有個底圖對應花色, 底圖上方都可以擺一張牌。 跟製作發牌區<DealerArea>相同,打算先做出元件<FinishedArea>在整合進原本的接龍區塊, 以下是目前的樣板程式碼: // FinishedArea.vue <template> <div style="display: flex;"> <div class="card club"></div> <div class="card diamond"></div> <div class="card heart"></div> <div class="card spade"></div> </div> </template> 補上拖曳的樣板前,這部分會需要考慮四個牌堆的資料, 所以資料結構就設計成四個花色各自對應1個Card陣列的狀態...

September 26, 2023 · 2 min · 宗嘉

Day16 接龍發牌區功能實作(三)拖曳與疊牌區整合

前言 今天要來處理<DealerArea>內的元素如何整合拖曳移動到7個牌堆, 這部分會拆成2個部分來看: 可將<DealerArea>卡牌移入至牌堆上方,且遵守移動遊戲規則的條件 其他牌堆的牌無法移入<DealerArea>牌堆中 實作將<DealerArea>卡牌移入牌堆 這邊在DragDemo.vue中設定提供給發牌區<DealerArea>判斷用的:move函數,因為這個函數不像函數limitLocalMove函數是同時給7個牌堆各自使用,所以可以看到沒有特別提到from的部分,因為不用特別想就可以知道一定是來自(from)發牌區。 如果不清楚limitLocalMove是做什麼的,這部分從 第10天~第12天 的文章都有提到,主要是對應<draggable>元件的:move函數判斷使否可拖曳成功。 檢查疊牌遊戲規則的部分就由函數checkNextOk判斷,幾天前寫好的函數重新複用了👍 這邊只要result回傳true就會讓卡牌移動自動產生變化。 // DragDemo.vue /** 發牌區移動 */ function dealerMove(evt) { const to = getDomName(evt.to); const dealerCard = evt.draggedContext.element; // 檢查疊牌順序、花色是否正確 const result = checkNextOk(cardStacks[to], dealerCard); return result; } 樣板的部分就是小調整而已: // DragDemo.vue <DealerArea :deck="cardStacks.dealerStacks" :moveCard="dealerMove" /> 結果看起來拖曳過去是沒問題,但本該移動過去的元素也仍留在原地, 如下圖GIF出現了2個梅花9,此為禁忌的二重身問題💀必須修正。 修正陰魂不散的元素 因為還是有拖曳成功,只是舊資料殘留在發牌區的陣列cardStacks.dealerStacks,所以只要在拖曳完成時,將發牌區的陣列去除已經發出去的那一張牌即可,以下是修正後的程式碼: // DragDemo.vue function dealerMove(evt) { const to = getDomName(evt.to); const dealerCard = evt.draggedContext.element; // 檢查疊牌順序、花色是否正確 const result = checkNextOk(cardStacks[to], dealerCard); if (result) { changeOption....

September 25, 2023 · 1 min · 宗嘉