Studio Happyvalley

トランプのカードを
シャッフルする
スクリプト

数値が重複しないように
ランダムに混ぜ合わせる

image: トランプのカードをシャッフルするスクリプト
Shuffle Playing Cards With JS

Javascriptで数値が重複しないようにランダムに混ぜ合わせる

 | 2023/07/10

開発
基礎

トランプのカードをシャッフルするために必要なこと
  • カードが重複しないことと、カードの順番を乱数で生成すること 

    例えば、5枚のカードがあるとして、単純に乱数を使うとカードが重複してしまいます。
    そのため順番にすべてのカードを他のカードと差し替えていく必要があります。
    差し替えるという考え方で、カードの重複を避けられます。

  • まずは乱数発生のスクリプトから 

    乱数発生の関数はMath.random() 関数を使用します。また、数値の範囲を決める場合も決まった構文があります。
    たとえば1~10までの間で乱数を発生しさせたい場合は、下記の関数へgetRandomNumber(1, 10.)と引数を送ります。

    function getRandomNumber(min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    }
  • 乱数を生成する時、処理中のカードと同じ順番を避ける 

    たとえば5枚組のカードの3番目を他のカードと差し替えるため乱数を生成したとします。
    その場合5分の1の確率で同じ順番がでます。それだと意味がないので、同じ順番が出た場合は、違う数値が生成されるまで乱数を生成する仕組みが必要です。下記がそのスクリプトになります。違う数値が生成されるまで乱数の生成を繰り返します。

    do {
    	r = getRandomNumber(1, cardsCount); // 1からカード総数(1, cardsCount)の範囲でランダムな数を生成
    } while (r == d);//dは処理中のカードの順番
  • 補足

    『javascript,シャッフル』で調べるとよくあるのは、配列を順番に他のカードと差し替えるところは同じですが、カードを重複させないために、差し替えるカードの数がどんどん減少していくロジックが多いです。
    これだと最初の方のカードは差し替える対象が50枚とかなのに、最後の方のカードになると残り一枚とだけ差し替えることになりこれじゃあシャッフルじゃあありませんね。
    なので常にすべてのカードを対象にし、ランダムに差し替えるようにしました。

    また、全部のカードをシャッフル対象とせず、使用する枚数のみシャッフルするという考え方もあるようですが、やはりここはリアルに全てのカードをシャッフルしたいですね。処理時間をかけないという意味があるようですが…。
    でも、現実でもシャッフルにじっくり時間をかけてシャッフルしますよね。この待ち時間に期待感が高まるわけですから。
    このワクワクこそがロマンなんですから。

JS
実装

トランプのカードをシャッフルするためのJavascriptになります。
  • 上記をまとめた、カードをシャッフルするスクリプトを下記に記します。 

    カード5枚のシャッフルスクリプトになります。

    const i={
    	cards: ['mja1.jpg','mja2.jpg','mja3.jpg','mja4.jpg','mja5.jpg'],
    	_data: [],
    	get data(){return this._data},
    	set data(v){this._data= v},
    	newArray: [],
    	limit: 3,
    	n: 0
    };
    	
    function setCard(i){
    	i.data= [];
    	i.newArray.forEach(function(v){
    		i.data.push(`<div><img src="/assets/labo/shuffle/images/${v}" alt="${v}"></div>`)
    	});
    	container.innerHTML = i.data.join('');
    }
    
    function getRandomNumber(min, max) {
      return Math.floor(Math.random() * (max - min + 1)) + min;
    }
    
    function shuffle(i) {
    	const container= document.querySelector('#container');
    	let d = i.cards.length;
    	const cardsCount= d - 1;
    	let r;
    	
    	while (d) {
    		--d;
    		do {
    			r = getRandomNumber(1, cardsCount); // 1からカード総数の範囲でランダムな数を生成
    			console.log(`IN: ${d} : ${r}`);
    		} while (r == d);
    		const t = i.cards[d];
    		i.cards[d] = i.cards[r];
    		i.cards[r] = t;/*ここで初期値カードとランダムカードを入れ替える*/
    		console.log(i.cards);
    		i.newArray= i.cards;
    	}
    	setCard(i);
    }
  • 上記の実装サンプル

    上記のサンプルへシャッフルを複数回可能なように設定追加。
    その場合、配列初期値を一番最後の配列で上書きするように設定。
    この設定を入れないと、せっかく複数回シャッフルしても一番最初の配列が1~5に毎回もどってしまうため。

    カードをシャッフルするスクリプト:
    https://labo.studio-happyvalley.com/shuffle/

検証

想定通りに動作するかをコンソールへ書出して検証します
  • カードを差し替える処理の度にその時点の配列をコンソールへ書き出して想定通りに動作しているかを検証します

    コンソールログは下記のように出力されました。

    Image-1

  • 上のコンソールログの解説です。

    1行目:処理される前の配列:順番通りに1~5まで整列しています。
    処理は最後から一枚づつ順番に処理されます。
    Array(5) [ "mja1.jpg", "mja2.jpg", "mja3.jpg", "mja4.jpg", "mja5.jpg" ]

    2行目:一回目の差し替え処理。上の最後の"mja5.jpg" を差し替えるため乱数を生成します。
    『IN: 4 : 1』の4は処理対象のカードの順番。1は生成された乱数です。
    配列は0から始まるのでそれぞれ1を足した数値が順番になります。
    つまり下記は初期状態の5番目のカードを2番目のカードと差し替えたことになります。
    IN: 4 : 1
    Array(5) [ "mja1.jpg", "mja5.jpg", "mja3.jpg", "mja4.jpg", "mja2.jpg" ]

    次の処理:4番目のカードを2番目のカードと差し替え
    IN: 3 : 1
    Array(5) [ "mja1.jpg", "mja4.jpg", "mja3.jpg", "mja5.jpg", "mja2.jpg" ]

    同様
    IN: 2 : 1
    Array(5) [ "mja1.jpg", "mja3.jpg", "mja4.jpg", "mja5.jpg", "mja2.jpg" ]

    下記の場合、処理対象の順番と入れ替えたいカードの順番が同じだったため、変わるまで乱数を生成しています。
    IN: 1 : 1
    IN: 1 : 3
    Array(5) [ "mja1.jpg", "mja5.jpg", "mja4.jpg", "mja3.jpg", "mja2.jpg" ]

    同様
    IN: 0 : 2
    Array(5) [ "mja4.jpg", "mja5.jpg", "mja1.jpg", "mja3.jpg", "mja2.jpg" ]

    というわけで想定通りの動作を確認。

実装
サンプル

このシャッフルプログラムを応用・実装したサンプルです。
  • すでにLABOサイトで公開中のWeb Tarotで動作中です。

    シャッフルとカードめくりを組み合わせた実装サンプルです。タロットのケルト十字占法の配置にカードを展開します。

    シャッフルを応用したWeb Tarot:
    https://labo.studio-happyvalley.com/webtarot/

『トランプのカードをシャッフルするスクリプト』関連のお薦め

このページで紹介しているプログラムやビジュアルなどご依頼いただければ実装を賜ります。
お問い合わせはこちら