シャッフルするには…?
トランプを切って並べたら
番号がランダムに並ぶ…。
これを実現する処理を
作るにはどうしたら良いか?
ここでは、単純に0~9の数とするよん。
さて、最初のプログラムは、
ボケが、プログラムをやり始めた頃に
組んだボケボケプログラム。
どのぐらいボケかと言うと
殆ど期待通りに動かん…。
----------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int card[10];
void shuffle( void )
{
int i;
for( i = 0 ; i < 10 ; i++ )
card[i] = 10 * rand( ) / ( RAND_MAX + 1 );
}
int shuffle_check( void )
{
int i, list[10];
memset( list, 0, sizeof( list ) );
for( i = 0 ; i < 10 ; i++ )
list[ card[i] ]++;
for( i = 0 ; i < 10 ; i++ )
if( list[i] != 1 )
return 0;
return 1;
}
void main( void )
{
int i;
i = -1;
srand( 0 ); /* 毎回同じ結果を期待 */
do
{
i++;
shuffle( );
} while( !shuffle_check( ) );
printf( "error count %d!", i );
}
----------------------------------------
約7500回に1回、成立する…。
って、おいおい…!
よくよく考えてみると…。
・丸め誤差
・数値の制限(循環する)
から、まず成功しない…。
つまり、やり方が悪い!
と言う訳で直したのがこれ。
----------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int card[10];
void shuffle( void )
{
int i, c, r;
for( i = 0 ; i < 10 ; i++ )
card[i] = i;
for( i = 0 ; i < 9 ; i++ )
{
r = ( 10 - i ) * rand( ) / ( RAND_MAX + 1 );
c = card[i];
card[i] = card[r];
card[r] = c;
}
}
int shuffle_check( void )
{
int i, list[10];
memset( list, 0, sizeof( list ) );
for( i = 0 ; i < 10 ; i++ )
list[ card[i] ]++;
for( i = 0 ; i < 10 ; i++ )
if( list[i] != 1 )
return 0;
return 1;
}
void main( void )
{
srand( 0 ); /* 毎回同じ結果を期待 */
shuffle( );
printf( shuffle_check( ) ? "good!" : "error!" );
}
----------------------------------------
見た通り、カードを切る様に
数値をランダムに入れ替えています。
この方法は、麻雀牌を混ぜたりするのに
使えるので覚えて損は、無いが…
ちょっと考えれば気が付くよね…。
| 固定リンク
コメント