考え、感じる、Web制作。

Web制作の学習や情報についての記事が中心です。

百人一首クイズ1

百人一首クイズを作る

phpMySQLの学習内容をふまえ、百人一首クイズを作る。今回は第1問目が表示されるところまで進める。
f:id:ys_nim_9:20141116044305p:plain

仕様

出題ページ(index.php)、回答ページ(answer.php)、最終結果ページ(result.php)の3ページで制作。上の句に対し下の句が4択で表示される。POSTで選択データを回答ページに送り、成否判定する。次の問題へ進むためのリンクを用意し、出題ページに戻る形にする。これを交互に繰り返し、5問終了時点で最終結果ページに飛び、出題内容と成否結果を一覧表示させる。DBはhyakuninという名前で事前に用意し、歌の番号(code)、上の句(first_poem)、下の句(second_poem)、詠み人(poet)のデータを格納してある。

問題を生成する

まずは問題をランダムに生成させる。乱数を使った方法を考えたが、rangeにshuffleという命令を組み合わせて使うとコードが短くなる。乱数を使う場合は、乱数生成後に並び替えが必要になるが、range + shuffleでは並び替える必要がない。今回は5問分を一度に生成してしまう。こうすることで問題が重複していないかのチェックをする必要がなくなる。

if(!isset($rand)){
$rand=range(1,100);
shuffle($rand);
  for($i=1;$i<=5;$i++){
    $mondai[$i]=$rand[$i];
  }
}

この処理により$mondai[$i]に1~100までのうち5つが無作為に格納される。この値をキーにして問題となる歌を呼び出す。

正解データのDB呼び出し

歌番号、上の句、下の句、詠み人の各データをDBから呼び出し、変数に格納する。これらのデータはセッションで受け渡すため、その格納も行なう。今回は最初の問題だけ表示させるところまでの処理を書くので、$code=$mondai['1'];とした

$code=$mondai['1'];
try{
  $dbh=new PDO(DB_CONNECT,DB_USER,DB_PASS);
}catch(Exception $e){
  //echo $e->getMessage();
  exit('ランタイムエラーが発生しました');
}
$sql="SELECT poet,first_poem,second_poem FROM hyakunin WHERE code=:code;";
$stmt=$dbh->prepare($sql);
$stmt->bindParam(':code',$code);
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$kami=$row['first_poem'];
$shimo=$row['second_poem'];
$poet=$row['poet'];
$_SESSION['monme']=$monme;
$_SESSION['seikai']['code']=$code;
$_SESSION['seikai']['kami']=$kami;
$_SESSION['seikai']['shimo']=$shimo;
$_SESSION['seikai']['poet']=$poet;

誤りの選択肢の生成

正解以外の選択3件を生成する。問題生成とほぼ同様だが、正解と重複が発生しないようにif文を追記している。正解の下の句と同じ値を持ってきてしまった場合はループをやり直す指定。取り出した値は$anser[$i]に格納。

$rand=range(1,100);
shuffle($rand);
for($i=1;$i<=3;$i++){
  $sql="SELECT second_poem FROM hyakunin WHERE code=:code;";
  $stmt=$dbh->prepare($sql);
  $stmt->bindParam(':code',$rand[$i-1]);
  $stmt->execute();
  $row2=$stmt->fetch(PDO::FETCH_ASSOC);
  $answer[$i]=$row2['second_poem'];
  if($answer[$i]===$row['second_poem']){
    $i=$i-1;
  }
}

選択肢をシャッフル

$answer['0']に正解を格納後、選択肢をシャッフルし、正解の位置が固定されないようにする。

$answer['0']=$row['second_poem'];
shuffle($answer);

回答の格納

正解の場合は$_SESSION['kotae']にcodeを格納、不正解の場合は0を格納する。

for($i=0;$i<=3;$i++){
  if($answer[$i]===$shimo){
    $kotae[$i]=$code;
  }else{
    $kotae[$i]=0;
  }
}
$_SESSION['kotae']=$kotae

ブラウザ表示

$answerの値をformのradioで表示させる。

  <h1>百人一首 第<?php print$monme;?></h1>
  <p class="black">ランダムで5首の上の句が表示されます。下の句を4択で回答してください。<br>目指せ、全問正解!</p>
  <dl>
    <dt><?php print$code;?><br>詠人:<?php print$poet;?></dt>
    <dd class="big"><?php print$kami;?></dd>
  </dl>
  <form action="answer.php" method="POST" class="grayback">
    <label for="kotae" class="black">答えを選んで回答ボタンをクリック!</label><br>
    <input type="radio" name="kotae" id="kotae" value="<?php echo$kotae['0'];?>" checked><?php print$answer['0'];?><br>
    <input type="radio" name="kotae" id="kotae" value="<?php echo$kotae['1'];?>"><?php print$answer['1'];?><br>
    <input type="radio" name="kotae" id="kotae" value="<?php echo$kotae['2'];?>"><?php print$answer['2'];?><br>
    <input type="radio" name="kotae" id="kotae" value="<?php echo$kotae['3'];?>"><?php print$answer['3'];?><br>
    <input type="submit" value="回  答">
  </form>

今回はここまでとする。

感想

ここまでの記述で約3時間の工数がかかった。ポイントはrange + shuffleの箇所だ。最初は乱数を発生させる記述で進めていたが、調べているうちにshuffleの使い方を発見し、早速採用したところ大変便利であることが分かった。実際の業務でランダム要素を扱う可能性は低いものの、調べながら作業を進め、得た情報を試行錯誤しながらコードに組み込む、という機会は多いと予想される。その点で有意義な経験だった。