Mercurial > public > geoquiz
comparison GeoQuiz/Logic/Game.swift @ 3:4dbe0cd9dadc
first game prototype
author | Dennis C. M. <dennis@denniscm.com> |
---|---|
date | Thu, 22 Sep 2022 10:42:39 +0200 |
parents | |
children | de54f05adb78 |
comparison
equal
deleted
inserted
replaced
2:5b7c89bd45c3 | 3:4dbe0cd9dadc |
---|---|
1 // | |
2 // GameProtocol.swift | |
3 // GeoQuiz | |
4 // | |
5 // Created by Dennis Concepción Martín on 18/9/22. | |
6 // | |
7 | |
8 import Foundation | |
9 import SwiftUI | |
10 | |
11 protocol Game: ObservableObject { | |
12 | |
13 // Define generic type | |
14 associatedtype T: Equatable | |
15 | |
16 // Game | |
17 var data: [String: T] { get set} | |
18 var dataAsked: [String] { get set } | |
19 var correctAnswer: (key: String, value: T) { get set } | |
20 | |
21 // User | |
22 var userChoices: [String: T] { get set } | |
23 var userScore: Int { get set } | |
24 var userLives: Int { get set } | |
25 | |
26 // Alerts | |
27 var alertTitle: String { get set } | |
28 var alertMessage: String { get set } | |
29 var showingNoLivesAlert: Bool { get set } | |
30 var showingEndGameAlert: Bool { get set } | |
31 var showingWrongAnswerAlert: Bool { get set } | |
32 | |
33 // Animations | |
34 var scoreScaleAmount: Double { get set } | |
35 var livesScaleAmount: Double { get set } | |
36 | |
37 // Modal views | |
38 var showingBuyLivesView: Bool { get set } | |
39 } | |
40 | |
41 extension Game { | |
42 var questionCounter: Int { | |
43 dataAsked.count | |
44 } | |
45 | |
46 func askQuestion() { | |
47 guard questionCounter < data.count else { | |
48 alertTitle = "Amazing!" | |
49 alertMessage = "You've completed the game." | |
50 showingEndGameAlert = true | |
51 | |
52 return | |
53 } | |
54 | |
55 // Get random choices | |
56 var userChoices = [String: T]() | |
57 | |
58 while userChoices.count < 2 { | |
59 if let choice = data.randomElement() { | |
60 userChoices[choice.key] = choice.value | |
61 } else { | |
62 fatalError("Couldn't get a random value from data") | |
63 } | |
64 } | |
65 | |
66 // Get question asked (correct answer) | |
67 let correctAnswer = data.first(where: { | |
68 !userChoices.keys.contains($0.key) && !dataAsked.contains($0.key) | |
69 }) | |
70 | |
71 // Unwrap optional | |
72 if let correctAnswer = correctAnswer { | |
73 userChoices[correctAnswer.key] = correctAnswer.value | |
74 dataAsked.append(correctAnswer.key) | |
75 self.correctAnswer = correctAnswer | |
76 } else { | |
77 fatalError("Couldn't unwrap optional value") | |
78 } | |
79 | |
80 self.userChoices = userChoices | |
81 } | |
82 | |
83 func answer(_ choice: (key: String, value: T)) { | |
84 guard userLives > 0 else { | |
85 alertTitle = "Not enough lives!" | |
86 alertMessage = "Please buy more lives to keep playing" | |
87 showingNoLivesAlert = true | |
88 | |
89 return | |
90 } | |
91 | |
92 if correctAnswer == choice { | |
93 hapticSuccess() | |
94 userScore += 1 | |
95 | |
96 withAnimation(.easeIn(duration: 0.5)) { | |
97 scoreScaleAmount += 1 | |
98 } | |
99 | |
100 askQuestion() | |
101 } else { | |
102 hapticError() | |
103 userLives -= 1 | |
104 | |
105 withAnimation(.easeIn(duration: 0.5)) { | |
106 livesScaleAmount += 1 | |
107 } | |
108 | |
109 alertTitle = "Wrong!" | |
110 alertMessage = "You have \(userLives) lives left" | |
111 showingWrongAnswerAlert = true | |
112 } | |
113 | |
114 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [self] in | |
115 withAnimation(.easeIn(duration: 0.5)) { | |
116 scoreScaleAmount = 1 | |
117 livesScaleAmount = 1 | |
118 } | |
119 } | |
120 } | |
121 } |