はじめまして、勉強中の初心者です。
今回JavaScriptでブラックジャックのアルゴリズムを組んでみました。
#使用関数
selectTrump 一番はじめにトランプを各2枚配る
drawCard 引数配列に1つ要素をいれて返す
total 引数配列の合計を返す
hitCard Hit時の挙動
stand stand時の挙動
yourTurn ディーラー側の挙動
result 結果判定
reset 初期化
ブラックジャックのルールを考えれば誰でも思いつくようなアルゴリズムなため、詳細は割愛します。
個人的にお気に入りなのは、1~13までの数を合計としてどのように処理するかのtotal関数。
たとえば、AAの組み合わせがあった時に合計は12となるように、Aが11扱いされるのは1つまでなので2つ目以降のAを1として処理するのを思いついた時はアルゴリズムって深いと感動しました。
よく考えれば部品にして使いまわす所や、もっと良いアルゴリズムや表記法があるような気がしないでもない。特に結果判定なんかは判定変数を 0/1/2 にして 勝ち/ドロー/負け とした方がすっきりかけたかもしれない…いや、それいったらif分岐をもっと簡潔にできたかもしれない…うーん
汎用性、拡張性を考えると、まだまだ最適解には程遠そうです。
次はできたコードをHTMLに落とし込む方法を模索したいと思います。
#コード
// global
var trumps = []; // トランプをいれる関数
var myHand = [];
var yourHand = [];
var myTotal = 0; // 合計値
var yourTotal = 0;
var flg = true; // 自分のターンかどうか
// const
var NUM = 2; // 最初に配る枚数
function selectTrump(){
// trumps の数をいれた配列の生成
for(var i = 0; i < 4; i++){
for (var j = 1; j < 14; j++){
trumps.push(j);
}
}
// 手札作成
for (var i =0; i < NUM; i++){
myHand = drawCard (myHand);
yourHand = drawCard (yourHand);
}
// 合計計算(A,10~13,2~9で分岐)
myTotal = total(myHand);
yourTotal = total(yourHand);
// 手札が21だった時flgをおろす
if(myTotal == 21){
flg = false;
yourTurn();
}
}
// カードを1枚引く関数
function drawCard(array){
array.push(trumps.splice(Math.random()*trumps.length,1));
return array;
}
// 配列を数字として合計を返す関数
function total(array){
var total = 0;
var a = 0; // Aの個数
for (var i = 0; i < array.length; i++){
var j = 0; // totall計算する時の値
switch(parseInt(array[i])){
case 1:
a++;
break;
case 10:
case 11:
case 12:
case 13:
j = 10;
total = total + j;
break;
default:
j = i;
total = total + parseInt(array[j]);
break;
} // end switch
} // end for
if(a > 0 && total <= 10){ // Aがある時
total = total + 11;
a--;
if(a > 0){ // aが2つ以上ある時2つ目は確実に1扱いなので+a
total = total + a;
}
}
return total;
}
// Hit
function hitCard(){
myHand = drawCard (myHand);
myTotal = total(myHand);
// 手札が21以上の時flgをおろす
if(myTotal >= 21){
flg = false;
yourTurn();
}
}
// Stand
function stand(){
flg = false;
yourTurn();
}
// ディーラー側の挙動
function yourTurn(){
if(yourTotal < 17){
for (var i = 0; yourTotal < 17; i++){
yourHand = drawCard (yourHand);
yourTotal = total(yourHand);
}
}
result();
}
// 合計を評価して高いほうを返す関数
function result(){
if(flg == false){
if(myTotal == 21 && yourTotal == 21){ // いずれかが21の時
alert("引き分け");
} else if (myTotal ==21 && yourTotal != 21){
alert("あなたの勝ち");
} else if (myTotal !=21 && yourTotal == 21){
alert("あなたの負け");
} else if(myTotal > 21 && yourTotal > 21){ // 自分も相手も21超過
alert("引き分け");
} else if(myTotal < 21 && yourTotal > 21){ // 相手のみ21超過
alert("あなたの勝ち");
} else if(myTotal > 21 && yourTotal < 21){ // 自分のみ21超過
alert("あなたの負け");
} else if(myTotal < 21 && yourTotal < 21){ // どちらも21以下
if(myTotal == yourTotal){
alert("引き分け");
} else if(myTotal - yourTotal > 0){
alert("あなたの勝ち");
} else {
alert("あなたの負け");
}
} // end if total
reset();
} // end if flg
}
// リセット関数
function reset (){
flg = true;
trumps = [];
myHand = [];
yourHand = [];
myTotal = 0;
yourTotal = 0;
selectTrump ();
}