Proje Detayları
Proje Tanımı
Bu projede, JavaScript kullanarak interaktif bir quiz uygulaması geliştireceğiz. Uygulama, farklı kategorilerde sorular sunacak, kullanıcının cevaplarını değerlendirecek ve sonuçları gösterecek. Bu proje, DOM manipülasyonu, olay yönetimi, zamanlayıcılar ve veri yapıları konularını uygulamalı olarak öğrenmenize yardımcı olacak.
Adım Adım Geliştirme
Bu bölümde, quiz uygulamasını adım adım nasıl geliştirebileceğinizi öğreneceksiniz. Her adımda, ilgili kod parçalarını ve açıklamalarını bulacaksınız.
Adım 1: Proje Yapısını Oluşturma
İlk olarak, projemiz için gerekli dosyaları oluşturalım:
index.html
- Ana HTML dosyasıstyle.css
- CSS stil dosyasıscript.js
- JavaScript kod dosyasıquestions.js
- Soru veritabanı dosyası
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quiz Uygulaması</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
<div class="quiz-app">
<div class="quiz-header">
<h2>JavaScript Quiz Uygulaması</h2>
</div>
<div class="quiz-container">
<div class="quiz-info">
<h3>Bilgi Yarışması</h3>
<p>Bilgilerinizi test edin ve eğlenin!</p>
</div>
<div class="quiz-start-screen" id="quizStartScreen">
<p>Bir kategori seçin ve başlayın:</p>
<select id="categorySelect">
<option value="genel">Genel Kültür</option>
<option value="bilim">Bilim ve Teknoloji</option>
<option value="tarih">Tarih</option>
<option value="spor">Spor</option>
<option value="sanat">Sanat ve Edebiyat</option>
</select>
<button class="quiz-button primary" id="startButton">Başla</button>
</div>
<div class="quiz-question" id="quizQuestion">
<div class="question-number" id="questionNumber"></div>
<div class="question-text" id="questionText"></div>
<ul class="quiz-options" id="quizOptions"></ul>
<div class="quiz-controls">
<button class="quiz-button secondary" id="prevButton">Önceki</button>
<button class="quiz-button primary" id="nextButton">Sonraki</button>
</div>
<div class="quiz-progress">
<div class="quiz-progress-bar" id="progressBar"></div>
</div>
</div>
<div class="quiz-results" id="quizResults">
<div class="results-title">Quiz Tamamlandı!</div>
<div class="results-score" id="resultsScore"></div>
<div class="results-message" id="resultsMessage"></div>
<div class="results-stats">
<div class="stat-item">
<div class="stat-value" id="correctAnswers"></div>
<div class="stat-label">Doğru</div>
</div>
<div class="stat-item">
<div class="stat-value" id="wrongAnswers"></div>
<div class="stat-label">Yanlış</div>
</div>
<div class="stat-item">
<div class="stat-value" id="timeSpent"></div>
<div class="stat-label">Süre</div>
</div>
</div>
<button class="quiz-button primary" id="restartButton">Yeniden Başla</button>
</div>
</div>
</div>
<script src="questions.js"></script>
<script src="script.js"></script>
</body>
</html>
/* Genel Stiller */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f0f2f5;
color: #333;
line-height: 1.6;
padding: 20px;
}
/* Quiz Uygulaması Stilleri */
.quiz-app {
max-width: 700px;
margin: 0 auto;
}
.quiz-header {
text-align: center;
margin-bottom: 20px;
}
.quiz-header h2 {
color: #333;
margin-bottom: 10px;
}
.quiz-container {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
overflow: hidden;
position: relative;
}
.quiz-info {
background-color: #4caf50;
color: white;
padding: 20px;
text-align: center;
}
.quiz-info h3 {
margin: 0;
font-size: 1.5rem;
}
.quiz-info p {
margin: 10px 0 0;
font-size: 0.9rem;
opacity: 0.9;
}
.quiz-start-screen {
padding: 30px;
text-align: center;
}
.quiz-start-screen p {
margin-bottom: 20px;
font-size: 1.1rem;
color: #555;
}
.quiz-start-screen select {
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
margin-bottom: 20px;
width: 100%;
max-width: 300px;
}
.quiz-question {
padding: 30px;
display: none;
}
.question-number {
font-size: 0.9rem;
color: #666;
margin-bottom: 10px;
}
.question-text {
font-size: 1.3rem;
font-weight: bold;
margin-bottom: 20px;
color: #333;
}
.quiz-options {
list-style-type: none;
padding: 0;
}
.quiz-option {
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
margin-bottom: 10px;
cursor: pointer;
transition: background-color 0.3s;
}
.quiz-option:hover {
background-color: #f0f0f0;
}
.quiz-option.selected {
background-color: #e3f2fd;
border-color: #2196f3;
}
.quiz-option.correct {
background-color: #e8f5e9;
border-color: #4caf50;
}
.quiz-option.wrong {
background-color: #ffebee;
border-color: #f44336;
}
.quiz-controls {
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.quiz-button {
padding: 10px 20px;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
.quiz-button.primary {
background-color: #4caf50;
color: white;
}
.quiz-button.primary:hover {
background-color: #45a049;
}
.quiz-button.secondary {
background-color: #f5f5f5;
color: #333;
}
.quiz-button.secondary:hover {
background-color: #e0e0e0;
}
.quiz-button:disabled {
background-color: #cccccc;
color: #666;
cursor: not-allowed;
}
.quiz-results {
padding: 30px;
text-align: center;
display: none;
}
.results-title {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 10px;
color: #333;
}
.results-score {
font-size: 2.5rem;
font-weight: bold;
margin: 20px 0;
color: #4caf50;
}
.results-message {
font-size: 1.1rem;
margin-bottom: 20px;
color: #555;
}
.results-stats {
display: flex;
justify-content: center;
margin-bottom: 30px;
}
.stat-item {
text-align: center;
margin: 0 15px;
}
.stat-value {
font-size: 1.5rem;
font-weight: bold;
color: #333;
}
.stat-label {
font-size: 0.9rem;
color: #666;
}
.quiz-timer {
position: absolute;
top: 20px;
right: 20px;
background-color: rgba(255, 255, 255, 0.8);
padding: 5px 10px;
border-radius: 20px;
font-size: 0.9rem;
color: #333;
}
.quiz-progress {
height: 5px;
background-color: #e0e0e0;
margin-top: 20px;
border-radius: 5px;
overflow: hidden;
}
.quiz-progress-bar {
height: 100%;
background-color: #4caf50;
width: 0;
transition: width 0.3s;
}
/* Responsive Tasarım */
@media (max-width: 768px) {
.quiz-container {
border-radius: 0;
}
.quiz-question {
padding: 20px;
}
.question-text {
font-size: 1.1rem;
}
.quiz-option {
padding: 12px;
}
.results-stats {
flex-direction: column;
gap: 15px;
}
}
Adım 2: Soru Veritabanını Oluşturma
Şimdi, quiz uygulaması için soru veritabanını oluşturalım. Bu, farklı kategorilerde soruları içeren bir JavaScript dosyası olacak:
// Soru veritabanı
const quizQuestions = {
// Genel Kültür Soruları
genel: [
{
question: "Türkiye'nin başkenti hangi şehirdir?",
options: ["İstanbul", "Ankara", "İzmir", "Bursa"],
answer: 1
},
{
question: "Dünyanın en büyük okyanusu hangisidir?",
options: ["Atlantik Okyanusu", "Hint Okyanusu", "Pasifik Okyanusu", "Arktik Okyanusu"],
answer: 2
},
{
question: "Hangi gezegen Güneş Sistemi'nde en büyüktür?",
options: ["Mars", "Venüs", "Dünya", "Jüpiter"],
answer: 3
},
{
question: "İnsan vücudundaki en büyük organ hangisidir?",
options: ["Kalp", "Beyin", "Deri", "Karaciğer"],
answer: 2
},
{
question: "Hangi ülke dünyanın en kalabalık nüfusuna sahiptir?",
options: ["Hindistan", "ABD", "Çin", "Endonezya"],
answer: 2
},
{
question: "Hangi element periyodik tabloda 'Fe' sembolü ile gösterilir?",
options: ["Flor", "Demir", "Fosfor", "Fermiyum"],
answer: 1
},
{
question: "Bir yıl kaç saniyedir?",
options: ["31,536,000", "86,400", "525,600", "3,600"],
answer: 0
},
{
question: "Hangi hayvan uçabilen tek memelidir?",
options: ["Penguen", "Yarasa", "Sincap", "Kanguru"],
answer: 1
},
{
question: "Hangi renk gökkuşağında bulunmaz?",
options: ["Mor", "Siyah", "Yeşil", "Turuncu"],
answer: 1
},
{
question: "Dünya'nın en uzun nehri hangisidir?",
options: ["Amazon Nehri", "Nil Nehri", "Yangtze Nehri", "Mississippi Nehri"],
answer: 1
}
],
// Bilim ve Teknoloji Soruları
bilim: [
{
question: "Işık hızı yaklaşık olarak kaç km/saniyedir?",
options: ["150,000 km/s", "300,000 km/s", "500,000 km/s", "1,000,000 km/s"],
answer: 1
},
{
question: "Hangi bilim insanı Görelilik Teorisi'ni geliştirmiştir?",
options: ["Isaac Newton", "Nikola Tesla", "Albert Einstein", "Stephen Hawking"],
answer: 2
},
{
question: "DNA'nın açılımı nedir?",
options: ["Deoksiribonükleik Asit", "Dinamik Nükleik Asit", "Deoksiriboz Nükleik Asit", "Dinamik Nükleotid Asit"],
answer: 0
},
{
question: "Hangi gezegen Güneş'e en yakındır?",
options: ["Venüs", "Mars", "Merkür", "Dünya"],
answer: 2
},
{
question: "Hangi element periyodik tabloda en yaygın olanıdır?",
options: ["Oksijen", "Karbon", "Hidrojen", "Demir"],
answer: 2
},
{
question: "İlk kişisel bilgisayar hangi şirket tarafından üretilmiştir?",
options: ["IBM", "Apple", "Microsoft", "Intel"],
answer: 1
},
{
question: "Hangi bilim dalı canlıları inceler?",
options: ["Fizik", "Kimya", "Biyoloji", "Jeoloji"],
answer: 2
},
{
question: "Hangi vitamin eksikliği skorbüt hastalığına neden olur?",
options: ["A Vitamini", "B Vitamini", "C Vitamini", "D Vitamini"],
answer: 2
},
{
question: "Hangi gezegen 'Kızıl Gezegen' olarak bilinir?",
options: ["Jüpiter", "Mars", "Venüs", "Satürn"],
answer: 1
},
{
question: "İnternet'in temelini oluşturan ağ protokolü hangisidir?",
options: ["HTTP", "FTP", "TCP/IP", "SMTP"],
answer: 2
}
],
// Tarih Soruları
tarih: [
{
question: "İstanbul'un fethi hangi yılda gerçekleşmiştir?",
options: ["1453", "1299", "1517", "1683"],
answer: 0
},
{
question: "I. Dünya Savaşı hangi yıllar arasında gerçekleşmiştir?",
options: ["1905-1910", "1914-1918", "1939-1945", "1922-1927"],
answer: 1
},
{
question: "Türkiye Cumhuriyeti hangi tarihte ilan edilmiştir?",
options: ["29 Ekim 1920", "23 Nisan 1920", "29 Ekim 1923", "30 Ağustos 1922"],
answer: 2
},
{
question: "Amerika'yı keşfeden denizci kimdir?",
options: ["Vasco da Gama", "Ferdinand Magellan", "Kristof Kolomb", "James Cook"],
answer: 2
},
{
question: "Fransız Devrimi hangi yılda başlamıştır?",
options: ["1789", "1804", "1776", "1815"],
answer: 0
},
{
question: "Osmanlı İmparatorluğu'nun kurucusu kimdir?",
options: ["Fatih Sultan Mehmet", "Yavuz Sultan Selim", "Osman Bey", "Kanuni Sultan Süleyman"],
answer: 2
},
{
question: "Hangi antik uygarlık piramitleri inşa etmiştir?",
options: ["Yunan", "Roma", "Mısır", "Çin"],
answer: 2
},
{
question: "II. Dünya Savaşı hangi yılda sona ermiştir?",
options: ["1943", "1944", "1945", "1946"],
answer: 2
},
{
question: "Magna Carta hangi ülkede imzalanmıştır?",
options: ["Fransa", "İngiltere", "İtalya", "Almanya"],
answer: 1
},
{
question: "Hangi Türk lider 'Atatürk' soyadını almıştır?",
options: ["İsmet İnönü", "Mustafa Kemal", "Fevzi Çakmak", "Kazım Karabekir"],
answer: 1
}
],
// Spor Soruları
spor: [
{
question: "Bir futbol maçında her takımda kaç oyuncu bulunur?",
options: ["9", "10", "11", "12"],
answer: 2
},
{
question: "Hangi spor dalında 'Grand Slam' turnuvaları düzenlenir?",
options: ["Golf", "Tenis", "Futbol", "Basketbol"],
answer: 1
},
{
question: "Olimpiyat bayrağında kaç halka vardır?",
options: ["4", "5", "6", "7"],
answer: 1
},
{
question: "Bir basketbol potasının yerden yüksekliği kaç metredir?",
options: ["2.74 m", "3.05 m", "3.25 m", "3.50 m"],
answer: 1
},
{
question: "Hangi ülke futbolda en çok Dünya Kupası kazanmıştır?",
options: ["Almanya", "İtalya", "Arjantin", "Brezilya"],
answer: 3
},
{
question: "Bir maraton yarışı kaç kilometredir?",
options: ["36.5 km", "40.2 km", "42.195 km", "45 km"],
answer: 2
},
{
question: "Hangi spor dalında 'hat-trick' terimi kullanılır?",
options: ["Basketbol", "Futbol", "Voleybol", "Tenis"],
answer: 1
},
{
question: "Formula 1 yarışlarında bir pilot hangi bayrağı gördüğünde yarışı bırakmalıdır?",
options: ["Kırmızı", "Sarı", "Siyah", "Mavi"],
answer: 2
},
{
question: "Bir voleybol takımında kaç oyuncu sahada bulunur?",
options: ["5", "6", "7", "8"],
answer: 1
},
{
question: "Hangi spor dalında 'birdie', 'eagle' ve 'bogey' terimleri kullanılır?",
options: ["Tenis", "Golf", "Kriket", "Beyzbol"],
answer: 1
}
],
// Sanat ve Edebiyat Soruları
sanat: [
{
question: "Mona Lisa tablosunun ressamı kimdir?",
options: ["Vincent van Gogh", "Pablo Picasso", "Leonardo da Vinci", "Michelangelo"],
answer: 2
},
{
question: "Hangi yazar 'Suç ve Ceza' romanını yazmıştır?",
options: ["Leo Tolstoy", "Fyodor Dostoyevski", "Anton Çehov", "Franz Kafka"],
answer: 1
},
{
question: "Hangi müzik türü 1950'lerde ABD'de ortaya çıkmıştır?",
options: ["Jazz", "Rock and Roll", "Hip Hop", "Elektronik"],
answer: 1
},
{
question: "'Guernica' tablosu hangi ressama aittir?",
options: ["Salvador Dali", "Pablo Picasso", "Claude Monet", "Frida Kahlo"],
answer: 1
},
{
question: "Hangi yazar 'Romeo ve Juliet' oyununu yazmıştır?",
options: ["Charles Dickens", "Jane Austen", "William Shakespeare", "Oscar Wilde"],
answer: 2
},
{
question: "Hangi müzik aleti yaylı çalgılar ailesine aittir?",
options: ["Flüt", "Piyano", "Keman", "Trompet"],
answer: 2
},
{
question: "'Yüzüklerin Efendisi' serisinin yazarı kimdir?",
options: ["J.K. Rowling", "J.R.R. Tolkien", "George R.R. Martin", "C.S. Lewis"],
answer: 1
},
{
question: "Hangi sanat akımı 'gerçeküstücülük' olarak bilinir?",
options: ["Empresyonizm", "Kübizm", "Sürrealizm", "Ekspresyonizm"],
answer: 2
},
{
question: "Hangi Türk yazar 'İnce Memed' romanını yazmıştır?",
options: ["Orhan Pamuk", "Yaşar Kemal", "Nazım Hikmet", "Sabahattin Ali"],
answer: 1
},
{
question: "Sistine Şapeli'nin tavanını kim resimlemiştir?",
options: ["Leonardo da Vinci", "Raphael", "Michelangelo", "Donatello"],
answer: 2
}
]
};
Adım 3: JavaScript Kodunu Yazma
Şimdi, uygulamanın işlevselliğini sağlayacak JavaScript kodunu yazalım:
// DOM elementlerini seçme
const quizStartScreen = document.getElementById('quizStartScreen');
const quizQuestion = document.getElementById('quizQuestion');
const quizResults = document.getElementById('quizResults');
const categorySelect = document.getElementById('categorySelect');
const startButton = document.getElementById('startButton');
const questionNumber = document.getElementById('questionNumber');
const questionText = document.getElementById('questionText');
const quizOptions = document.getElementById('quizOptions');
const prevButton = document.getElementById('prevButton');
const nextButton = document.getElementById('nextButton');
const progressBar = document.getElementById('progressBar');
const resultsScore = document.getElementById('resultsScore');
const resultsMessage = document.getElementById('resultsMessage');
const correctAnswers = document.getElementById('correctAnswers');
const wrongAnswers = document.getElementById('wrongAnswers');
const timeSpent = document.getElementById('timeSpent');
const restartButton = document.getElementById('restartButton');
// Quiz durumu
let currentQuestions = [];
let currentQuestionIndex = 0;
let userAnswers = [];
let startTime;
let timerInterval;
let quizTimer;
// Sayfa yüklendiğinde
document.addEventListener('DOMContentLoaded', () => {
// Başlat butonuna tıklama olayı
startButton.addEventListener('click', startQuiz);
// Önceki butonu olayı
prevButton.addEventListener('click', showPreviousQuestion);
// Sonraki butonu olayı
nextButton.addEventListener('click', () => {
// Eğer son soru ise, quizi bitir
if (currentQuestionIndex === currentQuestions.length - 1) {
finishQuiz();
} else {
// Değilse, sonraki soruya geç
showNextQuestion();
}
});
// Yeniden başlat butonu olayı
restartButton.addEventListener('click', () => {
// Quiz başlangıç ekranını göster
quizResults.style.display = 'none';
quizStartScreen.style.display = 'block';
});
});
// Quiz'i başlatma fonksiyonu
function startQuiz() {
// Seçilen kategoriyi al
const selectedCategory = categorySelect.value;
// Seçilen kategorideki soruları al
currentQuestions = quizQuestions[selectedCategory];
// Soruları karıştır
shuffleArray(currentQuestions);
// İlk 10 soruyu al (veya daha az varsa tümünü)
currentQuestions = currentQuestions.slice(0, 10);
// Quiz durumunu sıfırla
currentQuestionIndex = 0;
userAnswers = Array(currentQuestions.length).fill(null);
// Başlangıç ekranını gizle, soru ekranını göster
quizStartScreen.style.display = 'none';
quizQuestion.style.display = 'block';
// İlk soruyu göster
showQuestion(0);
// Zamanlayıcıyı başlat
startTime = new Date();
// Zamanlayıcı elementi oluştur
if (!quizTimer) {
quizTimer = document.createElement('div');
quizTimer.className = 'quiz-timer';
document.querySelector('.quiz-container').appendChild(quizTimer);
}
// Zamanlayıcıyı güncelle
updateTimer();
timerInterval = setInterval(updateTimer, 1000);
}
// Soruyu gösterme fonksiyonu
function showQuestion(index) {
// Geçerli soru indeksini güncelle
currentQuestionIndex = index;
// Soru numarasını güncelle
questionNumber.textContent = `Soru ${index + 1}/${currentQuestions.length}`;
// Soru metnini güncelle
questionText.textContent = currentQuestions[index].question;
// Seçenekleri temizle
quizOptions.innerHTML = '';
// Seçenekleri ekle
currentQuestions[index].options.forEach((option, i) => {
const li = document.createElement('li');
li.className = 'quiz-option';
li.textContent = `${String.fromCharCode(65 + i)}) ${option}`;
// Kullanıcı daha önce bu seçeneği seçtiyse, seçili olarak işaretle
if (userAnswers[index] === i) {
li.classList.add('selected');
}
// Seçeneğe tıklama olayı
li.addEventListener('click', () => {
// Tüm seçeneklerden 'selected' sınıfını kaldır
document.querySelectorAll('.quiz-option').forEach(opt => {
opt.classList.remove('selected');
});
// Seçilen seçeneğe 'selected' sınıfını ekle
li.classList.add('selected');
// Kullanıcının cevabını kaydet
userAnswers[index] = i;
// Sonraki butonunu etkinleştir
nextButton.disabled = false;
});
quizOptions.appendChild(li);
});
// Önceki ve sonraki butonlarını güncelle
prevButton.disabled = index === 0;
nextButton.disabled = userAnswers[index] === null;
// Son soru ise, sonraki butonunun metnini değiştir
if (index === currentQuestions.length - 1) {
nextButton.textContent = 'Bitir';
} else {
nextButton.textContent = 'Sonraki';
}
// İlerleme çubuğunu güncelle
updateProgressBar();
}
// Önceki soruyu gösterme fonksiyonu
function showPreviousQuestion() {
if (currentQuestionIndex > 0) {
showQuestion(currentQuestionIndex - 1);
}
}
// Sonraki soruyu gösterme fonksiyonu
function showNextQuestion() {
if (currentQuestionIndex < currentQuestions.length - 1) {
showQuestion(currentQuestionIndex + 1);
}
}
// Quiz'i bitirme fonksiyonu
function finishQuiz() {
// Zamanlayıcıyı durdur
clearInterval(timerInterval);
// Soru ekranını gizle, sonuç ekranını göster
quizQuestion.style.display = 'none';
quizResults.style.display = 'block';
// Doğru cevap sayısını hesapla
const correct = userAnswers.reduce((count, answer, index) => {
return count + (answer === currentQuestions[index].answer ? 1 : 0);
}, 0);
// Yanlış cevap sayısını hesapla
const wrong = currentQuestions.length - correct;
// Sonuç metnini güncelle
resultsScore.textContent = `${correct}/${currentQuestions.length}`;
// Doğru ve yanlış sayılarını güncelle
correctAnswers.textContent = correct;
wrongAnswers.textContent = wrong;
// Geçen süreyi hesapla
const endTime = new Date();
const timeDiff = Math.floor((endTime - startTime) / 1000); // saniye cinsinden
const minutes = Math.floor(timeDiff / 60);
const seconds = timeDiff % 60;
timeSpent.textContent = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
// Sonuç mesajını güncelle
if (correct === currentQuestions.length) {
resultsMessage.textContent = 'Mükemmel! Tüm soruları doğru cevapladınız.';
} else if (correct >= currentQuestions.length * 0.7) {
resultsMessage.textContent = 'Tebrikler! Harika bir performans gösterdiniz.';
} else if (correct >= currentQuestions.length * 0.5) {
resultsMessage.textContent = 'İyi iş! Yarıdan fazla soruyu doğru cevapladınız.';
} else {
resultsMessage.textContent = 'Daha fazla pratik yaparak gelişebilirsiniz.';
}
// Zamanlayıcıyı kaldır
if (quizTimer) {
quizTimer.remove();
quizTimer = null;
}
// Sonuçları localStorage'a kaydet
saveQuizResults(categorySelect.value, correct, currentQuestions.length, timeDiff);
}
// İlerleme çubuğunu güncelleme fonksiyonu
function updateProgressBar() {
const progress = ((currentQuestionIndex + 1) / currentQuestions.length) * 100;
progressBar.style.width = `${progress}%`;
}
// Zamanlayıcıyı güncelleme fonksiyonu
function updateTimer() {
const currentTime = new Date();
const timeDiff = Math.floor((currentTime - startTime) / 1000); // saniye cinsinden
const minutes = Math.floor(timeDiff / 60);
const seconds = timeDiff % 60;
quizTimer.textContent = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
}
// Diziyi karıştırma fonksiyonu (Fisher-Yates algoritması)
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
// Quiz sonuçlarını kaydetme fonksiyonu
function saveQuizResults(category, correct, total, time) {
// Önceki sonuçları al
let quizHistory = JSON.parse(localStorage.getItem('quizHistory')) || [];
// Yeni sonucu ekle
quizHistory.push({
category,
correct,
total,
time,
date: new Date().toISOString()
});
// En fazla 10 sonuç sakla
if (quizHistory.length > 10) {
quizHistory = quizHistory.slice(-10);
}
// Sonuçları kaydet
localStorage.setItem('quizHistory', JSON.stringify(quizHistory));
}
Adım 4: Uygulamayı Test Etme
Şimdi uygulamanızı test etme zamanı! Aşağıdaki adımları izleyin:
- Tüm dosyaları (
index.html
,style.css
,script.js
,questions.js
) aynı klasöre kaydedin. - HTML dosyasını bir web tarayıcısında açın.
- Bir kategori seçin ve "Başla" butonuna tıklayın.
- Soruları cevaplayın ve ilerleyin.
- Quiz'i tamamladıktan sonra sonuçlarınızı görün.
İpucu: Uygulamanızı test ederken, farklı tarayıcılarda ve cihazlarda (masaüstü, tablet, mobil) nasıl göründüğünü kontrol edin. Responsive tasarımın doğru çalıştığından emin olun.
Projeyi Geliştirme
Temel quiz uygulamasını başarıyla oluşturduktan sonra, aşağıdaki özelliklerle projenizi geliştirebilirsiniz:
1. Soru Süresi Sınırlaması
Her soru için bir süre sınırlaması ekleyebilirsiniz. Süre dolduğunda, otomatik olarak sonraki soruya geçilebilir veya cevap verilemez hale getirilebilir:
// Soru zamanlayıcısı için değişkenler
let questionTimer;
let questionTimeLeft;
const QUESTION_TIME = 20; // Her soru için 20 saniye
// Soru zamanlayıcısı elementi oluştur
const questionTimerElement = document.createElement('div');
questionTimerElement.className = 'question-timer';
quizQuestion.appendChild(questionTimerElement);
// Soruyu gösterme fonksiyonunu güncelle
function showQuestion(index) {
// ... mevcut kod ...
// Önceki zamanlayıcıyı temizle
if (questionTimer) {
clearInterval(questionTimer);
}
// Soru zamanlayıcısını başlat
startQuestionTimer();
// ... mevcut kod ...
}
// Soru zamanlayıcısını başlatma fonksiyonu
function startQuestionTimer() {
questionTimeLeft = QUESTION_TIME;
updateQuestionTimer();
questionTimer = setInterval(() => {
questionTimeLeft--;
updateQuestionTimer();
if (questionTimeLeft <= 0) {
// Zamanlayıcıyı durdur
clearInterval(questionTimer);
// Süre dolduğunda yapılacak işlem
if (userAnswers[currentQuestionIndex] === null) {
// Kullanıcı cevap vermediyse, otomatik olarak boş bırak
userAnswers[currentQuestionIndex] = -1; // -1, cevap verilmedi anlamında
}
// Son soru değilse, sonraki soruya geç
if (currentQuestionIndex < currentQuestions.length - 1) {
showNextQuestion();
} else {
// Son soru ise, quizi bitir
finishQuiz();
}
}
}, 1000);
}
// Soru zamanlayıcısını güncelleme fonksiyonu
function updateQuestionTimer() {
questionTimerElement.textContent = `Kalan Süre: ${questionTimeLeft}s`;
// Süre azaldıkça rengi değiştir
if (questionTimeLeft <= 5) {
questionTimerElement.style.color = '#f44336'; // Kırmızı
} else if (questionTimeLeft <= 10) {
questionTimerElement.style.color = '#ff9800'; // Turuncu
} else {
questionTimerElement.style.color = '#4caf50'; // Yeşil
}
}
2. Zorluk Seviyeleri
Farklı zorluk seviyelerinde sorular ekleyebilirsiniz:
// HTML'e zorluk seviyesi seçimi ekleyin
// <select id="difficultySelect">
// <option value="kolay">Kolay</option>
// <option value="orta">Orta</option>
// <option value="zor">Zor</option>
// </select>
// Zorluk seviyesi seçimini al
const difficultySelect = document.getElementById('difficultySelect');
// Soru veritabanını zorluk seviyelerine göre düzenleyin
const quizQuestionsByDifficulty = {
genel: {
kolay: [ /* Kolay sorular */ ],
orta: [ /* Orta zorlukta sorular */ ],
zor: [ /* Zor sorular */ ]
},
// Diğer kategoriler...
};
// Quiz'i başlatma fonksiyonunu güncelle
function startQuiz() {
// Seçilen kategori ve zorluk seviyesini al
const selectedCategory = categorySelect.value;
const selectedDifficulty = difficultySelect.value;
// Seçilen kategori ve zorluk seviyesindeki soruları al
currentQuestions = quizQuestionsByDifficulty[selectedCategory][selectedDifficulty];
// ... mevcut kod ...
}
3. Soru İpuçları
Her soru için ipucu ekleyebilir ve kullanıcıların ihtiyaç duyduklarında bu ipuçlarını görmelerini sağlayabilirsiniz:
// Soru veritabanına ipuçları ekleyin
const quizQuestionsWithHints = {
genel: [
{
question: "Türkiye'nin başkenti hangi şehirdir?",
options: ["İstanbul", "Ankara", "İzmir", "Bursa"],
answer: 1,
hint: "1923'te Cumhuriyet'in ilanından sonra başkent olmuştur."
},
// Diğer sorular...
],
// Diğer kategoriler...
};
// HTML'e ipucu butonu ekleyin
// <button class="quiz-button secondary" id="hintButton">İpucu</button>
// İpucu butonunu seç
const hintButton = document.getElementById('hintButton');
// İpucu elementi oluştur
const hintElement = document.createElement('div');
hintElement.className = 'question-hint';
hintElement.style.display = 'none';
quizQuestion.appendChild(hintElement);
// İpucu butonuna tıklama olayı
hintButton.addEventListener('click', showHint);
// İpucu gösterme fonksiyonu
function showHint() {
// İpucu metnini güncelle
hintElement.textContent = currentQuestions[currentQuestionIndex].hint;
// İpucu elementini göster
hintElement.style.display = 'block';
// İpucu butonunu devre dışı bırak
hintButton.disabled = true;
// İpucu kullanımını kaydet (puanı azaltmak için)
hintsUsed++;
}
// Soruyu gösterme fonksiyonunu güncelle
function showQuestion(index) {
// ... mevcut kod ...
// İpucu elementini gizle ve butonu sıfırla
hintElement.style.display = 'none';
hintButton.disabled = false;
// ... mevcut kod ...
}
4. Sonuç Grafiği
Quiz sonuçlarını görsel olarak göstermek için bir grafik ekleyebilirsiniz:
// HTML'e grafik için bir canvas ekleyin
// <canvas id="resultsChart" width="400" height="200"></canvas>
// Quiz'i bitirme fonksiyonunu güncelle
function finishQuiz() {
// ... mevcut kod ...
// Sonuç grafiğini oluştur
createResultsChart();
// ... mevcut kod ...
}
// Sonuç grafiği oluşturma fonksiyonu
function createResultsChart() {
const canvas = document.getElementById('resultsChart');
const ctx = canvas.getContext('2d');
// Grafik verilerini hazırla
const correct = userAnswers.reduce((count, answer, index) => {
return count + (answer === currentQuestions[index].answer ? 1 : 0);
}, 0);
const wrong = currentQuestions.length - correct;
// Grafik ayarları
const chartWidth = canvas.width;
const chartHeight = canvas.height;
const barHeight = 40;
const maxBarWidth = chartWidth - 100;
// Arkaplanı temizle
ctx.clearRect(0, 0, chartWidth, chartHeight);
// Doğru cevaplar çubuğu
ctx.fillStyle = '#4caf50';
const correctBarWidth = (correct / currentQuestions.length) * maxBarWidth;
ctx.fillRect(80, 50, correctBarWidth, barHeight);
// Yanlış cevaplar çubuğu
ctx.fillStyle = '#f44336';
const wrongBarWidth = (wrong / currentQuestions.length) * maxBarWidth;
ctx.fillRect(80, 110, wrongBarWidth, barHeight);
// Etiketler
ctx.fillStyle = '#333';
ctx.font = '14px Arial';
ctx.fillText('Doğru', 20, 75);
ctx.fillText('Yanlış', 20, 135);
// Değerler
ctx.fillStyle = '#333';
ctx.font = '14px Arial';
ctx.fillText(`${correct}`, correctBarWidth + 90, 75);
ctx.fillText(`${wrong}`, wrongBarWidth + 90, 135);
}
Geliştirme Zorlukları
Quiz uygulamanızı daha da geliştirmek için aşağıdaki zorlukları deneyebilirsiniz:
- Çoklu Oyuncu Modu: İki veya daha fazla oyuncunun aynı cihazda sırayla oynayabilmesini sağlayan bir mod ekleyin.
- Soru Ekleme Paneli: Kullanıcıların kendi sorularını ekleyebilmesini sağlayan bir panel oluşturun.
- Yüksek Skor Tablosu: En iyi sonuçları gösteren bir yüksek skor tablosu ekleyin.
- Ses Efektleri: Doğru ve yanlış cevaplar için ses efektleri ekleyin.
- Sosyal Medya Paylaşımı: Kullanıcıların sonuçlarını sosyal medyada paylaşabilmesini sağlayın.
Sonuç ve Öğrenilen Dersler
Bu projede, JavaScript kullanarak interaktif bir quiz uygulaması geliştirdik. Bu süreçte şunları öğrendik:
- DOM elementlerini dinamik olarak oluşturmayı ve manipüle etmeyi
- JavaScript ile form kontrolü ve kullanıcı girdilerini işlemeyi
- Zamanlayıcılar ve geri sayım işlevselliği eklemeyi
- Veri yapılarını (diziler, nesneler) etkili bir şekilde kullanmayı
- Uygulama durumunu yönetmeyi ve farklı ekranlar arasında geçiş yapmayı
- LocalStorage kullanarak kullanıcı verilerini kaydetmeyi
- Responsive tasarım ilkelerini uygulamayı
Bu proje, modern web geliştirme becerilerinizi geliştirmenize ve gerçek dünya uygulamaları oluşturmanıza yardımcı olacak temel bilgileri sağlamıştır. Öğrendiğiniz teknikleri ve kavramları kullanarak, daha karmaşık ve özelleştirilmiş web uygulamaları geliştirebilirsiniz.