ios - 点击时禁用 UICollectionViewCell,并随机化单元格

标签 ios swift random uicollectionview cell

我正在开发一个非常简单的快速游戏。游戏的主要布局是具有 16 个单元格(门)的 UICollectionView。其中 1 个单元格(门)是一个游戏结束单元格。除了 game over cell 之外,您还需要点击(打开)所有门。如果一个 game over cell 被点击,细胞将全部随机化,你会失去一条生命。如果你打开除了 game over cell 之外的所有门,你就赢了。

我的代码如下。

什么有效?

  • 在初始加载时,门会通过一系列 15 个 DoorIdentifier 和 1 个 GameOverIdentifier。我就是这样 检测细胞游戏。

什么不起作用?

  • 如果我点击一些普通的门(以禁用它们),然后点击游戏 在门上,它会左右移动门(应该如此),但随后 其他随机门被禁用并看起来启用(通过 1.0 alpha)。不打算。

  • 如果我点击一些普通的门(以禁用它们),然后点击 Game Over 门,所有门都变为 1.0 alpha,只有一些有 启用交互。此外,按下游戏结束门后, 有时只有一扇门会保持 0.2 alpha。

我需要什么? 当一扇普通的门被敲击时,该单元格现在将始终被禁用。如果门上的游戏被点击,它将忽略已经被点击的单元格,因为它们应该“退出游戏”。

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

@IBOutlet weak var mainCollectionView: UICollectionView!


var gameOverDoorArray = ["GameOverIdentifier"]
var normalDoors = ["DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier", "DoorIdentifier"]
var reuseIdentifiers = [String]()
var livesLeftCounter = 3


@IBAction func randomizeButton(sender: UIButton) {
    randomizeReuseIdentifiers()
}

override func viewDidLoad() {
    super.viewDidLoad()
    mainCollectionView.dataSource = self
    mainCollectionView.delegate = self
    mainCollectionView.backgroundColor = UIColor.clearColor()

    reuseIdentifiers = gameOverDoorArray + normalDoors

    randomizeReuseIdentifiers()
}


func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return reuseIdentifiers.count
}


func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let identifier = reuseIdentifiers[indexPath.item]
    let cell: DoorCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(identifier, forIndexPath: indexPath) as! DoorCollectionViewCell

    cell.backgroundColor = UIColor(patternImage: UIImage(named: "doorClosedImage")!)

    return cell
}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let currentCell = mainCollectionView.cellForItemAtIndexPath(indexPath) as UICollectionViewCell!



    // Game Over door was pressed!
    if reuseIdentifiers[indexPath.item] == "GameOverIdentifier" {
        gameOverDetection()
        randomizeReuseIdentifiers()
        mainCollectionView.reloadData()
    }

    // Normal door was pressed!
    else if reuseIdentifiers[indexPath.item] == "DoorIdentifier"{
        if currentCell.userInteractionEnabled && (normalDoors.count > 0){
            currentCell.alpha = 0.2
            print("reuse ID's array - \(reuseIdentifiers)")
            // when all the above is done, the button gets disabled.
            currentCell.userInteractionEnabled = false
            // Remove last item in normalDoors Array.
            normalDoors.removeLast()
        }

        print("Array count of allTheDoors - \(reuseIdentifiers.count).")
    }



}


func randomizeReuseIdentifiers() {
    var randomized = [String]()

    for _ in reuseIdentifiers {
        let random = reuseIdentifiers.removeAtIndex(Int(arc4random_uniform(UInt32(reuseIdentifiers.count))))
        randomized.append(random)
    }

    reuseIdentifiers = randomized

}

func gameOverDetection() {
    livesLeftCounter -= 1
    if livesLeftCounter < 0 {
        print("GAME OVER!")
    }
    print(livesLeftCounter)
}

}

Screenshot of layout

最佳答案

使用 UICollectionView 时(以及通常使用 MVC 时)最好将您要使用的所有数据与 View 分开存储。每扇门都有一些游戏状态属性,您当前正尝试使用 UICollectionViewCell 上的属性来存储这些属性。这是不正确的。您应该创建一个模型(我们称它为 Door),并使用该模型的属性来存储您的游戏状态。

首先,创建一个带有嵌套枚举的类来存储门的类型。

class Door {
    enum Type {
        case Normal
        case GameOver
    }

    var type: Type

    init(type: Type) {
        self.type = type
    }
}

然后,您需要存储每个 Door 的打开/关闭状态:

class Door {
    enum Type {
        case Normal
        case GameOver
    }

    var type: Type

    var closed = true

    init(type: Type) {
        self.type = type
    }
}

最后,您应该编写一个方法或计算属性来为每种返回适当的重用标识符。

class Door {
    enum Type {
        case Normal
        case GameOver
    }

    var type: Type

    var closed = true

    var reuseIdentifier: String {
        switch type {
        case .Normal:
            return "DoorIdentifier"
        case .GameOver:
            return "GameOverIdentifier"
        default:
            return ""
    }

    init(type: Type) {
        self.type = type
    }
}

然后您将初始化模型对象数组,而不是初始化reuseIdentifiers 数组。

var doors = [Door]()

override func viewDidLoad() {
    super.viewDidLoad()

    // Your other initialization in viewDidLoad here...

    doors = [Door(.Normal), Door(.Normal), /* etc... */ Door(.GameOver)]
}

然后您需要重写 randomizeReuseIdentifiers 以随机化 doors

func randomizeDoors() {
    var randomized = [Door]()

    for _ in doors {
        let random = doors.removeAtIndex(Int(arc4random_uniform(UInt32(doors.count))))
        randomized.append(random)
    }

    doors = randomized
}

最后,您可以在 UICollectionViewDataSourceUICollectionViewDelegate 方法中使用这个新的数据模型:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return reuseIdentifiers.count
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let door = doors[indexPath.item]
    let identifier = door.reuseIdentifier
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(identifier, forIndexPath: indexPath) as! DoorCollectionViewCell

    // Here, use the closed property to set interaction enabled and alpha.
    if door.closed {
        cell.userInteractionEnabled = true
        cell.alpha = 1.0
    } else {
        cell.userInteractionEnabled = false
        cell.alpha = 0.2    
    }

    cell.backgroundColor = UIColor(patternImage: UIImage(named: "doorClosedImage")!)
    return cell
}     

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let currentCell = mainCollectionView.cellForItemAtIndexPath(indexPath) as UICollectionViewCell!
    let door = doors[indexPath.item]

    switch door.type {
    case .Normal:
        // Set the door to opened, so it is disabled on the next reload.
        door.closed = false
    case .GameOver:
        gameOverDetection()
        randomizeDoors()            
    }

    mainCollectionView.reloadData()
}

总的来说,我认为在您继续学习的过程中阅读更多关于 Model View Controller (MVC) 模式的内容会对您有所帮助。苹果有some documentation that might be helpful , 你可能会发现 these resources也是说明性的。

关于ios - 点击时禁用 UICollectionViewCell,并随机化单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36845527/

相关文章:

random - 慢速随机种子生成器——为什么?

c++ - 不涉及时间的 rand() 种子?

ios - 如何在 UICollectionView Swift 中显示多个图像

ios - 在 Swift 的 Alamofire 中通过查询获取 http 请求

iphone - 如何使用字符串值获取 NSArray 中对象的索引?

ios - 如何为 iOS AVFoundation 定义自定义检测器?

ios - 在 NSUserDefaults 中存储字典并使用存储的数据。

r - 给定 R 中的特定概率值生成随机数(0 和 1)

objective-c - 如何在触摸按钮时更改 UIButton 图像

ios - Swift 中不同时间间隔刷新 TableView Cell 从 URL 获取数据