FisherYates

構文
FisherYates( var arr[] )
引数
var arr[]
シャッフルする配列(参照引数)
戻値

プログラム

//////////////////////////////////////////////////
// 【引数】
//   var arr[] : シャッフルする配列(参照引数) 
// 【戻値】
// 
//////////////////////////////////////////////////
PROCEDURE FisherYates(var arr[])
	FOR n = UBound(arr) TO 0 STEP -1
		DIM num = RANDOM(n+1)
		DIM tmp = arr[n]
		arr[n] = arr[num]
		arr[num] = tmp
	NEXT
FEND

//////////////////////////////////////////////////
// 【引数】
//   配列 : 上限値を求める配列 
// 【戻値】
//   配列の上限値 
//////////////////////////////////////////////////
FUNCTION UBound(array[])
	RESULT = RESIZE(array)
FEND

プログラム実行例

ハイアンドロー

DIM cards[-1]
DIM mark[3] = "♠", "♥", "♣", "♦"

FOR item IN mark
	FOR n = 1 TO 13
		arrayPush(cards, item + n)
	NEXT
NEXT

FisherYates(cards)

FOR n = 0 TO UBound(cards) - 1
	DIM res = SLCTBOX(SLCT_BTN OR SLCT_NUM, 0, "次のカードは「 " + cards[n] + " 」よりHIGH、LOW?", "HIGH", "LOW")
	PRINT cards[n] + "<#TAB>" + COPY(cards[n], 2)
	PRINT cards[n+1] + "<#TAB>" + COPY(cards[n+1], 2)
	DIM before = VAL(COPY(cards[n], 2))
	DIM after = VAL(COPY(cards[n+1], 2))
	IF res = 0 THEN operator = "<"
	IF res = 1 THEN operator = ">"
	res = IIF(before + operator + "=" + after, "正解", "不正解")
	PRINT res
	IF res = "不正解" THEN EXIT
	PRINT "----------"
NEXT

MSGBOX("全問正解!!!")

//////////////////////////////////////////////////
// 【引数】
//   array : 要素を追加する配列(参照引数) 
//   str : 追加する要素 
// 【戻値】
//   処理後の配列の中の要素の数 
//////////////////////////////////////////////////
FUNCTION arrayPush(var arr[], str)
	DIM res = RESIZE(arr, UBound(arr) + 1)
	arr[res] = str
	RESULT = res + 1
FEND

//////////////////////////////////////////////////
// 【引数】
//   var arr[] : シャッフルする配列(参照引数) 
// 【戻値】
// 
//////////////////////////////////////////////////
PROCEDURE FisherYates(var arr[])
	FOR n = UBound(arr) TO 0 STEP -1
		DIM num = RANDOM(n+1)
		DIM tmp = arr[n]
		arr[n] = arr[num]
		arr[num] = tmp
	NEXT
FEND

//////////////////////////////////////////////////
// 【引数】
//   expr : 評価する式 
//   truepart : 評価した式がTrueのときに返す値 
//   falsepart : 評価した式がFalseのときに返す値 
// 【戻値】
//   truepart : 評価した式がTrueのとき、falsepart : 評価した式がFalseのとき 
//////////////////////////////////////////////////
FUNCTION IIF(expr, truepart, falsepart)
	IFB EVAL(expr) THEN
		RESULT = truepart
	ELSE
		RESULT = falsepart
	ENDIF
FEND

//////////////////////////////////////////////////
// 【引数】
//   配列 : 上限値を求める配列 
// 【戻値】
//   配列の上限値 
//////////////////////////////////////////////////
FUNCTION UBound(array[])
	RESULT = RESIZE(array)
FEND
結果
♦12 12
♠1 1
正解
----------
♠1 1
♥7 7
正解
----------
♥7 7
♥13 13
正解
----------
♥13 13
♦9 9
正解
----------
♦9 9
♥1 1
正解
----------
♥1 1
♥5 5
正解
----------
♥5 5
♥10 10
正解
----------
♥10 10
♣4 4
正解
----------
♣4 4
♠10 10
正解
----------
♠10 10
♥6 6
不正解

配列の中身をシャッフルして出力

DIM arr[] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

FisherYates(arr)

FOR item IN arr
	PRINT item
NEXT

//////////////////////////////////////////////////
// 【引数】
//   var arr[] : シャッフルする配列(参照引数) 
// 【戻値】
// 
//////////////////////////////////////////////////
PROCEDURE FisherYates(var arr[])
	FOR n = UBound(arr) TO 0 STEP -1
		DIM num = RANDOM(n+1)
		DIM tmp = arr[n]
		arr[n] = arr[num]
		arr[num] = tmp
	NEXT
FEND

//////////////////////////////////////////////////
// 【引数】
//   配列 : 上限値を求める配列 
// 【戻値】
//   配列の上限値 
//////////////////////////////////////////////////
FUNCTION UBound(array[])
	RESULT = RESIZE(array)
FEND
結果
4
7
3
9
1
10
2
5
8
6

フィッシャー–イェーツのシャッフル

フィッシャー-イェーツのシャッフルとは、有限集合からランダムな順列を生成するアルゴリズムです。処理の流れは、くじ引きボックスに入れた紙を1枚ずつ取り出して並べるイメージです。

処理時間はシャッフルされる要素数に比例します。