From 9a1f86156f8093bd0f073c83b6a36262f3be06f1 Mon Sep 17 00:00:00 2001 From: oliverhnat Date: Sun, 9 Apr 2023 17:35:53 +0200 Subject: [PATCH] Default screen with cards on it working --- Set/AspectVGrid.swift | 64 ++++++++++++++++++++++++++ Set/ContentView.swift | 26 ----------- Set/Diamond.swift | 31 +++++++++++++ Set/SetApp.swift | 2 +- Set/SetGame.swift | 68 +++++++++++++++++++++++++++ Set/SetGameView.swift | 104 ++++++++++++++++++++++++++++++++++++++++++ Set/Uniqueness.swift | 20 ++++++++ 7 files changed, 288 insertions(+), 27 deletions(-) create mode 100644 Set/AspectVGrid.swift delete mode 100644 Set/ContentView.swift create mode 100644 Set/Diamond.swift create mode 100644 Set/SetGame.swift create mode 100644 Set/SetGameView.swift create mode 100644 Set/Uniqueness.swift diff --git a/Set/AspectVGrid.swift b/Set/AspectVGrid.swift new file mode 100644 index 0000000..4691f99 --- /dev/null +++ b/Set/AspectVGrid.swift @@ -0,0 +1,64 @@ +// +// AspectVGrid.swift +// Memorize +// +// Created by Oliver Hnát on 08.04.2023. +// + +import SwiftUI + + struct AspectVGrid: View where ItemView: View, Item: Identifiable { + var items: [Item] + var aspectRatio: CGFloat + var content: (Item) -> ItemView + + init(items: [Item], aspectRatio: CGFloat, @ViewBuilder content: @escaping (Item) -> ItemView) { + self.items = items + self.aspectRatio = aspectRatio + self.content = content + } + + var body: some View { + GeometryReader { geometry in + VStack { + let width: CGFloat = widthThatFits(itemCount: items.count, in: geometry.size, itemAspectRatio: aspectRatio) + LazyVGrid(columns: [adaptiveGridItem(width: width)], spacing: 0) { + ForEach(items) { item in + content(item).aspectRatio(aspectRatio, contentMode: .fit) + } + } + Spacer(minLength: 0) + } + } + } + + private func adaptiveGridItem(width: CGFloat) -> GridItem { + var gridItem = GridItem(.adaptive(minimum: width)) + gridItem.spacing = 0 + return gridItem + } + + private func widthThatFits(itemCount: Int, in size: CGSize, itemAspectRatio: CGFloat) -> CGFloat { + var columnCount = 1 + var rowCount = itemCount + repeat { + let itemWidth = size.width / CGFloat(columnCount) + let itemHeight = itemWidth / itemAspectRatio + if CGFloat(rowCount) * itemHeight < size.height { + break + } + columnCount += 1 + rowCount = (itemCount + (columnCount-1)) / columnCount + } while columnCount < itemCount + if columnCount > itemCount { + columnCount = itemCount + } + return floor(size.width / CGFloat(columnCount)) + } +} + +//struct AspectVGrid_Previews: PreviewProvider { +// static var previews: some View { +// AspectVGrid() +// } +//} diff --git a/Set/ContentView.swift b/Set/ContentView.swift deleted file mode 100644 index ae7c487..0000000 --- a/Set/ContentView.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// ContentView.swift -// Set -// -// Created by Oliver Hnát on 08.04.2023. -// - -import SwiftUI - -struct ContentView: View { - var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello, world!") - } - .padding() - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } -} diff --git a/Set/Diamond.swift b/Set/Diamond.swift new file mode 100644 index 0000000..d935335 --- /dev/null +++ b/Set/Diamond.swift @@ -0,0 +1,31 @@ +// +// Diamond.swift +// Set +// +// Created by Oliver Hnát on 08.04.2023. +// + +import SwiftUI + + +struct Diamond: Shape { + + func path(in rect: CGRect) -> Path { + + let leftSide = CGPoint(x: rect.minX, y: rect.midY) + let bottom = CGPoint(x: rect.midX, y: rect.midY-rect.maxY/4) + let rightSide = CGPoint(x: rect.maxX, y: rect.midY) + let top = CGPoint(x: rect.midX, y: rect.midY+rect.maxY/4) + + var p = Path() + + p.move(to: rightSide) + p.addLine(to: top) + p.addLine(to: leftSide) + p.addLine(to: bottom) + p.addLine(to: rightSide) + + return p + } + +} diff --git a/Set/SetApp.swift b/Set/SetApp.swift index 9ffff0b..307c93b 100644 --- a/Set/SetApp.swift +++ b/Set/SetApp.swift @@ -11,7 +11,7 @@ import SwiftUI struct SetApp: App { var body: some Scene { WindowGroup { - ContentView() + SetGameView(game: SetGame()) } } } diff --git a/Set/SetGame.swift b/Set/SetGame.swift new file mode 100644 index 0000000..d6030b0 --- /dev/null +++ b/Set/SetGame.swift @@ -0,0 +1,68 @@ +// +// SetGame.swift +// Set +// +// Created by Oliver Hnát on 09.04.2023. +// + +import Foundation +import SwiftUI + +struct SetGame { + private var deck: Array + private(set) var cardsOnTable: Array + + + init() { + var deck = SetGame.createCards() + deck.shuffle() + let cardsOnTable = Array(deck[0..<12]) + deck.removeAll { card in + cardsOnTable.contains { $0 == card } + } + self.deck = deck + self.cardsOnTable = cardsOnTable + } + + private static func createCards() -> Array { + let colors: Array = [.blue, .green, .red] + var deck: Array = Array() + var id = 0 + for symbol in CardSymbol.allCases { + for shading in CardShading.allCases { + for number in 1..<4 { + for symbolColor in colors.indices { + let newCard = SetGame.Card(id: id, shading: shading, symbol: symbol, color: colors[symbolColor], numberOnCard: number) + deck.append(newCard) + id += 1 + } + } + } + } + return deck + } + + mutating func newGame() { + var deck = SetGame.createCards() + deck.shuffle() + let cardsOnTable = Array(deck[0..<12]) + deck.removeAll { card in + cardsOnTable.contains { $0 == card } + } + self.deck = deck + self.cardsOnTable = cardsOnTable + } + + + + struct Card: Identifiable, Equatable { + var id: Int + var shading: CardShading + var symbol: CardSymbol + var color: Color + var isMatched: Bool = false + var isSelected: Bool = false + var numberOnCard: Int + } + +} diff --git a/Set/SetGameView.swift b/Set/SetGameView.swift new file mode 100644 index 0000000..8cc6bb3 --- /dev/null +++ b/Set/SetGameView.swift @@ -0,0 +1,104 @@ +// +// ContentView.swift +// Set +// +// Created by Oliver Hnát on 08.04.2023. +// + +import SwiftUI + +struct SetGameView: View { + + var game: SetGame + var body: some View { + VStack { + AspectVGrid(items: game.cardsOnTable, aspectRatio: 2/3) { card in + CardView(card: card).foregroundColor(.red) + } + Spacer() + Spacer() +// Button(action: {game.newGame()}, label: {Text("New game")}) + } + } + +} + + +struct CardView: View { + var card: SetGame.Card + var numberOfSymbols: Int + var color: Color + var symbol: CardSymbol + var shading: CardShading + + init(card: SetGame.Card) { + self.card = card + self.numberOfSymbols = card.numberOnCard + self.color = card.color + self.symbol = card.symbol + self.shading = card.shading + } + + var body: some View { + GeometryReader { geometry in + ZStack { + let cardShape = RoundedRectangle(cornerRadius: 10) + cardShape.aspectRatio(2/3, contentMode: .fit) + cardShape.foregroundColor(.white) + cardShape.strokeBorder(lineWidth: 5) + + if (shading == CardShading.open) { + } + VStack { + ForEach (0.. some View { + switch symbol { + case .diamond: + colorShape(Diamond()) + case .squiggles: + colorShape(Rectangle()) + default: + colorShape(RoundedRectangle(cornerRadius: 100)) + } + } + + @ViewBuilder + private func colorShape(_ shape: some Shape) -> some View { + opacityShape(shape).foregroundColor(color).padding(.horizontal) + } + + @ViewBuilder + private func opacityShape(_ shape: some Shape) -> some View { + switch shading { + case .solid: + shape.stroke(lineWidth: 2.5) + case .striped: + shape.opacity(0.5) + default: + shape + } + } +} + + + + + + + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + let game = SetGame() + SetGameView(game: game) + .preferredColorScheme(.dark) + SetGameView(game: game) + } +} diff --git a/Set/Uniqueness.swift b/Set/Uniqueness.swift new file mode 100644 index 0000000..a64b3f4 --- /dev/null +++ b/Set/Uniqueness.swift @@ -0,0 +1,20 @@ +// +// Shading.swift +// Set +// +// Created by Oliver Hnát on 08.04.2023. +// + +import Foundation + +enum CardShading: CaseIterable { + case solid + case striped + case open +} + +enum CardSymbol: CaseIterable { + case diamond + case squiggles + case oval +}