Aquest article descriu el procés de creació d'un joc d'entrenament de memòria senzill que m'agrada molt. A més de ser bo en si mateix, aprendreu una mica més sobre les classes i els protocols de Swift a mesura que aneu. Però abans de començar, entenem el joc en si.
Recordem:per a tots els lectors de "Habr": un descompte de 10 rubles en inscriure's a qualsevol curs de Skillbox amb el codi promocional "Habr".
El joc comença amb una demostració d'un joc de cartes. Es troben boca avall (respectivament, imatge avall). Quan feu clic a qualsevol, la imatge s'obre durant uns segons.
La tasca del jugador és trobar totes les cartes amb les mateixes imatges. Si després d'obrir la primera targeta, gireu la segona i les imatges coincideixen, ambdues cartes romandran obertes. Si no coincideixen, les cartes es tornen a tancar. L'objectiu és obrir-ho tot.
Estructura del projecte
Per crear una versió senzilla d'aquest joc, necessiteu els components següents:
Un controlador: GameController.swift.
Una vista: CardCell.swift.
Dos models: MemoryGame.swift i Card.swift.
Main.storyboard per garantir que tot el conjunt de components estigui disponible.
Comencem amb el component més senzill del joc, les cartes.
Card.swift
El model de targeta tindrà tres propietats: id per identificar cadascuna, una variable booleana mostrada per especificar l'estat de la targeta (ocult o oberta) i artworkURL per a les imatges de les targetes.
class Card {
var id: String
var shown: Bool = false
var artworkURL: UIImage!
}
També necessitareu aquests mètodes per controlar la interacció de l'usuari amb els mapes:
Mètode per mostrar una imatge en una targeta. Aquí restablirem totes les propietats per defecte. Per a l'identificador, generem un identificador aleatori cridant a NSUUIS().uuidString.
El segon model és MemoryGame, aquí establim una graella de 4*4. El model tindrà propietats com ara cartes (una matriu de cartes en una graella), una matriu cardsShown amb cartes ja obertes i una variable booleana isPlaying per fer un seguiment de l'estat del joc.
class MemoryGame {
var cards:[Card] = [Card]()
var cardsShown:[Card] = [Card]()
var isPlaying: Bool = false
}
També hem de desenvolupar mètodes per controlar la interacció de l'usuari amb la xarxa.
Aquest mètode llegeix l'últim element de la matriu **cardsShown** i retorna la targeta que no coincideix.
func didSelectCard(_ card: Card?) {
guard let card = card else { return }
if unmatchedCardShown() {
let unmatched = unmatchedCard()!
if card.equals(unmatched) {
cardsShown.append(card)
} else {
let secondCard = cardsShown.removeLast()
}
} else {
cardsShown.append(card)
}
if cardsShown.count == cards.count {
endGame()
}
}
Main.storyboard i GameController.swift
Main.storyboard té un aspecte semblant a això:
Inicialment, heu de configurar el nou joc com a viewDidLoad al controlador, incloses les imatges per a la graella. Al joc, tot això estarà representat per 4*4 collectionView. Si encara no esteu familiaritzat amb collectionView, aquí el teniu podeu obtenir la informació que necessiteu.
Configurarem el GameController com a controlador arrel de l'aplicació. El GameController tindrà una collectionView a la qual farem referència com a IBOutlet. Una altra referència és al botó IBAction onStartGame(), aquest és un UIButton, el podeu veure al guió gràfic anomenat PLAY.
Una mica sobre la implementació dels controladors:
Primer, inicialitzem dos objectes principals: la quadrícula: joc = Joc de memòria() i un conjunt de cartes: targetes = [Targeta]().
Establem les variables inicials com viewDidLoad, aquest és el primer mètode que es crida mentre el joc s'executa.
collectionView està configurat com a amagat perquè totes les cartes estan amagades fins que l'usuari prem PLAY.
Tan bon punt premem PLAY, s'inicia la secció IBAction onStartGame i establim la propietat collectionView isHidden en false perquè les cartes puguin ser visibles.
Cada vegada que l'usuari selecciona una targeta, es crida al mètode didSelectItemAt. En el mètode que anomenem didSelectCard per implementar la lògica principal del joc.
Aquí teniu la implementació final de GameController:
Treballar amb protocols és el nucli de la programació Swift. Els protocols ofereixen la capacitat de definir regles per a una classe, estructura o enumeració. Aquest principi us permet escriure codi modular i extensible. De fet, aquest és un patró que ja estem implementant per a collectionView a GameController. Ara fem la nostra pròpia versió. La sintaxi serà així:
protocol MemoryGameProtocol {
//protocol definition goes here
}
Sabem que un protocol ens permet definir regles o instruccions per implementar una classe, així que pensem quines haurien de ser. Necessites quatre en total.
Inici del joc: memoryGameDidStart.
Heu de girar la targeta cap avall: memoryGameShowCards.
Heu de girar la targeta cap avall: memoryGameHideCards.
Final del joc: memoryGameDidEnd.
Els quatre mètodes es poden implementar per a la classe principal, que és GameController.
memoryGameDidStart
Quan s'executa aquest mètode, el joc hauria de començar (l'usuari prem PLAY). Aquí simplement tornarem a carregar el contingut cridant a collectionView.reloadData(), que barrejarà les targetes.
Anomenem aquest mètode des de la col·lecció SDViewSelectItemAt. Primer mostra la targeta seleccionada. A continuació, comprova si hi ha una targeta no coincident a la matriu cardsShown (si el nombre de cardsShown és senar). Si n'hi ha una, es compara la targeta seleccionada amb ella. Si les imatges són les mateixes, les dues cartes s'afegeixen a les targetes Mostrades i es mantenen boca amunt. Si és diferent, la carta deixa cartes Mostrades i totes dues es tornen cap avall.
memoryGameHideCards
Si les targetes no coincideixen, s'anomena aquest mètode i s'amaguen les imatges de les targetes.
mostrat = fals.
memoryGameDidEnd
Quan es crida aquest mètode, vol dir que totes les cartes ja estan revelades i estan a la llista cardsShown: cardsShown.count = cards.count, de manera que el joc s'ha acabat. El mètode es crida específicament després d'haver cridat endGame() per establir la variable isPlaying a false, després de la qual cosa es mostra el missatge de finalització del joc. També alertController s'utilitza com a indicador per al controlador. Es crida a viewDidDisappear i es restableix el joc.
A continuació es mostra com es veu tot a GameController:
extension GameController: MemoryGameProtocol {
func memoryGameDidStart(_ game: MemoryGame) {
collectionView.reloadData()
}
func memoryGame(_ game: MemoryGame, showCards cards: [Card]) {
for card in cards {
guard let index = game.indexForCard(card)
else { continue
}
let cell = collectionView.cellForItem(
at: IndexPath(item: index, section:0)
) as! CardCell
cell.showCard(true, animted: true)
}
}
func memoryGame(_ game: MemoryGame, hideCards cards: [Card]) {
for card in cards {
guard let index = game.indexForCard(card)
else { continue
}
let cell = collectionView.cellForItem(
at: IndexPath(item: index, section:0)
) as! CardCell
cell.showCard(false, animted: true)
}
}
func memoryGameDidEnd(_ game: MemoryGame) {
let alertController = UIAlertController(
title: defaultAlertTitle,
message: defaultAlertMessage,
preferredStyle: .alert
)
let cancelAction = UIAlertAction(
title: "Nah", style: .cancel) {
[weak self] (action) in
self?.collectionView.isHidden = true
}
let playAgainAction = UIAlertAction(
title: "Dale!", style: .default) {
[weak self] (action) in
self?.collectionView.isHidden = true
self?.resetGame()
}
alertController.addAction(cancelAction)
alertController.addAction(playAgainAction)
self.present(alertController, animated: true) { }
resetGame()
}
}
De fet, això és tot. Podeu utilitzar aquest projecte per crear la vostra pròpia versió del joc.