我正在通过斯坦福大学的iOS课程学习CS193P。我刚刚完成了第一次作业,并希望能进行代码评审,因为由于课程已经完成,我实际上无法提交作业以获得反馈。
需求可以在这里找到。但是任何关于最佳实践和我植入的建议都是有帮助的。该应用程序工作,并处于一个状态,我会提交,如果我可以。我只是在找另一双眼睛。
import Foundation
/**
a game card that contains the following var:
- isFaceUp
- isMatched
- identifier
*/
struct Card: Hashable
{
var hashValue: Int {
return identifier
}
static func == (lhs: Card, rhs: Card) -> Bool {
return lhs.identifier == rhs.identifier
}
var isFaceUp = false
var isMatched = false
private var identifier: Int
private static var identifierFactory = 0
private static func getUniqueIdentifer() -> Int {
identifierFactory += 1
return identifierFactory
}
init(){
self.identifier = Card.getUniqueIdentifer()
}
}
import Foundation
struct Concentration
{
private(set) var cards = [Card]()
private(set) var score = 0
private(set) var flipCount = 0
private var indexOfOneAndOnlyFaceUp: Int? {
get {
return cards.indices.filter({cards[$0].isFaceUp}).oneAndOnly
}
set {
for flipDownIndex in cards.indices {
cards[flipDownIndex].isFaceUp = (flipDownIndex == newValue)
}
}
}
private var selectedIndex = Set<Int>()
private var lastIndexWasSelected = false
/// returns true if all cards have been matched
var allCardsHaveBeenMatched: Bool {
for index in cards.indices {
if !cards[index].isMatched { return false }
}
return true
}
/**
Choose a card at an index.
Handles flip count, if a card is faced up, and matching of cards
*/
mutating func chooseCard(at index: Int){
assert(cards.indices.contains(index), "Concentration.chooseCard(at:\(index)): index is not in the cards")
let cardWasPreviouslySelected = selectedIndex.contains(index)
if !cards[index].isMatched {
// only flip cards that are visible
flipCount += 1
if let matchIndex = indexOfOneAndOnlyFaceUp, matchIndex != index {
// 2 cards are face up, check if cards match
if cards[index] == cards[matchIndex] {
cards[index].isMatched = true
cards[matchIndex].isMatched = true
if lastIndexWasSelected {
// add extra to account for subtracting earlier
score += 3
} else {
score += 2
}
}else {
// no match
if cardWasPreviouslySelected {score -= 1}
}
cards[index].isFaceUp = true
} else {
// one card is selected, turn down other cards and set this card
if cardWasPreviouslySelected { score -= 1 }
indexOfOneAndOnlyFaceUp = index
lastIndexWasSelected = cardWasPreviouslySelected
}
}
selectedIndex.insert(index)
}
init(numberOfPairsOfCards: Int){
assert(numberOfPairsOfCards > 0, "Concentraation.init(numberOfPairsOfCards:\(numberOfPairsOfCards) you must have multiple pairs of cards")
for _ in 0..<numberOfPairsOfCards {
let card = Card()
cards += [card, card]
}
shuffleCards()
}
mutating private func shuffleCards() {
for _ in 0..<cards.count {
// sort seems better than .swap()
cards.sort(by: {_,_ in arc4random() > arc4random()})
}
}
}
extension Collection {
var oneAndOnly: Element? {
return count == 1 ? first : nil
}
}
import Foundation
class Theme
{
enum Theme: UInt32 {
case halloween
case love
case animal
case waterCreatures
case plants
case weather
}
/// get an array of icons by theme
func getThemeIcons(by theme: Theme) -> [String] {
switch theme {
case .halloween:
return ["", "", "", "", "", "☠️", "", ""]
case .love:
return ["","", "", "", "❤️", "", "", ""]
case .animal:
return ["", "", "", "", "", "", "", ""]
case .waterCreatures:
return ["", "", "", "", "", "", "", ""]
case .plants:
return ["", "", "", "", "", "", "", ""]
case .weather:
return ["", "❄️", "☀️", "", "☔️", "", "☁️", "", "⛈"]
}
}
private func random() -> Theme {
let max = Theme.weather.rawValue
let randomIndex = arc4random_uniform(max + UInt32(1))
return Theme(rawValue: randomIndex) ?? Theme.halloween
}
/**
get a random array of themed icons
- Author:
Anna
*/
func getRandomThemeIcons() ->[String] {
return getThemeIcons(by: random())
}
}
import UIKit
class ViewController: UIViewController {
private lazy var game = Concentration(numberOfPairsOfCards: numberOfPairsOfCards)
var numberOfPairsOfCards: Int {
return (cardButtons.count + 1) / 2
}
@IBOutlet weak var finishedLabel: UILabel!
@IBOutlet weak var scoreCountLabel: UILabel!
@IBOutlet weak var flipCountLabel: UILabel!
private var flipCount = 0 {
didSet {
flipCountLabel.text = "Flip Count: \(flipCount)"
}
}
private var scoreCount = 0 { didSet { scoreCountLabel.text = "Score: \(scoreCount)"} }
@IBOutlet var cardButtons: [UIButton]!
@IBAction func touchCard(_ sender: UIButton) {
if let cardNumber = cardButtons.index(of: sender){
game.chooseCard(at: cardNumber)
updateViewFromModel()
}else {
print("card is not in cardButton array")
}
}
@IBAction func touchNewGame(_ sender: UIButton) {
// reset game
game = Concentration(numberOfPairsOfCards: (cardButtons.count + 1) / 2)
// reset theme choices
emojiChoices = theme.getRandomThemeIcons()
// update view
updateViewFromModel()
}
private func updateViewFromModel(){
flipCount = game.flipCount
scoreCount = game.score
for index in cardButtons.indices {
let button = cardButtons[index]
let card = game.cards[index]
if card.isFaceUp {
button.setTitle(emoji(for: card), for: UIControlState.normal)
button.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
} else {
button.setTitle("", for: UIControlState.normal)
button.backgroundColor = card.isMatched ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0) : #colorLiteral(red: 1, green: 0.5763723254, blue: 0, alpha: 1)
}
}
finishedLabel.textColor = game.allCardsHaveBeenMatched ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) : #colorLiteral(red: 0.9999960065, green: 1, blue: 1, alpha: 0)
finishedLabel.text = game.score >= 0 ? "Nice work! " : "Phew, ly made it"
}
private var theme = Theme()
private lazy var emojiChoices = theme.getRandomThemeIcons()
private var emoji = [Card: String]()
private func emoji(for card: Card) -> String {
if emoji[card] == nil, emojiChoices.count > 0 {
emoji[card] = emojiChoices.remove(at: emojiChoices.count.arc4random)
}
return emoji[card] ?? "?"
}
}
extension Int {
var arc4random: Int {
if self > 0 {
return Int(arc4random_uniform(UInt32(self)))
} else if self < 0 {
return -Int(arc4random_uniform(UInt32(abs(self))))
}else {
return 0
}
}
}发布于 2018-05-29 19:36:35
我几乎没有笔记:
import Foundation
struct Concentration
{
private(set) var cards = [Card]()
private(set) var score = 0var allCardsHaveBeenMatched: Bool {
for index in cards.indices {
if !cards[index].isMatched { return false }
}
return true
}更好/更短版本:
var allCardsHaveBeenMatched: Bool { !cards.contains(where: { !$0.isMatched } }/**
Choose a card at an index.
Handles flip count, if a card is faced up, and matching of cards
*/
mutating func chooseCard(at index: Int){private static var identifierFactory = 0
private static func getUniqueIdentifer() -> Int {
identifierFactory += 1
return identifierFactory
}可以这样重写(使用枚举而不包含类):
import Foundation
enum Theme: UInt32 {
case halloween
case love
case animal
case waterCreatures
case plants
case weather
/// get an array of icons by theme
var icons: [String] {
switch self {
case .halloween:
return ["", "", "", "", "", "☠️", "", ""]
case .love:
return ["","", "", "", "❤️", "", "", ""]
case .animal:
return ["", "", "", "", "", "", "", ""]
case .waterCreatures:
return ["", "", "", "", "", "", "", ""]
case .plants:
return ["", "", "", "", "", "", "", ""]
case .weather:
return ["", "❄️", "☀️", "", "☔️", "", "☁️", "", "⛈"]
}
}
static func randomTheme() -> Theme {
let max = Theme.weather.rawValue
let randomIndex = arc4random_uniform(max + UInt32(1))
return Theme(rawValue: randomIndex) ?? Theme.halloween
}
}总结一下:您的代码还不错,但是需要一些改进。您正在使用封装来隐藏实现细节,并且比引用类型(类)更喜欢值类型(如structs)。这是很好的陈述点!
PS:欢迎来到代码审查!!
https://codereview.stackexchange.com/questions/195113
复制相似问题