Default screen with cards on it working

This commit is contained in:
2023-04-09 17:35:53 +02:00
parent 94113e80fd
commit 9a1f86156f
7 changed files with 288 additions and 27 deletions

64
Set/AspectVGrid.swift Normal file
View File

@@ -0,0 +1,64 @@
//
// AspectVGrid.swift
// Memorize
//
// Created by Oliver Hnát on 08.04.2023.
//
import SwiftUI
struct AspectVGrid<Item, ItemView>: 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()
// }
//}

View File

@@ -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()
}
}

31
Set/Diamond.swift Normal file
View File

@@ -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
}
}

View File

@@ -11,7 +11,7 @@ import SwiftUI
struct SetApp: App { struct SetApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
ContentView() SetGameView(game: SetGame())
} }
} }
} }

68
Set/SetGame.swift Normal file
View File

@@ -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<Card>
private(set) var cardsOnTable: Array<Card>
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<SetGame.Card> {
let colors: Array<Color> = [.blue, .green, .red]
var deck: Array<SetGame.Card> = 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
}
}

104
Set/SetGameView.swift Normal file
View File

@@ -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..<numberOfSymbols, id: \.self) { _ in
createShape().frame(height: geometry.size.height/4)
}
}
}
}
}
@ViewBuilder
private func createShape() -> 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)
}
}

20
Set/Uniqueness.swift Normal file
View File

@@ -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
}