質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

714閲覧

jsを使って、21を超えない様にプログラムしたい

amazing02

総合スコア4

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2022/11/14 08:32

前提

jsでブラックジャックを作っており、相手のディーラーが3枚目を引いた時に21を超さないプログラムを作っているのですが、while文を使った所、無限ループが発生してしまった為、解決方法を教えていただきたいです。

実現したいこと

21を越さないようにjsでプログラムしたい

発生している問題・エラーメッセージ

無限ループ

該当のソースコード

javascript

1const trump = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; 2let trump_1 = trump[Math.floor(Math.random() * 13)]; 3let trump_2 = trump[Math.floor(Math.random() * 13)]; 4let trump_3 = trump[Math.floor(Math.random() * 13)]; 5let trump_4 = trump[Math.floor(Math.random() * 13)]; 6let trump_5 = trump[Math.floor(Math.random() * 13)]; 7let trump_6 = trump[Math.floor(Math.random() * 13)]; 8const enemyCard = trump_1 + trump_2; 9 const myCard = trump_4 + trump_5; 10 let enemyAddCard = trump_1 + trump_2 + trump_3; 11 while (enemyAddCard > 21) { 12 console.log(enemyAddCard); 13 trump_3 = trump[Math.floor(Math.random() * 13)]; 14 if (enemyAddCard < 21) { 15 break; 16 } 17 }

補足情報(FW/ツールのバージョンなど)

trump_1,trump_2trump_3が、ディーラーのカードになります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2022/11/14 09:01

10以上(J,Q,K)は10で計算しなくてもよいのでしょうか?Aは1か11で計算しなくてもいいのでしょうか?
guest

回答4

0

3枚目を引いた時に21を超さないプログラム

手札に一枚でもAがあれば21は超えませんね
2枚目までにAがなければ、強制的にAを引かせればよいでしょう

投稿2022/11/14 09:06

yambejp

総合スコア114833

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

ルール(前提条件)

通常のブラックジャックとはちょっと違うルールなのでしょうか?
一応以下のルールを前提にコードを書きました。

  • カードAは111どちらにも対応するが、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}

投稿2022/11/14 13:39

編集2022/11/14 15:11
Cocode

総合スコア2314

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

amazing02

2022/11/16 01:28

理解して実装することができました。ありがとうございました。
guest

0

while文の条件式に使われている変数への操作がないため値が変化しません
そのため、条件式を満たし続けるのでループから抜け出すことはありません

投稿2022/11/15 09:45

eipi-1-0

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

そのwhile文の中で、enemyAddCardという変数は全く操作されていません。
こいつが変化しないため、一旦このループに入ってしまうと無限ループとなります

投稿2022/11/14 08:39

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問