ルール(前提条件)
通常のブラックジャックとはちょっと違うルールなのでしょうか?
一応以下のルールを前提にコードを書きました。
- カードAは
1
と11
どちらにも対応するが、3枚目までで21以下かの判定の際は1
として扱う
- カード2〜10は数字の通りとする
- カードJ, Q, Kは、
11
, 12
, 13
とする
考え方
- 手札が3枚未満の時、
- 「手札の配列+引いてきたカードの合計が22未満」の場合、手札の配列にそのカードを加える。
- 22以上の場合、カードを引き直す。
- 決定したカードを山札の配列から削除 → 手札の配列に格納する。
あとは、質問者様のコードですと、奇跡的にランダムな数字が全部一緒になったら、5枚以上同じカードを引いてしまえることになります。
(トランプは1つの数字につき、同数字はそれぞれ4枚までだと思います)
そうならないように、引いたカードは山札から削除する処理をしました。
コード例
ボタンをクリックしたら、敵・ユーザーそれぞれカードを1枚引くようにしました。
html
1<button id="btn-draw">Draw a card</button>
javascript
1console.clear();
2
3// エースカードの数字
4const ace = [1, 11];
5// 山札を生成
6const cardsInDeck = Array.from({length: 13}, (_, i) => Array(4).fill((i===0 ? 'A' : i+1))).flat();
7// ['A', 'A', 'A', 'A', 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, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13]
8console.log(cardsInDeck)
9
10// クラスを定義
11class Player {
12 constructor() {
13 this.cardsInHand = []; // 手札
14 }
15
16 // 配列の長さの範囲内(残りの山札数)で、ランダムな番号を生成するメソッド
17 getRandomIndex(allCardsArr) {
18 return Math.floor(Math.random() * allCardsArr.length - 1);
19 }
20
21 // 配列(残りの山札)から、カードを選択するメソッド
22 getRandomCard(allCardsArr, index) {
23 return allCardsArr[index];
24 }
25
26 // 配列(手札)の合計値が、22未満か確認するメソッド
27 // エースの時は1として扱う
28 isSmallerThan22(numOrStr) {
29 return this.cardsInHand.reduce((acc, cur) => acc + (cur === 'A' ? ace[0] : cur), 0) + (numOrStr === 'A' ? ace[0] : numOrStr) < 22;
30 }
31
32 // 山札からカードを引いて、手札にいれるメソッド
33 drawCard(allCardsArr) {
34 let randIdx = this.getRandomIndex(allCardsArr);
35 let card = this.getRandomCard(allCardsArr, randIdx);
36
37 // 配列の長さが3未満(今持っている手札が2枚まで)の場合
38 if (this.cardsInHand.length < 3) {
39 while (true) {
40 // 手札と新しくひいたカードの合計値が22未満か確認
41 const flag = this.isSmallerThan22(card);
42
43 // 22未満なら、whileループを終了する
44 if (flag) {
45 break;
46
47 // 22以上なら、カードを引き直す
48 } else {
49 console.log('手札が2枚以下、かつ、合計が21を超えるので、カードを引き直します。');
50 randIdx = this.getRandomIndex(allCardsArr);
51 card = this.getRandomCard(allCardsArr, randIdx);
52 }
53 }
54 }
55
56 // 引いたカードを、山札から削除する
57 const [pickedCard] = allCardsArr.splice(randIdx, 1);
58
59 // 引いたカードを、手札にいれる
60 this.cardsInHand.push(pickedCard);
61 }
62}
63
64const user = new Player();
65const enemy = new Player();
66
67const btnDraw = document.querySelector('#btn-draw');
68btnDraw.addEventListener('click', drawCard);
69
70function drawCard() {
71 // 山札のカードが0枚の時、処理を終了する
72 if (cardsInDeck.length === 0) {
73 console.log('山札にカードがありません。');
74 return;
75 }
76
77 enemy.drawCard(cardsInDeck);
78 user.drawCard(cardsInDeck);
79
80 // コンソールに表示
81 console.group('new turn')
82
83 console.log('---enemy cards---');
84 console.log(enemy.cardsInHand);
85
86 console.log('---user cards---');
87 console.log(user.cardsInHand);
88
89 console.groupEnd();
90}