2016-04-25 55 views
1

我正在研究一个非常简单的快速游戏。游戏的主要布局是带有16个单元(门)的UICollectionView。其中1个单元(门)是单元格上的游戏。您需要点击(打开)除单元格上的游戏以外的所有门。如果一个单元格的游戏被挖掘,细胞将全部随机化,并且你失去了生命。如果你打开了除单元格游戏之外的所有门,你就赢了。在水龙头禁用UICollectionViewCell,并随机化单元格

我的代码如下。

什么工作?

  • 在初始负载,门得到与 15 DoorIdentifier和1个GameOverIdentifier的阵列适当随机化。这就是我在 上通过单元格检测游戏的方式。

什么不行?

  • 如果我对一些正常的门点按(禁用它们),然后点击在游戏 在门,它周围洗牌门(因为它应该),但随后 其他随机门打开禁用,看启用(由1.0阿尔法)。不打算。

  • 如果我对一些正常的门点按(禁用它们),然后点击在游戏结束的门,所有的门变成1.0α,只有一些启用 互动。此外,在按下游戏结束门后,有时只有1个门将保持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

+0

我不明白你的游戏的所有细节,但我看了看代码,发现了一些可能导致这些问题的缺陷。请注意,您使用单元格本身来存储有关是否启用此门的信息。它不会工作。您应该创建一些属性(可能是数组),并将其存储在其中,而不是单元格中。在'cellForItemAtIndexPath'里面,你需要根据这个数组的信息更新单元格的状态。 –

+0

通过保持重用标识符阵列看起来很奇怪,还存储游戏在单元格上的信息。你只需要1个数字。 –

回答

2

UICollectionView工作,(和一般使用MVC时),最好所有的存储你会从视图分开来处理的数据的。每个门都有几个游戏状态属性,您目前正尝试使用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 
    } 
} 

最后,你应该写一个方法或计算的属性返回相应的重用标识符为每一种Door

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() 
} 

在一般情况下,我认为这将有利于你读多一点模型 - 视图 - 控制器( MVC)模式,继续学习。苹果有some documentation that might be helpful,您也可能会发现theseresources也是说明性的。

+0

感谢您的帮助。但是,在你的代码中出现一些错误。 “var closed = true”枚举可能不包含存储的属性“/ var reuseIdentifier”计算属性必须具有显式类型“/ randomized.append(random)”无法将类型'ViewController.Door'的值转换为期望的参数类型'string'/门=随机化“无法指定类型'[String]'的值来键入'[ViewController.Door]'” – Joe

+0

修复了这些问题。对不起 - 在发布之前未运行此代码。 –

+0

你好!我得到了这个工作。你的代码中有几个小问题,但是我把它们解决了。 Door类中的reuseIdentifier缺少一个紧密支架/门阵列需要的类型: - Door(type:.Normal)/ currentCell不需要在didSelectItemAtIndexPath中声明。还有一个问题。如果“游戏结束”门被挖掘,它将洗牌整个收集视图。是否有可能只是洗牌所有关闭的门,以便开放(alpha 1.0 /启用)门不会转移? – Joe