题目:
解题思路:
- 洗牌【Fisher–Yates 算法】
- 发牌【按顺序分发】
- 判断结果 【查重、比较&排序、结果输出】
- 重新开始下轮
- 响应式API绑定
Talk is cheap, Show code.
编写代码
1、定义数据类型
export type Record = {
roundId: number, //第几轮发牌
playerId: number, //玩家Id
cards: string, //玩家手中的牌
result: boolean // 输赢判定结果 (win = 1 / lost = 0)
}
//存储于Vuex中的接口定义
export interface IResultInfo {
history: Record []
}
//用于玩家手中的牌面比较和排序
export type SortedAnalysisData = {
playerId: number
prefix: string, //前缀,注意 10 需要特别处理, A/J/Q 等
count: number, //前缀重复次数
suffixs: string //后缀联合的字符串,比如:^@*
}
2、定义常量类型
let cards = ["2@","2#","2^","2*",
"3@","3#","3^","3*",
"4@","4#","4^","4*",
"5@","5#","5^","5*",
"6@","6#","6^","6*",
"7@","7#","7^","7*",
"8@","8#","8^","8*",
"9@","9#","9^","9*",
"10@","10#","10^","10*",
"J@","J#","J^","J*",
"Q@","Q#","Q^","Q*",
"K@","K#","K^","K*",
"A@","A#","A^","A*",
];
//用于按顺序Index比较
const prefixSequence = ["2","3","4","5","6","7","8","9","10","J","Q","K","A",];
const suffixSequence = ["@", "#", "^", "*"];
3、洗牌 & 发牌
let curPlayerCards: string[][] = [[], [], [], []];
//Fisher–Yates for random sequence
function shuffleCards(): void {
let currentIndex = cards.length;
let randomIndex = 0;
while (currentIndex !== 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[cards[currentIndex], cards[randomIndex]] = [
cards[randomIndex],
cards[currentIndex],
];
}
function dealCard(): void {
cards.forEach((value: string, index: number) => {
curPlayerCards[index % 4][Math.trunc(index / 4)] = value;
});
}
}
4、查重 & 标识
function findRepeatCards(playerId: number, cardArray: string[]) {
cardArray.reduce((analysisData, cur) => {
let prefix = cur.charAt(0);
let suffix = cur.charAt(1);
//10 is special
if (cur.charCodeAt(1) >= 48 && cur.charCodeAt(1) <= 57) {
prefix = cur.substring(0, 2);
suffix = cur.charAt(2);
}
let matchedRecord = isExistedInAnalysisData(
playerId,
prefix,
analysisData
);
if (typeof matchedRecord !== "undefined") {
matchedRecord.count += 1;
matchedRecord.suffixs += suffix;
} else {
analysisData.push({
playerId: playerId,
prefix: prefix,
count: 1,
suffixs: suffix,
});
}
return analysisData;
}, analysisData);
}
function isExistedInAnalysisData(
playerId: number,
prefix: string,
analysisData: SortedAnalysisData[]
) {
return analysisData.find(
(data) => data.prefix === prefix && data.playerId === playerId
);
}
5、比较 & 排序
//玩家手中牌面的比较和排序
export function sortByPrefixAndSuffix(prefixSequence:string[], suffixSequence:string[], analysisData:SortedAnalysisData[]){
analysisData.sort((first, second) =>{
//max repeat count
if(first.count > second.count){
return -1;
}else if (first.count === second.count){
const firstPrefixIndex = prefixSequence.indexOf(first.prefix);
const secondPrefixIndex = prefixSequence.indexOf(second.prefix);
//large prefix index
if(firstPrefixIndex > secondPrefixIndex){
return -1;
}else if(firstPrefixIndex === secondPrefixIndex){
const firstSuffixIndex = spliteAndCheckMaxIndex(first.suffixs, suffixSequence);
const secondSuffixIndex = spliteAndCheckMaxIndex(second.suffixs, suffixSequence);
//large suffix index
if(firstSuffixIndex > secondSuffixIndex){
return -1;
}
}
}
return 1;
})
}
function spliteAndCheckMaxIndex(suffixs:string, suffixSequence:string[]){
let index = 0;
suffixs.split('').forEach((item)=> {
const temp = suffixSequence.indexOf(item);
if(temp > index){
index = temp;
}
})
return index;
}