PHPで簡単にランダム選択問題を出す仕組みを作る。

2019年09月25日 正午の月齢:26.1  月名:二十七日月  潮汐:中潮 月齢:26.1[二十七日月] 潮汐:中潮 (最終更新日:2019年09月26日)
3か月前に投稿 | ウェブ・IT関係 | コメントはありません

10分ぐらいで読めます。

先日、PHPでランダム選択問題を出す仕組みを作ってみたのですが、やっぱりというか、問題ごとにファイルを作るのがとてもめんどくさい…。

というわけで、もう少し実用的なものにすることにしました。構成としては「出題のファイル」「答え合わせのファイル」「スタイルシート」「問題・選択肢・正答・画像パスのCSV」という4枚で収めようと思います。

まずは「出題のファイル」question.php。

<!DOCTYPE html>

<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<link rel="stylesheet" href="style.css">
<title>問題</title>
</head>

<body>

<?php
$data = 'quiz.csv'; //データのファイル("で囲んでいないCSV形式)
$random = file_exists($data); //ファイル存在の確認
$link = $random ?file($data) : array();//配列に格納
$link = mb_convert_encoding($link, 'UTF-8', 'sjis-win'); //文字のエンコード
$rand_c = count($link); //行数のカウント
$rand_c = $rand_c - 1; //配列番号化のためマイナス1
$r = rand(0, $rand_c); //行番号をランダムに取得
$q_data = $link[$r]; //設問の取得
$q = explode(",", $q_data); //配列の展開
$question = array_slice($q,0,1); //問題文の分離
$i_data = array_slice($q,0,2); //イメージファイルパスの分離
$img = $i_data[1]; //イメージファイルパス
$query = $question[0]; //問題文
$choices = array_slice($q,2); //選択肢
$answer = $choices[0]; //正しい回答
shuffle($choices); //選択肢をランダムにする
?>

<div class="question">
<p><?php echo $query ?></p>
</div>

<div class="image">
<p><img src="<?php echo $img ?>"></p>
</div>

<div class="answer">
<form method="POST" action="answer.php">
<?php foreach($choices as $value){ ?>

<ul>
<li><input class="choices" type="radio" name="choices" value="<?php echo $value; ?>"><?php echo $value; ?></li>
<?php } ?>
</ul>

<input class="dummychoices" type="radio" name="choices" value="none" checked="checked" style="display:none;">
<input class="answer" type="hidden" name="answer" value="<?php echo $answer ?>">
<p><input class="send" type="submit" value="解答する"></p>
</form>
</div>

</body>

</html>

配列をぶった切ってコネコネしているだけですがあまりかっこよくないソースコードですねー。ま、とりあえずこれで動きます。出題順序と選択肢の並び方をランダムに変えます。

「答え合わせのファイル」answer.php。

<!DOCTYPE html>

<html>

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<link rel="stylesheet" href="style.css">
<title>結果判定</title>
</head>

<body>

<?php
$choices = $_POST['choices'];
$answer = $_POST['answer'];
if($choices == $answer){
$result = "<span class=\"ok\">正解</span>";
}elseif($choices == 'none'){
$result = "<span class=\"xx\">無回答</span>";
}else{
$result = "<span class=\"ng\">不正解</span>";
}
?>

<div class="answer">
<p class="result"><?php echo $result ?></p>
<p class="next"><a href="question.php" class="send">次の問題へ</a></p>
</div>

</body>
</html>

正解・不正解・無回答を判定し、次の問題へのリンクを表示します。取りあえず使えますが、もう少しマシなデザインにした方がいいですね。

「スタイルシート」style.css。

* {
margin: 0px;
padding: 0px;
list-style-type: none;
text-decoration:none;
font-size: 100%;
font-weight: normal;
text-decoration: none;
font-family: 'メイリオ', Meiryo, 'Hiragino Kaku Gothic ProN', 'ヒラギノ角ゴ ProN W3', Helvetica, Arial, sans-serif;
color: #000000;
letter-spacing: 0.1em;
word-wrap : break-word;
overflow-wrap : break-word;
}

html {
overflow-y: scroll;
}

body {
margin: 15px;
}

button, input, select, textarea, code, pre {
font-family: inherit !important;
border: none;
}

.send {
background-color: #666666;
margin: 10px;
padding: 10px;
color: #ffffff;
}

.send:hover {
background-color: #cccccc;
color: #000000;
}

img {
max-height: 150px;
}

.ok {
font-size: 300%;
color: #FF0000;
}

.ng {
font-size: 300%;
color: #0000ff;
}

.xx {
font-size: 300%;
color: #cccccc;
}

li {
margin: 15px;
}

input {
margin-top: 15px;
margin-bottom: 15px;
}

これも実際に使うときにはもう少しちゃんとしたデザインにしてあげた方がいいかも。とりあえず動かすのが目的ということで。

最後に「問題・選択肢・正答・画像パスのCSV」quiz.csv。

太陽に最も近い惑星は。,,水星,金星,火星,木星,土星
仕事を継続的に改善していくサイクルの名前は。,,PDCA,ABCD,CMYK,YMCA,PPAP,CFRP
この暗号通貨の単位は。,https://susu.cc/wp-content/uploads/2018/05/nem-150x150.png,XEM,XRP,BTC,MONA
ガルウイングが特徴のこの自動車の名前は。,https://susu.cc/sera/hassy_org/w-white.jpg,セラ,アヴェンタドール,AZ-1,エクリプス
この列車の名前は。,https://susu.cc/wp-content/uploads/2019/08/pea_009-600x338.jpg,パノラマエクスプレスアルプス,スーパーエクスプレスレインボー,パノラマライナーサザンクロス,アルファコンチネンタルエクスプレス

Shift-JISのCSV。1列目が問題文・2列目が画像ファイルのパス・3列目が正しい答えの選択肢・4列目以降が誤った選択肢。CSVをうまく扱える関数を実装したら、ダブルクォーテーション付きのデータもそつなく扱えるでしょうけど、このままでも使えます。

問題数が少ないと、同じ問題が何度も続けて出てくることもありますが、選択肢の順番が毎回違うので少しは練習になるかな。

というわけで、これを使ってあの資格とあの資格の勉強を頑張ります。頑張る予定です、たぶん。

古い記事・新しい記事

古い記事
新しい記事

コメントはありません »

[RSS on this post] [TrackBack URI]

コメントをどうぞ

Translate »