重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

$loop = 5;
$count = 0;

while($count < $loop){
mt_srand(microtime() * 100000);
$rand_key = rand(0,9);
if (in_array($rand_key, $yomi)){
$count--;
continue;
}

echo $yomi[$rand_key]\n;
}


配列($yomi)に格納されたひらがなから5つ重複させずに選び出したいのですが、
randで選出された「りんご」が2度選び出された場合、これでやり直しされますか?
現在出力出来る環境がありません…

初心者ですので指摘やアドバイス等いただけると嬉しいです。
よろしくお願いします。

A 回答 (2件)

全然ダメですね。


まず、終了条件をみたすことがないのでこのプログラムは終了しません。
$count < $loopが終了条件ですが、$count--はあっても$count++が無いので、このプログラムは終了条件をみたすことはありません。(まあ、あえてあるとしたらinteger overflowで符号が逆転した時でしょうが...)
終了条件という点で言うと、重複を許さず選択するということなので$loopよりも$yomiの要素数が少ないと無限ループに陥るのでそのチェックをしたほうがベターです。

また、in_arrayの使い方もおかしいです。
上記のin_arrayでは$rand_keyが$yomiに含まれるか調べていますが、調べるべきは$yomiではなく既に選ばれたかどうかでしょう。その場合も$count--するのは間違っています。

さらに、この方向でプログラムを書くとしたら、次の2点を満たしてないとダメですね。
1. $rand_keyが使われたことを示す配列を作る
2. 表示した時だけ$countの値を増やす。選ばなかったらカウントアップしなければいいだけなので、$countから値を引く必要は全くないと思います。

あと、細かいことですがmt_srandの使い方も変です。PHP 4.2.0以降ではmt_srandは不要になりましたし、mt_srandを使うなら、乱数を取り出すにはmt_randだと思います。
http://php.net/manual/ja/function.mt-srand.php

という点を考えて書きなおすとこんな感じです。
if (count($yomi) > $loop) {
$selected_keys = array();
while ($count < $loop){
$rand_key = mt_rand(0, count($yomi) - 1);
if (in_array($rand_key, $selected_keys)) {
continue;
}
array_push($selected_keys, $rand_key);
$count++;
echo $yomi[$rand_key]."\n";
}
} else {
echo "Error: cannot choose yomi for $loop times.\n";
}
選択した$rand_keyは$selected_keysに入れておき、後でチェックしています。また、mt_randは端点を含むのでcount($yomi) - 1となっています。ちなみに、countとは配列の要素数を数える関数です。
http://php.net/manual/ja/function.mt-rand.php
http://jp1.php.net/manual/ja/function.count.php


元のやつだとn個からn個の要素を取る場合でnがある程度大きいと、何度も次のところを実行して空振りし続けるので、自分だったら別のやり方でやります。
| $rand_key = mt_rand(0, count($yomi) - 1);
| if (in_array($rand_key, $selected_keys)) {
| continue;
| }

$loopが要素数以上かのチェックは省略しました。$yomiのコピーを作って、出力するたびにそれを配列から消していきます。これだとそもそも配列には前回選んだものは含まれないのでin_arrayのチェックをする必要はありません。
$yomi_copy = $yomi; // make clone of $yomi.
for ($count = 0; $count < $loop; $count++) {
$rand_key = mt_rand(0, count($yomi_copy) - 1);
echo "$yomi_copy[$rand_key]\n";
array_splice($yomi_copy, $rand_key, 1);
}

ちなみに、PHPでは配列を代入すると配列のコピーができるので、$yomi_copyをいくらいじっても元の$yomiには影響を与えません。
また、array_spliceというのは配列の一部の要素を切り取る命令です。
http://php.net/manual/ja/function.array-splice.php
    • good
    • 0
この回答へのお礼

お早い回答ありがとうございます。

加算するのは忘れてました!
色々と勉強不足ですみません…

回答してくださったものを元にやってみます!
ありがとうございました!

お礼日時:2012/12/09 19:39

シャッフルして前から5個取り出せばよいのでは?

    • good
    • 0
この回答へのお礼

すみませんありがとうございます!
別の形で取り入れさせて頂きました!

お礼日時:2012/12/25 15:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!