Created
September 21, 2020 10:26
-
-
Save k-mao/b718c28ec36bff2342ec4894c0145030 to your computer and use it in GitHub Desktop.
Rock Paper Scissors Trainer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
struct PlayerMoveEmoji: ViewModifier { | |
func body(content: Content) -> some View { | |
content | |
.font(.system(size: 60)) | |
.padding(.bottom, 8) | |
} | |
} | |
extension View { | |
func playerMoveEmoji() -> some View { | |
self.modifier(PlayerMoveEmoji()) | |
} | |
} | |
struct PlayerMoveCardStyle: ButtonStyle { | |
let defaultTransform = CGAffineTransform(translationX: 0, y: 0) | |
let pressedTransform = CGAffineTransform(translationX: 0, y: -12) | |
func makeBody(configuration: Self.Configuration) -> some View { | |
configuration.label | |
.frame(minWidth: 60, maxWidth: 125, maxHeight: 160) | |
.clipShape(RoundedRectangle(cornerRadius: 24, style: .continuous)) | |
.shadow(color: Color(red: 0, green: 0, blue: 0, opacity: configuration.isPressed ? 0.2 : 0.16), radius: configuration.isPressed ? 4 : 12, y: configuration.isPressed ? 2 : 8) | |
.scaleEffect(configuration.isPressed ? 0.96 : 1.0) | |
.transformEffect(configuration.isPressed ? pressedTransform : defaultTransform) | |
} | |
} | |
struct PlayerMoveCard: View { | |
var emoji: String | |
var name: String | |
var index: Int { | |
switch self.name { | |
case "Rock": return 0 | |
case "Paper": return 1 | |
case "Scissors": return 2 | |
default: | |
return 0 | |
} | |
} | |
var handleTap: (Int) -> Void | |
var body: some View { | |
Button(action: { | |
handleTap(index) | |
}) { | |
ZStack { | |
Color.white | |
VStack { | |
Text(emoji) | |
.rotationEffect(.degrees(self.name == "Rock" ? 98 : 0)) | |
.padding(.leading, self.name == "Rock" ? 4 : 0) | |
.playerMoveEmoji() | |
Text(name) | |
.foregroundColor(.primary) | |
.font(.headline) | |
} | |
} | |
} | |
.buttonStyle(PlayerMoveCardStyle()) | |
.animation(.spring()) | |
} | |
} | |
struct ContentView: View { | |
var moveEmojis = ["🤛", "🖐", "✌️"] | |
var moveNames = ["Rock", "Paper", "Scissors"] | |
var maxTurns = 10 | |
@State private var score = 0 | |
@State private var appChoice = Int.random(in: 0 ..< 3) | |
@State private var shouldWin = Bool.random() | |
@State private var playerChoice = 0 | |
@State private var turns = 0 | |
@State private var showScore = false | |
var body: some View { | |
VStack { | |
HStack { | |
ProgressView(value: Float(turns) / Float(maxTurns)) | |
.padding(.trailing, 20) | |
Text("Score: \(score)") | |
.font(.callout) | |
.padding(8) | |
.background(Color(red: 0.95, green: 0.95, blue: 0.95)) | |
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous)) | |
} | |
Spacer() | |
VStack { | |
shouldWin ? Text("WIN") : Text("LOSE") | |
Text("against").font(.subheadline) | |
} | |
.font(.system(size: 48, weight: .heavy, design: .default)) | |
.padding(.bottom, 8) | |
VStack { | |
Text(moveNames[appChoice]).font(.title).bold() | |
.padding(.bottom, 20) | |
Text(moveEmojis[appChoice]) | |
.rotationEffect(.degrees(appChoice == 0 ? -82 : 180)) | |
.font(.system(size: 100)) | |
.padding(.leading, appChoice == 0 ? -6 : 0) | |
} | |
.padding(.bottom, 24) | |
Spacer() | |
HStack(spacing: 16) { | |
ForEach(0 ..< moveNames.count) { | |
PlayerMoveCard(emoji: moveEmojis[$0], name: moveNames[$0]) { | |
playerChoice = $0 | |
handleCardTap() | |
} | |
} | |
} | |
.padding(.bottom, 36) | |
} | |
.padding(20) | |
.alert(isPresented: $showScore, content: { | |
Alert(title: Text("Score: \(score) out of 10"), dismissButton: .default(Text("Play Again!")) { | |
score = 0 | |
turns = 0 | |
}) | |
}) | |
} | |
func handleCardTap() { | |
if shouldWin { | |
switch appChoice { | |
case 0: if playerChoice == 1 { score += 1 } | |
case 1: if playerChoice == 2 { score += 1 } | |
case 2: if playerChoice == 0 { score += 1 } | |
default: score += 0 | |
} | |
} else { | |
switch appChoice { | |
case 0: if playerChoice == 2 { score += 1 } | |
case 1: if playerChoice == 0 { score += 1 } | |
case 2: if playerChoice == 1 { score += 1 } | |
default: score += 0 | |
} | |
} | |
appChoice = Int.random(in: 0 ..< 3) | |
shouldWin = Bool.random() | |
turns += 1 | |
if turns == maxTurns { | |
showScore.toggle() | |
} | |
} | |
} | |
struct ContentView_Previews: PreviewProvider { | |
static var previews: some View { | |
ContentView() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A brain training game that challenges players to win or lose at rock, paper, scissors.
Check it out in action here: https://twitter.com/k_mao/status/1308084646240907264?s=21