2016-04-25 9 views
1

私は非常に簡単な迅速なゲームに取り組んでいます。ゲームの主なレイアウトは、16個のセル(ドア)を持つUICollectionViewです。セル(ドア)の1つは、セル上のゲームです。あなたは、セル上のゲーム以外のすべてのドアをタップ(開く)する必要があります。セル上のゲームがタップされると、セルはすべてランダム化され、あなたは人生を失います。あなたがセル上のゲーム以外のドアをすべて開くと、あなたは勝ちます。タップでUICollectionViewCellを無効にし、セルをランダム化

私のコードは以下の通りです。

どんな機能がありますか?初期ロードで

  • 、ドアが 15 DoorIdentifierと1 GameOverIdentifierの配列を適切にランダム化します。これは私がどのように細胞上のゲームを検出している です。

どうしますか?

  • 私はドアゲームオーバー をタップし、次に、(それらを無効にする)いくつかの通常のドアをタップすると、それは周りのドア(それが必要として)をシャッフルしたが、その後 他のランダムドアが無効になって、ルックを有効にしました(1.0アルファ)。意図していません。

  • 普通のドアをタップして(無効にする)、Game Overドアをタップすると、すべてのドアが1.0アルファになり、一部では の対話が有効になります。さらに、Game Overドアを押した後に、 のドアがたった1つのドアで0.2アルファを維持することがあります。

私に必要なもの 通常のドアがタップされると、そのセルは常に無効になります。ドアの上にあるゲームがタップされた場合、既にタップされていたセルは無視されます。「ゲームプレイから外れる」必要があります。

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 

    var closed = true 

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

最後に:

class Door { 
    enum Type { 
     case Normal 
     case GameOver 
    } 

    var type: Type 

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

その後、あなたは各Doorのためのオープン/クローズ状態を保存する必要があります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)] 
} 

あなたは、代わりにdoorsをランダム化するrandomizeReuseIdentifiersを書き換える必要があります。

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 reuseIdentifier"計算されたプロパティは明示的な型 "/ randomized.append(random)"を必要とする "ViewController.Door"型の値を期待される引数型 'string'に変換できません/ doors = randomized "'[ViewController.Door]'をタイプするには '[String]'タイプの値を割り当てることができません" – Joe

+0

問題を修正しました。申し訳ありません - 投稿する前にこのコードを実行しませんでした。 –

+0

あなたはロック!私はこれを仕事にしました。あなたのコードにはいくつかの小さな問題がありましたが、私はそれらをアイロンで取り出しました。 DoorクラスのreuseIdentifierには、ブラケット/ドア配列が必要な型が閉じていませんでした。 - Door(type:.Normal)/ currentCellはdidSelectItemAtIndexPathで宣言する必要はありませんでした。しかしもう1つの質問.. "ゲームオーバー"ドアをタップすると、コレクションビュー全体がシャッフルされます。すべての閉じたドアをシャッフルするだけで、開いている(アルファ1.0 /有効にされた)ドアが動かないようにすることはできますか? – Joe

関連する問題