/**
* 創建基本卡組
*
* 思路
* 1. Array.from轉化基本花色字符串爲數組
* 2. 利用map進行初始化花色以及基本數字, 設置level屬性爲排序數組做準備
* 3. [].concat()平鋪數組
* @returns {Array} 返回type長度的二維數組
*/
const createDeck = (function(){
const type = "♠♥♦♣" // 基本花色
const base = ["3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"] // 牌組
return [].concat(...Array.from(type, item => {
return base.map( (v, key) => ({val: item + v, level: key}))
}), {val: "大王", level: 13}, {val: "小王", level: 13})
})()
/**
* 返回指定範圍的隨機數
*
* @param {number} [min] 最小值
* @param {number} [min] 最大值
* @returns {number} 數組下標
*/
function getRandom(min, max){
return Math.floor(Math.random() * (max - min) + min);
}
/**
* 生成隨機卡組
*
* 思路
* 1. Array.from初始化卡組長度
* 2. 隨機抽取數組元素
* 3. 根據level屬性進行重排序
* @returns {Array} 返回len長度的隨機數組
*/
function createGrop(len){
let cardNum = createDeck.length / len // 牌數
let copy = createDeck.concat() // 獲取基本卡組, 通過concat解引
return Array.from({length: len}, () => {
const sortHandle = (a, b) => b.level - a.level; // 重排序方法
let _, arr = []
// 如果長度爲最後立即返回,即後面的隨機抽取已沒意義
if(copy.length == 18) return copy.sort(sortHandle).map(v => v.val);
_ = function grop(){ // 自調用寫法
if(arr.length == cardNum) return; // 達到指定手牌數即終止
let cur = getRandom(0, copy.length)
if(arr.map(v => v.val).includes(copy[cur].val)){ // 檢測是否已存在
return grop() // 如果存在重新獲取隨機數
} else {
arr.push(copy[cur])
copy.splice(cur, 1) // 刪除原數組中已被抽取的數子
grop()
}
}()
arr = arr.sort(sortHandle).map(v => v.val) // 重排序數組,並刪除level屬性
return arr
})
}
console.log(createGrop(3)) // -↓
/*
0: (18) ["大王", "♠2", "♣A", "♦K", "♣K", "♥K", "♥Q", "♣J", "♣10", "♥10", "♦8", "♦7", "♠6", "♥6", "♥4", "♠4", "♣3", "♠3"]
1: (18) ["小王", "♦2", "♥A", "♦A", "♠A", "♠K", "♣Q", "♠Q", "♠J", "♥J", "♦9", "♣9", "♥8", "♣7", "♣6", "♠5", "♣4", "♥3"]
2: (18) ["♥2", "♣2", "♦Q", "♦J", "♠10", "♦10", "♠9", "♥9", "♠8", "♣8", "♠7", "♥7", "♦6", "♥5", "♦5", "♣5", "♦4", "♦3"]
*/