予め正しい答えを全て配列の0に入れておき、click functionで正しいか正誤判定しています。選択肢はシャッフルして表示し、最後に、正解率を表示させています。
reference
Autoloading Classes:The spl_autoload_register() function registers any number of autoloaders, enabling for classes and interfaces to be automatically loaded if they are currently not defined. By registering autoloaders, PHP is given a last chance to load the class or interface before it fails with an error.
index.php
<?php require_once(__DIR__ . '/config.php'); $quiz = new MyApp\Quiz(); if(!$quiz->isFinished()) { $data = $quiz->getCurrentQuiz(); shuffle($data['a']); } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Intractive Art</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles.css"> </head> <body> <?php if ($quiz->isFinished()) : ?> <div id="container"> <div id="result"> your score ... <div><?= h($quiz->getScore()); ?>%</div> </div> <a href=""><div id="btn">Replay</div></a> </div> <?php $quiz->reset(); ?> <?php else : ?> <div id="container"> <h1>Q. <?= h($data['q']); ?></h1> <ul> <?php foreach ($data['a'] as $a) : ?> <li class="answer"><?= h($a); ?></li> <!-- <li class="answer">A1</li> <li class="answer">A2</li> <li class="answer">A3</li> --> <?php endforeach; ?> </ul> <div id="btn" class="disabled"><?= $quiz->isLast() ? 'Show Result' : 'Next Question'; ?></div> <input type="hidden" id="token" value="<?= h($_SESSION['token']); ?>"> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script src="quiz.js"></script> <?php endif; ?> </body> </html>
autoload.php
<?php spl_autoload_register(function($class){ $prefix = 'MyApp\\'; if (strpos($class, $prefix) === 0){ $className = substr($class, strlen($prefix)); $classFilePath = __DIR__ . '/' . $className . '.php'; if (file_exists($classFilePath)){ require $classFilePath; } else { echo 'No such class' . $className; exit; } } }); [/php] _answer.php [php] <?php require_once(__DIR__ . '/config.php'); $quiz = new MyApp\Quiz(); try{ $correctAnswer = $quiz->checkAnswer(); } catch (Exception $e) { header($_SERVER['SERVER_PROTOCOL']. ' 403 Forbidden', true, 403); echo $e->getMessage(); exit; } header('Content-Type: application/json; charset=UTF-8'); echo json_encode([ 'correct_answer' => $correctAnswer ]);
Token.php
<?php require_once(__DIR__ . '/config.php'); $quiz = new MyApp\Quiz(); try{ $correctAnswer = $quiz->checkAnswer(); } catch (Exception $e) { header($_SERVER['SERVER_PROTOCOL']. ' 403 Forbidden', true, 403); echo $e->getMessage(); exit; } header('Content-Type: application/json; charset=UTF-8'); echo json_encode([ 'correct_answer' => $correctAnswer ]);
Quiz.php
<?php namespace MyApp; class Quiz{ private $_quizSet = []; public function __construct(){ $this->_setup(); Token::create(); if(!isset($_SESSION['current_num'])){ $this->_initSession(); } } public function checkAnswer(){ Token::validate('token'); $correctAnswer = $this->_quizSet[$_SESSION['current_num']]['a'][0]; if (!isset($_POST['answer'])){ throw new \Exception('answer not set!'); } if($correctAnswer === $_POST['answer']){ $_SESSION['correct_count']++; } $_SESSION['current_num']++; return $correctAnswer; } public function isFinished(){ return count($this->_quizSet) === $_SESSION['current_num']; } public function getScore() { return round($_SESSION['correct_count'] / count($this->_quizSet) * 100); } public function isLast(){ return count($this->_quizSet) === $_SESSION['current_num'] + 1; } public function reset(){ $this->_initSession(); // $_SESSION['current_num'] = 0; // $_SESSION['correct_count'] = 0; } private function _initSession(){ $_SESSION['current_num'] = 0; $_SESSION['correct_count'] = 0; } public function getCurrentQuiz() { return $this->_quizSet[$_SESSION['current_num']]; } private function _setup(){ $this->_quizSet[] = [ 'q' => '1543年は、ある物が日本に伝えられた年でもある。それは何か?', 'a' => ['鉄砲', 'キリスト教', '貿易', '忍法'] ]; $this->_quizSet[] = [ 'q' => '海上交通の要地に作られた港町で有名なのはどこ?', 'a' => ['堺', '伊丹', '京都', '江戸'] ]; $this->_quizSet[] = [ 'q' => '1639年に鎖国は完成する。この年から、来航を禁止された国はどこ?', 'a' => ['ポルトガル', 'イギリス', '清', 'オランダ'] ]; } }
config.php
quiz.js
$(function() { 'use strict'; $('.answer').on('click', function() { var $selected = $(this); if ($selected.hasClass('correct') || $selected.hasClass('wrong')) { return; } $selected.addClass('selected'); var answer = $selected.text(); $.post('/_answer.php', { answer: answer, token: $('#token').val() }).done(function(res) { $('.answer').each(function() { if ($(this).text() === res.correct_answer) { $(this).addClass('correct'); } else { $(this).addClass('wrong'); } }); // alert(res.correct_answer); if (answer === res.correct_answer) { // correct! $selected.text(answer + ' ... CORRECT!'); } else { // wrong! $selected.text(answer + ' ... WRONG!'); } $('#btn').removeClass('disabled'); }); }); $('#btn').on('click', function() { if (!$(this).hasClass('disabled')) { location.reload(); } }); });
body { font-size: 16px; font-family: Arial, sans-serif; } #container { width: 500px; margin: 15px auto; } h1, ul > li { border: 1px solid #ddd; border-radius: 5px; } h1 { padding: 10px; height: 50px; font-size: 18px; margin: 0 0 10px; } ul { list-style: none; margin: 0 0 10px; padding: 0; } ul > li { margin-bottom: 7px; padding: 7px 10px; cursor: pointer; } #btn { text-align: center; float: right; width: 100px; padding: 7px; color: #fff; border-radius: 5px; background: #00aaff; box-shadow: 0 4px 0 #0088cc; cursor: pointer; font-size: 14px; } #btn.disabled { opacity: 0.5; } .correct{ color: limegreen; font-weight: bold; } .wrong { color: #ddd; } .selected { font-weight: bold; } #result { border: 1px solid #ddd; border-radius: 5px; margin-bottom: 15px; text-align: center; padding: 30px 0 50px; } #result > div { font-size: 64px; font-weight: bold; margin-top: 30px; }