我正在开发一个非常简单的快速游戏。游戏的主要布局是具有 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)
}
}
最佳答案
使用 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
}
最后,您可以在 UICollectionViewDataSource
和 UICollectionViewDelegate
方法中使用这个新的数据模型:
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/