Please leave feedback by posting on Ed or contacting the course staff.
Required Software: macOS Ventura, Xcode 15
Deadline: Wednesday, 3/19 @ 11:59 PM
This assignment does not have any starter code -- you'll be creating your own project from scratch.
Introduction
In this assignment, you will create a trivia game application using SwiftUI. This project will
consolidate your understanding of UI components, state management, navigation, and app design by
applying them to a real-world interactive application. We have laid out some basic requirements and
a high-level guide to get you started, but the design and implementation are up to you. Pick your
favorite trivia topic and have fun!
Requirements
Your app should have at least two screens, organized in a NavigationStack
(or NavigationSplitView
, should you choose):
- Welcome Screen: Title, instructions (or a button to show them on another screen), high score, and a start button that leads to the Game Screen.
- Game Screen: Screen for the game itself, which presents the trivia questions and displays the final score at the end.
You can split these into more screens if you'd like, but you should have at least two in your navigation stack.
Your game should:
- Have at least 5 questions, each with question text, an image, and 4 answer options. (The image can be an SF Symbols icon if you'd like.)
- Keep track of and display the user's score as they progress through the questions (the exact scoring system is up to you, so long as each question affects it).
- Provide a mechanism to restart the game at any time, and allow the user to play the game again after finishing all questions.
- Display a high score on the Welcome Screen, update it as needed when the user finishes a game, and persist it while the app is running. (You do not need to save it between app launches -- we won't cover that until Lecture 9.)
You should use the Model-View-ViewModel (MVVM) architecture to separate the game logic from the UI:
- Model: You should have a
Question
model that represents a single question.
- ViewModel: You should have a
QuizViewModel
that manages the game state.
- View: Multiple views that make up the interactive game UI.
You should also use these SwiftUI features:
- An
@Observable
class for the view model (using ObservableObject
no longer counts for this assignment)
@State
to store simple data and @Binding
to pass it between views (or alternatively @Environment/@Bindable if passing data through the view model)
- You must have a property that is annotated with
@State
.
- You must explicitly use at least one property annotated with
@Binding
, @Bindable
, or @Environment
to pass data both ways.
NavigationStack
for screen transitions
- When resetting the game to the Welcome Screen, you may not push the Welcome Screen onto the top of the
NavigationStack
.
- e.g. Just clicking the "Back" button to go to the Welcome Screen is sufficient, but alternatively you may reset/clear the
NavigationPath
if you're using that.
The above are simply some minimum requirements for us to grade your game. We encourage you to add
more features and polish your game as much as you like!
Grading
This assignment is out of 100 points, with the following breakdown:
Gameplay & Screens (60 points)
Welcome Screen (5 points)
- Includes a title and instructions, or a way to navigate to them (2 points)
- Includes a functional start button that navigates to the Game Screen (3 points)
Game Screen (30 points)
- Displays the current question's text, image, and answers (10 points)
- Moves to the next question after an answer is selected (10 points)
- Correctly tracks the user's score (5 points)
- Displays the score after the last question (5 points)
Restarting Flow (10 points)
To receive full credit, restarts must clear all transient game state, except for data like high score. Other than that, the restarting flow can be implemented however you'd like so long as you can do so without relaunching the app.
- Allows the user to restart the game while the game is running (5 points)
- Allows the user to restart the game once it finishes (5 points)
High Score (15 points)
- High score is displayed on the Welcome Screen (5 points)
- High score is updated if the user beats it at the end of a game (5 points)
- High score stays the same if it is not beaten at the end of a game (5 points)
State Management & Navigation (15 points)
- Creating an
@Observable
class and sharing an instance of it across multiple views (5 points)
- Proper use of
@State
; and proper use of @Binding
, @Bindable
, or @Environment
to pass data between views both ways (5 points)
- Using
NavigationStack
(or NavigationSplitView
) for smooth screen transitions (5 points)
Architecture (15 points)
- Model: Well-structured
Question
model representing each question (5 points)
- View Model: Robust
QuizViewModel
managing game logic and state, with appropriate
encapsulation of game logic and separation of concerns (10 points)
Design (10 points)
- Text is generally readable (in terms of size and contrast) in both light and dark modes (5 points)
- Modifiers are used to make the UI more visually appealing (5 points)
Deductions
- Egregious style/readability errors (see the code style guide) (-5 points)
- Xcode project contains a broken file reference preventing compilation (-5 points)
.xcodeproj
file is missing entirely (-10 points)
- App does not compile (-20 points)
General bugs (those not covered in the above deductions) will be subject to these deductions:
- -2 points: Minor bug, e.g. a UI/UX issue that appears in limited circumstances and doesn't affect the core flow
- -5 points: Major bug, e.g. a bug that prevents the core flow of the app but can be worked around in-app
- -10 points: Fatal bug, e.g. a bug that requires code modification to continue testing the core flow
- Crashes on launch, or during major parts of the app flow, will fall into this category
If a bug only appears when testing an extra credit feature, we will deduct at most the points you would have earned for that feature.
Extra Credits
- Sound Effects (+5): Add sound effects to your app to make it more immersive. For example, you can play a "correct" sound when the user selects the right answer, or a "wrong" sound when they select the wrong answer.
- Timer (+10): Add a timer to your game to limit the time the user has to answer each question. When the timer runs out, the game should automatically move to the next question.
- The timer should reset if the user restarts the game.
Instructions
The exact implementation is up to you, and we in fact recommend you take some time to sketch out how you personally might want to structure your app on paper or a whiteboard. This will help you more easily reason about your code later on.
We've provided a basic guide to get you started, but feel free to disregard it entirely:
View Guide →
Submission
Before you submit, check:
- Have I finished all the requirements?
- Does my app compile and run without crashing?
Then, zip (or tar.gz) your entire project folder and upload it to Gradescope. Be sure it contains both all necessary Swift files and your .xcodeproj
file! If you're not sure, unzip it somewhere else and verify that everything is there in the Finder.
Submit on Gradescope →