TroglodyteDerivations's picture
Upload 3 files
3f63052 verified
import sys
import math
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QLabel, QPushButton, QRadioButton,
QButtonGroup, QMessageBox, QProgressBar, QFrame)
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QFont, QPalette
class AStarQuizGame(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
self.initQuestions()
self.current_question = 0
self.score = 0
self.showQuestion()
def initUI(self):
self.setWindowTitle("A* Heuristic Functions Quiz Game")
self.setGeometry(100, 100, 800, 600)
self.setStyleSheet("""
QMainWindow {
background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
stop:0 #2c3e50, stop:1 #34495e);
}
QLabel {
color: white;
background: transparent;
}
QRadioButton {
color: white;
background: transparent;
padding: 8px;
}
QRadioButton::indicator {
width: 20px;
height: 20px;
border-radius: 10px;
border: 2px solid #3498db;
}
QRadioButton::indicator:checked {
background-color: #3498db;
}
QPushButton {
background-color: #3498db;
color: white;
border: none;
padding: 12px 24px;
border-radius: 5px;
font-size: 14px;
font-weight: bold;
}
QPushButton:hover {
background-color: #2980b9;
}
QPushButton:disabled {
background-color: #7f8c8d;
}
QFrame {
background-color: rgba(44, 62, 80, 0.9);
border-radius: 10px;
border: 2px solid #3498db;
}
QProgressBar {
border: 2px solid #3498db;
border-radius: 5px;
text-align: center;
color: white;
background-color: #2c3e50;
}
QProgressBar::chunk {
background-color: #3498db;
width: 20px;
}
""")
# Central widget
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
layout.setSpacing(20)
layout.setContentsMargins(30, 30, 30, 30)
# Title
title = QLabel("A* Heuristic Functions Quiz")
title.setAlignment(Qt.AlignCenter)
title.setFont(QFont("Arial", 24, QFont.Bold))
layout.addWidget(title)
# Score and progress
score_layout = QHBoxLayout()
self.score_label = QLabel("Score: 0/0")
self.score_label.setFont(QFont("Arial", 14))
self.progress_bar = QProgressBar()
self.progress_bar.setMaximum(100)
self.progress_bar.setMinimum(0)
score_layout.addWidget(self.score_label)
score_layout.addWidget(self.progress_bar)
layout.addLayout(score_layout)
# Question frame
self.question_frame = QFrame()
question_frame_layout = QVBoxLayout(self.question_frame)
question_frame_layout.setSpacing(15)
self.question_label = QLabel()
self.question_label.setWordWrap(True)
self.question_label.setFont(QFont("Arial", 16))
self.question_label.setAlignment(Qt.AlignCenter)
question_frame_layout.addWidget(self.question_label)
# Options
self.option_group = QButtonGroup()
self.options_layout = QVBoxLayout()
self.option_buttons = []
for i in range(4):
radio = QRadioButton()
radio.setFont(QFont("Arial", 12))
self.option_group.addButton(radio, i)
self.options_layout.addWidget(radio)
self.option_buttons.append(radio)
question_frame_layout.addLayout(self.options_layout)
layout.addWidget(self.question_frame)
# Buttons
buttons_layout = QHBoxLayout()
self.prev_button = QPushButton("Previous")
self.next_button = QPushButton("Next")
self.submit_button = QPushButton("Submit Answer")
self.restart_button = QPushButton("Restart Quiz")
self.prev_button.clicked.connect(self.previousQuestion)
self.next_button.clicked.connect(self.nextQuestion)
self.submit_button.clicked.connect(self.submitAnswer)
self.restart_button.clicked.connect(self.restartQuiz)
buttons_layout.addWidget(self.prev_button)
buttons_layout.addWidget(self.next_button)
buttons_layout.addWidget(self.submit_button)
buttons_layout.addWidget(self.restart_button)
layout.addLayout(buttons_layout)
# Explanation
self.explanation_label = QLabel()
self.explanation_label.setWordWrap(True)
self.explanation_label.setFont(QFont("Arial", 12))
self.explanation_label.setStyleSheet("color: #f39c12; background: transparent;")
self.explanation_label.setAlignment(Qt.AlignCenter)
self.explanation_label.hide()
layout.addWidget(self.explanation_label)
def initQuestions(self):
self.questions = [
{
"question": "Which heuristic function is calculated as |xโ‚ - xโ‚‚| + |yโ‚ - yโ‚‚|?",
"options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "Hamming Distance"],
"correct": 1,
"explanation": "Manhattan Distance is calculated as the sum of absolute differences in x and y coordinates: |xโ‚ - xโ‚‚| + |yโ‚ - yโ‚‚|"
},
{
"question": "Which heuristic is optimal for grid-based movement with 4-direction movement (up, down, left, right)?",
"options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "All are equally good"],
"correct": 1,
"explanation": "Manhattan Distance is optimal for 4-direction grid movement as it exactly matches the movement cost."
},
{
"question": "What is the formula for Euclidean Distance between points (xโ‚,yโ‚) and (xโ‚‚,yโ‚‚)?",
"options": [
"|xโ‚ - xโ‚‚| + |yโ‚ - yโ‚‚|",
"โˆš((xโ‚ - xโ‚‚)ยฒ + (yโ‚ - yโ‚‚)ยฒ)",
"max(|xโ‚ - xโ‚‚|, |yโ‚ - yโ‚‚|)",
"(xโ‚ - xโ‚‚)ยฒ + (yโ‚ - yโ‚‚)ยฒ"
],
"correct": 1,
"explanation": "Euclidean Distance uses the Pythagorean theorem: โˆš((xโ‚ - xโ‚‚)ยฒ + (yโ‚ - yโ‚‚)ยฒ)"
},
{
"question": "Which heuristic is calculated as max(|xโ‚ - xโ‚‚|, |yโ‚ - yโ‚‚|)?",
"options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "Minkowski Distance"],
"correct": 2,
"explanation": "Chebyshev Distance takes the maximum of the absolute differences in coordinates."
},
{
"question": "For 8-direction movement (including diagonals), which heuristic is most appropriate?",
"options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "Manhattan is always better"],
"correct": 2,
"explanation": "Chebyshev Distance is optimal for 8-direction movement as diagonal moves have cost equal to the maximum coordinate difference."
},
{
"question": "Which heuristic is always admissible (never overestimates) for grid-based pathfinding?",
"options": [
"Only Manhattan Distance",
"Only Euclidean Distance",
"Both Manhattan and Euclidean",
"All three: Manhattan, Euclidean, and Chebyshev"
],
"correct": 3,
"explanation": "All three heuristics are admissible for grid-based pathfinding as they never overestimate the actual cost."
},
{
"question": "In terms of computation cost, which heuristic is generally the fastest to calculate?",
"options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "They are all similar"],
"correct": 1,
"explanation": "Manhattan Distance is fastest as it only uses absolute values and addition, avoiding square roots and powers."
},
{
"question": "Which heuristic would be most suitable for a game with diagonal movement costing the same as horizontal/vertical?",
"options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "None are suitable"],
"correct": 2,
"explanation": "Chebyshev Distance is perfect when diagonal moves cost the same as horizontal/vertical moves."
}
]
self.user_answers = [None] * len(self.questions)
self.answered = [False] * len(self.questions)
def showQuestion(self):
question_data = self.questions[self.current_question]
self.question_label.setText(f"Question {self.current_question + 1}: {question_data['question']}")
for i, option in enumerate(question_data['options']):
self.option_buttons[i].setText(option)
self.option_buttons[i].setChecked(self.user_answers[self.current_question] == i)
self.explanation_label.hide()
self.updateNavigation()
self.updateProgress()
def updateNavigation(self):
self.prev_button.setEnabled(self.current_question > 0)
self.next_button.setEnabled(self.current_question < len(self.questions) - 1)
if self.answered[self.current_question]:
self.submit_button.setEnabled(False)
self.explanation_label.show()
else:
self.submit_button.setEnabled(True)
def updateProgress(self):
# FIX: Convert float to int for progress bar
progress = int((self.current_question + 1) / len(self.questions) * 100)
self.progress_bar.setValue(progress)
self.score_label.setText(f"Score: {self.score}/{len(self.questions)}")
def nextQuestion(self):
if self.current_question < len(self.questions) - 1:
self.current_question += 1
self.showQuestion()
def previousQuestion(self):
if self.current_question > 0:
self.current_question -= 1
self.showQuestion()
def submitAnswer(self):
selected = self.option_group.checkedId()
if selected == -1:
QMessageBox.warning(self, "No Selection", "Please select an answer before submitting.")
return
self.user_answers[self.current_question] = selected
self.answered[self.current_question] = True
question_data = self.questions[self.current_question]
is_correct = (selected == question_data['correct'])
# Update score
if is_correct:
self.score += 1
# Show explanation
self.explanation_label.setText(
f"{'โœ“ Correct!' if is_correct else 'โœ— Incorrect!'} {question_data['explanation']}"
)
self.explanation_label.show()
self.updateNavigation()
self.updateProgress()
# Auto-advance if not last question
if self.current_question < len(self.questions) - 1:
QTimer.singleShot(2000, self.nextQuestion)
else:
self.showFinalScore()
def showFinalScore(self):
percentage = (self.score / len(self.questions)) * 100
if percentage >= 80:
message = "Excellent! You're an A* heuristic expert! ๐ŸŽ‰"
elif percentage >= 60:
message = "Good job! You have a solid understanding! ๐Ÿ‘"
else:
message = "Keep practicing! Review the heuristics and try again! ๐Ÿ“š"
QMessageBox.information(
self,
"Quiz Completed!",
f"Final Score: {self.score}/{len(self.questions)} ({percentage:.1f}%)\n\n{message}"
)
def restartQuiz(self):
self.current_question = 0
self.score = 0
self.user_answers = [None] * len(self.questions)
self.answered = [False] * len(self.questions)
self.option_group.setExclusive(False)
for button in self.option_buttons:
button.setChecked(False)
self.option_group.setExclusive(True)
self.showQuestion()
def main():
app = QApplication(sys.argv)
# Set application-wide font
font = QFont("Arial", 10)
app.setFont(font)
game = AStarQuizGame()
game.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()