// // SetGame.swift // Set // // Created by Oliver Hnát on 09.04.2023. // import Foundation import SwiftUI struct SetGame { private(set) var cards: Array private(set) var score: Int = 0 private(set) var colors : [Int : Color] = [:] private var matches: Int = 0 mutating func choose(_ card: Card) { if let chosenIndex = cards.firstIndex(where: {card.id == $0.id}), !cards[chosenIndex].isMatched, !cards[chosenIndex].isSelected, cards[chosenIndex].isOnTheTable { cards[chosenIndex].isSelected = true var chosenCards: Array = Array() for c in cards { if c.isSelected { chosenCards.append(c) } } if chosenCards.count > 2 { let chosenCard1 = chosenCards[0] let chosenCard2 = chosenCards[1] let chosenCard3 = chosenCards[2] let chosenCards = [chosenCard1, chosenCard2, chosenCard3] let color = all3EqualOrAllDifferent(chosenCard1.color, chosenCard2.color, chosenCard3.color) let shading = all3EqualOrAllDifferent(chosenCard1.shading, chosenCard2.shading, chosenCard3.shading) let symbol = all3EqualOrAllDifferent(chosenCard1.symbol, chosenCard2.symbol, chosenCard3.symbol) let numberOnCard = all3EqualOrAllDifferent(chosenCard1.numberOnCard, chosenCard2.numberOnCard, chosenCard3.numberOnCard) if color && shading && symbol && numberOnCard { for chosenCard in chosenCards { cards[cards.firstIndex(where: {chosenCard.id == $0.id})!].isMatched = true cards[cards.firstIndex(where: {chosenCard.id == $0.id})!].matchId = matches } colors.updateValue(randomColor(), forKey: self.matches) score += 1 matches += 1 if (cardsOnTheTable < GameConstants.cardsOnTableInTheBeggining) { addCardsToTable(GameConstants.numberOfCardsToDraw) } } else { score -= 1 } for chosenCard in chosenCards { cards[cards.firstIndex(where: {chosenCard.id == $0.id})!].isSelected = false } } } else if let chosenIndex = cards.firstIndex(where: {card.id == $0.id}), !cards[chosenIndex].isMatched, cards[chosenIndex].isSelected, cards[chosenIndex].isOnTheTable { cards[chosenIndex].isSelected = false } } func all3EqualOrAllDifferent(_ first: EquatableObject, _ second: EquatableObject, _ third: EquatableObject) -> Bool { (first == second && first == third) || ((first != second && first != third) && second != third) } mutating func addCardsToTable(_ numberOfCards: Int) { var i = 0 var cardsAdded = 0 while cardsAdded < numberOfCards && i < cards.count { let card = cards[i] if (!card.isOnTheTable && !card.isMatched) { let cardIndexToBeModified = cards.firstIndex(where: {$0.id == card.id}) if (cardIndexToBeModified != nil) { cards[cardIndexToBeModified!].isOnTheTable = true cardsAdded += 1 } } i += 1 } } var displayedCards: Array { cards.filter { card in card.isOnTheTable // && !card.isMatched }.sorted { $0.matchId < $1.matchId } } var cardsOnTheTable: Int { cards.filter({$0.isOnTheTable && !$0.isMatched}).count } init() { var deck = SetGame.createCards() deck.shuffle() for i in 0.. 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.. Color { let red = Double.random(in: 0...1) let blue = Double.random(in: 0...1) let green = Double.random(in: 0...1) return Color(red: red, green: green, blue: blue).opacity(0.5) } 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 isOnTheTable: Bool = false var numberOnCard: Int var matchId: Int = -1 } private struct GameConstants { static let numberOfDifferences = 4 static let cardsOnTableInTheBeggining = 12 static let numberOfCardsToDraw = 3 } }