今天會實作發牌區
、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.delaerStacks" :moveCard="dealerMove" />
<div class="text">結算牌堆</div>
<FinishedArea :fourCards="cardStacks" @doms="setFourCardDoms" :change="cardChange" />
</div>
在DragDemo.vue
中對變數cardStacks
新增四個key調整,而原本的函數getDomName(dom)
也要跟著調整,
主要除了上層對應7個牌堆、也需要對應到結算牌堆
的HTML元素。
底下程式碼中使用花色列表FOUR_SUITS
一個個檢查,
若有相同的元素則回傳結算牌堆
的花色名稱 (club/diamond/heart/spade),否則依然回傳none。
// DragDemo.vue
function getDomName(dom) {
if (dom == first.value.targetDomElement) {
return 'first';
} else if (dom == second.value.targetDomElement) {
return 'second';
} else if (dom == third.value.targetDomElement) {
return 'third';
} else if (dom == fourth.value.targetDomElement) {
return 'fourth';
} else if (dom == fifth.value.targetDomElement) {
return 'fifth';
} else if (dom == sixth.value.targetDomElement) {
return 'sixth';
} else if (dom == seventh.value.targetDomElement) {
return 'seventh';
} else {
for (let i = 0; i < FOUR_SUITS.length; i++) {
const name = FOUR_SUITS[i];
if (dom == fourCardsDom[name]) {
return name;
}
}
return 'none';
}
}
上方程式碼寫到的變數fourCardsDom
是一個字典,KEY會是花色(字串),VALUE對應畫色的結算牌堆(HTML元素)。
底下的函數setFourCardDoms
將花色、HTML元素儲存到變數fourCardsDom
這個字典中這件事,會在<FinishedArea />
發送的@doms
事件被執行,這跟昨天實作在DealerAreaView.vue
中一樣只會執行一次。
// DragDemo.vue
const fourCardsDom = reactive({
club: null,
diamond: null,
heart: null,
spade: null,
});
function setFourCardDoms(cardDomMaps) {
FOUR_SUITS.forEach(name => {
const domElement = cardDomMaps[name];
fourCardsDom[name] = domElement;
});
}
主要是調整內部變數result
的布林判斷,如果拖曳目標位置名稱to
是結算牌堆的花色則走屬於checkNextOk2
的判斷,否則是走checkNextOk
的不同花色疊牌判斷,至於if (result)
內的並沒有調整。
/** 發牌區移動 */
function dealerMove(evt) {
const to = getDomName(evt.to);
const dealerCard = evt.draggedContext.element;
const { futureIndex } = evt.draggedContext;
let result = true;
// 如果目標是結算盤堆,則套用結算盤堆的規則
if (FOUR_SUITS.includes(to)) {
result = result && checkNextOk2(to, cardStacks, dealerCard);
} else {
// 只能移動至目標牌堆的最後一張牌
result = result && futureIndex == cardStacks[to].length;
// 檢查疊牌順序、花色是否正確
result = result && checkNextOk(cardStacks[to], dealerCard);
}
if (result) {
changeOption.value = () => {
cardStacks.delaerStacks = cardStacks.delaerStacks.filter(card => card.value !== dealerCard.value);
changeOption.value = null;
};
}
return result;
}
這部分跟發牌區拖曳一樣只改動result
的布林判斷,如果是針對結算牌堆
則改用checkNextOk2
,目前測試應該是沒問題,直接上縮減後的程式碼:
function limitLocalMove(evt) {
// 略
if (FOUR_SUITS.includes(to)) {
result = result && checkNextOk2(to, cardStacks, element);
} else {
// 只能移動至目標牌堆的最後一張牌
result = result && futureIndex == cardStacks[to].length;
// 檢查疊牌順序、花色是否正確
result = result && checkNextOk(cardStacks[to], element);
}
// 略
}
已完成撲克牌都可以遵守規則拖曳至結算牌堆
,但目前結算牌堆
的牌移入後就無法移出,所以結算牌堆
還不完全符合紙牌接龍的遊戲規則。
明日預計完成結算牌堆
的牌應該要可以拖曳回7牌堆
。
程式碼: https://github.com/kabuto412rock/ithelp-pokergame/tree/day19