Advertisement
QwertyAvatar

plik z wszystkim (do 6.6, niepełne)

Dec 10th, 2024
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 13.38 KB | Software | 0 0
  1. //MemoGameViewModel.Swift
  2.  
  3. import SwiftUI
  4.  
  5. class MemoGameViewModel: ObservableObject {
  6.     @Published private(set) var model: MemoGameModel<String>
  7.    
  8.     let theme1Symbols = ["🥷", "🥼", "🙉", "🏀", "🤿", "♌️", "❤️‍🩹", "🦊"]
  9.     let theme2Symbols = ["🍎", "🍏", "🍋", "🍇", "🍓", "🍉", "🍒", "🍌"]
  10.     let theme3Symbols = ["🚗", "🚕", "🚙", "🚌", "🚑", "🚒", "🚓", "🚜"]
  11.  
  12.  
  13.     enum Theme {
  14.         case theme1, theme2, theme3
  15.     }
  16.    
  17.     @Published var selectedTheme: Theme = .theme1 {
  18.         didSet {
  19.             updateModel() // Aktualizacja modelu po zmianie motywu
  20.         }
  21.     }
  22.    
  23.     var mainCard: MemoGameModel<String>.Card? {
  24.         model.cards.randomElement() // Losowa karta z obecnego modelu
  25.     }
  26.    
  27.     var selectedThemeColor: Color {
  28.         switch selectedTheme {
  29.         case .theme1: return .blue
  30.         case .theme2: return .green
  31.         case .theme3: return .red
  32.         }
  33.     }
  34.    
  35.     init() {
  36.         model = MemoGameViewModel.createGameModel(using: theme1Symbols)
  37.     }
  38.    
  39.     public var currentThemeSymbols: [String] {
  40.         switch selectedTheme {
  41.         case .theme1: return theme1Symbols
  42.         case .theme2: return theme2Symbols
  43.         case .theme3: return theme3Symbols
  44.         }
  45.     }
  46.    
  47.     private static func createGameModel(using symbols: [String]) -> MemoGameModel<String> {
  48.         return MemoGameModel<String>(numberOfCards: symbols.count) { index in
  49.             if index < symbols.count {
  50.                 return symbols[index]
  51.             } else {
  52.                 return "??" // Wartość błędna, gdy indeks jest poza zakresem
  53.             }
  54.         }
  55.     }
  56.    
  57.     func changeTheme(to theme: Theme) {
  58.         selectedTheme = theme
  59.         updateModel() // Aktualizujemy model przy zmianie tematu
  60.     }
  61.    
  62.     func updateModel() {
  63.         model = MemoGameViewModel.createGameModel(using: currentThemeSymbols)
  64.         model.resetCards() // Resetowanie stanu kart
  65.     }
  66.  
  67.  
  68.     func adjustCardNumber(by offset: Int) {
  69.         let newCardCount = model.cards.count + offset
  70.         if newCardCount >= 1 && newCardCount <= currentThemeSymbols.count { // Minimalna liczba kart to 1
  71.             model = MemoGameViewModel.createGameModel(using: Array(currentThemeSymbols.prefix(newCardCount)))
  72.             model.resetCards() // Resetujemy karty po zmianie liczby kart
  73.         }
  74.     }
  75.  
  76.    
  77.     func shuffleCards() {
  78.         model.shuffleCards() // Wywołanie tasowania kart w modelu
  79.         objectWillChange.send() // Wymuszenie odświeżenia widoku
  80.         model.resetCards()
  81.     }
  82.    
  83.     func choose(_ card: MemoGameModel<String>.Card) {
  84.         model.choose(card) // Obsługa wyboru karty
  85.     }
  86. }
  87.  
  88.  
  89. //MemoGameModel.swift
  90.  
  91. struct MemoGameModel<CardContent> where CardContent: Equatable {
  92.     private(set) var cards: [Card]
  93.     private(set) var mainCard: Card? // Zmienna dla głównej karty
  94.  
  95.     init(numberOfCards: Int, cardContentFactory: (Int) -> CardContent) {
  96.         cards = []
  97.         for index in 0..<numberOfCards {
  98.             let content = cardContentFactory(index)
  99.             cards.append(Card(id: "\(index)", content: content)) // Każdy `content` jest unikalny
  100.         }
  101.         shuffleCards()
  102.         mainCard = cards.randomElement() // Ustawienie losowej karty jako głównej
  103.     }
  104.  
  105.     mutating func setMainCard(_ card: Card) {
  106.         mainCard = card
  107.     }
  108.  
  109.    
  110.     mutating func choose(_ card: Card) {
  111.         // Znajdź indeks wybranej karty
  112.         guard let chosenIndex = cards.firstIndex(where: { $0.id == card.id }),
  113.               !cards[chosenIndex].isMatched else {
  114.             return
  115.         }
  116.        
  117.         // Jeśli karta jest już odkryta, nie robimy nic
  118.         if cards[chosenIndex].isFaceUp {
  119.             return
  120.         }
  121.  
  122.         // Zakrywamy wszystkie karty, z wyjątkiem głównej karty
  123.         for index in cards.indices {
  124.             // Jeśli karta nie jest dopasowana i nie jest główną kartą, ustawiamy ją na zakrytą
  125.             if !cards[index].isMatched && cards[index].id != mainCard?.id {
  126.                 cards[index].isFaceUp = false
  127.             }
  128.         }
  129.  
  130.         // Odkrywamy tylko wybraną kartę
  131.         cards[chosenIndex].isFaceUp = true
  132.  
  133.         // Sprawdzamy, czy mamy już odkrytą kartę
  134.         if let faceUpIndex = cards.firstIndex(where: { $0.isFaceUp && !$0.isMatched }) {
  135.             let faceUpCard = cards[faceUpIndex]
  136.  
  137.             // Sprawdzamy, czy karty pasują
  138.             if faceUpCard.content == cards[chosenIndex].content {
  139.                 // Karty pasują, oznaczamy je jako dopasowane
  140.                 cards[chosenIndex].isMatched = true
  141.                 cards[faceUpIndex].isMatched = true
  142.             }
  143.         }
  144.     }
  145.  
  146.  
  147.  
  148.     mutating func resetCards() {
  149.         for index in cards.indices {
  150.             cards[index].isFaceUp = false
  151.             cards[index].isMatched = false
  152.         }
  153.        
  154.         // Ustawienie głównej karty jako odkrytej
  155.         if let mainCard = mainCard, let index = cards.firstIndex(where: { $0.id == mainCard.id }) {
  156.             cards[index].isFaceUp = true
  157.         }
  158.     }
  159.  
  160.  
  161.  
  162.     mutating func shuffleCards() {
  163.         cards.shuffle()
  164.        
  165.         // Przywróć główną kartę na początek, aby była odkryta
  166.         if let mainCard = mainCard, let index = cards.firstIndex(where: { $0.id == mainCard.id }) {
  167.             cards.remove(at: index)
  168.             cards.insert(mainCard, at: 0)
  169.         }
  170.  
  171.         // Ustawiamy wszystkie karty na zakryte, oprócz głównej
  172.         for index in cards.indices {
  173.             cards[index].isFaceUp = false
  174.             cards[index].isMatched = false
  175.         }
  176.  
  177.         // Ustawienie głównej karty jako odkrytej
  178.         if let mainCard = mainCard, let index = cards.firstIndex(where: { $0.id == mainCard.id }) {
  179.             cards[index].isFaceUp = true
  180.         }
  181.     }
  182.  
  183.  
  184.    
  185.     func index(of card: Card) -> Int? {
  186.         cards.firstIndex { $0.id == card.id }
  187.     }
  188.  
  189.     func indexOfFacedUpCard(excluding card: Card) -> [Int] {
  190.         cards.indices.filter { cards[$0].isFaceUp && cards[$0] != card }
  191.     }
  192.  
  193.     mutating func changeVisible() {
  194.         for index in cards.indices {
  195.             if !cards[index].isMatched {
  196.                 cards[index].visible.toggle()
  197.             }
  198.         }
  199.     }
  200.  
  201.     func getNumberCard(card: Card) -> String {
  202.         String(card.id.dropLast())
  203.     }
  204.  
  205.  
  206.     struct Card: Identifiable, Equatable {
  207.         let id: String // Typ String
  208.         var isFaceUp = false
  209.         var isMatched = false
  210.         let content: CardContent
  211.         var visible: Bool = true
  212.     }
  213. }
  214.  
  215.  
  216. //ContentView.swift (ma Card!)
  217.  
  218. import SwiftUI
  219.  
  220. // 6.6 - poprawki (fix: przy tasowaniu pierwsza karta zawsze odkryta,
  221. // caly czas sie roluje glowna, moze byc wiecej niz jedna odkryta)
  222.  
  223. struct ContentView: View {
  224.     @StateObject var viewModel = MemoGameViewModel() // Adnotacja @ObservedObject
  225.    
  226.     var columns: [GridItem] {
  227.         [GridItem(.adaptive(minimum: 85), spacing: -30)] // Modyfikator adaptive z minimum 85, spacing 0
  228.     }
  229.    
  230.     var body: some View {
  231.         VStack {
  232.             Text("Memo")
  233.                 .font(.largeTitle)
  234.                 .padding(.top, 20)
  235.                 .foregroundColor(viewModel.selectedThemeColor) // Kolor zgodny z motywem
  236.            
  237.             //Spacer()
  238.            
  239.             mainCard // Wyświetlanie głównej karty
  240.            
  241.             ScrollView {
  242.                 cardDisplay
  243.             }
  244.            
  245.             HStack {
  246.                 ThemeButton(title: "Motyw 1", icon: "🥎", action: { viewModel.changeTheme(to: .theme1) }, color: viewModel.selectedThemeColor)
  247.                 Spacer()
  248.                 ThemeButton(title: "Motyw 2", icon: "🏀", action: { viewModel.changeTheme(to: .theme2) }, color: viewModel.selectedThemeColor)
  249.                 Spacer()
  250.                 ThemeButton(title: "Motyw 3", icon: "⚽️", action: { viewModel.changeTheme(to: .theme3) }, color: viewModel.selectedThemeColor)
  251.             }
  252.             .padding(.horizontal)
  253.            
  254.             HStack {
  255.                 adjustCardNumberButton(by: -1, symbol: "minus", isEnabled: viewModel.model.cards.count > 1)
  256.                 Spacer()
  257.                 adjustCardNumberButton(by: 1, symbol: "plus", isEnabled: viewModel.model.cards.count < 8)
  258.                 Spacer()
  259.                 shuffleButton // Przycisk do tasowania kart
  260.             }
  261.             .padding(.horizontal)
  262.         }
  263.         .onAppear {
  264.             viewModel.updateModel()
  265.         }
  266.     }
  267.    
  268.     var cardDisplay: some View {
  269.         LazyVGrid(columns: columns, spacing: 0) { // Spacing 0 dla siatki
  270.             ForEach(viewModel.model.cards) { card in
  271.                 CardView(card: card, cardColor: .constant(viewModel.selectedThemeColor))
  272.                     .onTapGesture {
  273.                         viewModel.choose(card)
  274.                     }
  275.                     .padding(5) // Padding dla każdej karty
  276.             }
  277.         }
  278.         .padding()
  279.     }
  280.    
  281.     var mainCard: some View {
  282.         if let mainCard = viewModel.mainCard {
  283.             var mainCardCopy = mainCard
  284.             mainCardCopy.isFaceUp = true // Zawsze ustawiamy główną kartę jako odkrytą
  285.  
  286.             return AnyView(
  287.                 CardView(card: mainCardCopy, cardColor: .constant(viewModel.selectedThemeColor))
  288.                     .padding()
  289.                     .frame(width: 180, height: 270)
  290.                     .aspectRatio(2 / 3, contentMode: .fit)
  291.             )
  292.         } else {
  293.             return AnyView(EmptyView())
  294.         }
  295.     }
  296.  
  297.  
  298.    
  299.     private func adjustCardNumberButton(by offset: Int, symbol: String, isEnabled: Bool) -> some View {
  300.         Button(action: {
  301.             viewModel.adjustCardNumber(by: offset)
  302.         }) {
  303.             Image(systemName: symbol == "plus" ? "plus" : "minus")
  304.                 .font(.title)
  305.                 .padding(10)
  306.                 .background(Color.white)
  307.                 .overlay(
  308.                     RoundedRectangle(cornerRadius: 8)
  309.                         .stroke(viewModel.selectedThemeColor, lineWidth: 2)
  310.                 )
  311.         }
  312.         .disabled(!isEnabled)
  313.         .foregroundColor(isEnabled ? viewModel.selectedThemeColor : .gray)
  314.     }
  315.    
  316.     private var shuffleButton: some View { // Przycisk do tasowania kart
  317.         Button(action: {
  318.             viewModel.shuffleCards() // Poprawione wywołanie metody
  319.         }) {
  320.             Text("Tasuj")
  321.                 .font(.headline)
  322.                 .padding()
  323.                 .background(Color.white)
  324.                 .cornerRadius(8)
  325.                 .overlay(
  326.                     RoundedRectangle(cornerRadius: 8)
  327.                         .stroke(viewModel.selectedThemeColor, lineWidth: 2)
  328.                 )
  329.         }
  330.         .foregroundColor(viewModel.selectedThemeColor)
  331.     }
  332. }
  333.  
  334.  
  335. //CardView.swift
  336.  
  337. import SwiftUI
  338.  
  339. struct CardView: View {
  340.     let card: MemoGameModel<String>.Card // Stała karta zdefiniowana w modelu
  341.     @Binding var cardColor: Color
  342.  
  343.     var body: some View {
  344.         if card.visible {
  345.             ZStack {
  346.                 RoundedRectangle(cornerRadius: 12, style: .continuous)
  347.                     .fill(card.isFaceUp ? Color.white : cardColor)
  348.                     .frame(height: 100)
  349.                     .aspectRatio(2 / 3, contentMode: .fit)
  350.                
  351.                 if card.isFaceUp {
  352.                     Text(card.content)
  353.                         .font(.system(size: 200)) // Ustawienie dużego rozmiaru czcionki
  354.                         .minimumScaleFactor(0.01) // Zmniejszenie rozmiaru w razie potrzeby
  355.                         .aspectRatio(contentMode: .fit) // Dopasowanie proporcji
  356.                         .foregroundColor(cardColor)
  357.                     RoundedRectangle(cornerRadius: 12, style: .continuous)
  358.                         .stroke(cardColor, lineWidth: 2)
  359.                 }
  360.             }
  361.             .opacity(card.isFaceUp ? 1 : 0.7) // Przezroczystość dla zakrytych kart
  362.             .padding()
  363.             .animation(.default, value: card.isFaceUp)
  364.         }
  365.     }
  366. }
  367.  
  368.  
  369. //Themes.swift
  370.  
  371. import SwiftUI
  372.  
  373. struct Theme {
  374.     var color: Color
  375.  
  376.     static let theme1 = Theme(color: Color.blue)
  377.     static let theme2 = Theme(color: Color.green)
  378.     static let theme3 = Theme(color: Color.red)
  379. }
  380.  
  381. struct ThemeButton: View {
  382.     let title: String
  383.     let icon: String
  384.     let action: ()->Void
  385.     let color: Color
  386.  
  387.     var body: some View {
  388.         Button(action: action) {
  389.             VStack {
  390.                 Text(icon) // Ikona
  391.                     .font(.largeTitle) // Rozmiar czcionki dla ikony
  392.                     .padding() // Padding wokół ikony
  393.                     .background(Color.white) // Tło przycisku
  394.                     .clipShape(Circle()) // Kształt okręgu
  395.                     .overlay(
  396.                         Circle() // Obramowanie
  397.                             .stroke(color, lineWidth: 2)
  398.                     )
  399.                 Text(title) // Tekst przycisku
  400.                     .font(.caption) // Mniejszy rozmiar czcionki dla tekstu
  401.                     .foregroundColor(.black) // Kolor tekstu
  402.             }
  403.         }
  404.     }
  405. }
  406.  
  407.  
  408. //Item.swift
  409.  
  410. import Foundation
  411. import SwiftData
  412.  
  413. @Model
  414. final class Item {
  415.     var timestamp: Date
  416.    
  417.     init(timestamp: Date) {
  418.         self.timestamp = timestamp
  419.     }
  420. }
  421.  
Tags: swift
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement