0

有没有一种简单的方法可以在 swift/SpriteKit(库?)中使用元胞自动机创建程序关卡?我想创建一个高度为 11 个字段,宽度为 22 个字段的“洞穴”。这些应该是随机创建的,并且应该到达每个没有墙的领域。我刚刚找到了一个使用 Objective-C 的文档,我不熟悉。我花了很多时间试图理解代码并按照示例进行操作,但没有成功。

PS:如果有更简单的方法,我会欣赏一些算法

4

2 回答 2

3

我做了一个操场,你可以在那里做实验

//: Playground - noun: a place where people can play

import UIKit
import SpriteKit
import XCPlayground


class Cave {

    var cellmap:[[Bool]]

    let chanceToStartAlive = 35
    let deathLimit = 3
    let birthLimit = 4
    var xCell = 40 // number of cell in x axes
    var yCell = 20 // number of cell in y axes
    var wCell = 20 // cell width
    var hCell = 20 // cell height

    init(){
        cellmap = Array(count:yCell, repeatedValue:
            Array(count:xCell, repeatedValue:false))

        cellmap = self.initialiseMap(xCell, yIndex:yCell)
    }

    func initialiseMap(xIndex:Int, yIndex:Int) -> [[Bool]]{
        var map:[[Bool]] = Array(count:yIndex, repeatedValue:
            Array(count:xIndex, repeatedValue:false))

        for y in 0...(yIndex - 1) {
            for x in 0...(xIndex - 1) {

                let diceRoll = Int(arc4random_uniform(100))

                if diceRoll < chanceToStartAlive {
                    map[y][x] = true
                } else {
                    map[y][x] = false
                }
            }
        }
        return map
    }

    func addSprite(scene:SKScene){
        for (indexY, row) in cellmap.enumerate(){
            for (indexX, isWall) in row.enumerate(){
                if isWall {

                    let wall = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: wCell, height: hCell))
                    wall.position = CGPoint(x: (indexX * wCell) + (wCell / 2) , y: (indexY * hCell) + (hCell / 2)  )
                    scene.addChild(wall)
                }
            }
        }
    }

    func countAliveNeighbours(x:Int, y:Int) -> Int{

        var count = 0
        var neighbour_x = 0
        var neighbour_y = 0

        for i in -1...1 {

            for j in -1...1 {

                neighbour_x = x + j
                neighbour_y = y + i


                if(i == 0 && j == 0){
                } else if(neighbour_x < 0 || neighbour_y < 0 || neighbour_y >= cellmap.count || neighbour_x >= cellmap[0].count){
                    count = count + 1
                } else if(cellmap[neighbour_y][neighbour_x]){
                    count = count + 1
                }

            }

        }

        return count

    }

    func applyRules(){

        var newMap:[[Bool]] = Array(count:yCell, repeatedValue:
            Array(count:xCell, repeatedValue:false))



        for y in 0...(cellmap.count - 1) {
            for x in 0...(cellmap[0].count - 1) {
                let nbs = countAliveNeighbours( x, y: y);
                if(cellmap[y][x]){
                    if(nbs < deathLimit){
                        newMap[y][x] = false;
                    }
                    else{
                        newMap[y][x] = true;
                    }
                } else{
                    if(nbs > birthLimit){
                        newMap[y][x] = true;
                    }
                    else{
                        newMap[y][x] = false;
                    }
                }
            }
        }
        cellmap = newMap
    }
}

let view:SKView = SKView(frame: CGRectMake(0, 0, 1024, 768))

XCPShowView("Live View", view: view)

let scene:SKScene = SKScene(size: CGSizeMake(1024, 768))
scene.scaleMode = SKSceneScaleMode.AspectFit

let aCave = Cave()

aCave.applyRules()
aCave.applyRules()

aCave.addSprite(scene)
view.presentScene(scene)
于 2016-05-06T15:56:47.620 回答
1

更新了 Xcode 8 和 Swift 3 的 Playground 代码。我交换了 X 和 Y 单元格计数,因为您可能会看到“纵向”方向的视图。

记得打开助手编辑器查看结果。执行也需要一点时间,所以给它几分钟来运行算法。

//: Playground - noun: a place where people can play

import UIKit
import SpriteKit
import XCPlayground
import PlaygroundSupport


class Cave {

    var cellmap:[[Bool]]

    let chanceToStartAlive = 35
    let deathLimit = 3
    let birthLimit = 4
    var xCell = 20 // number of cell in x axes
    var yCell = 40 // number of cell in y axes
    var wCell = 20 // cell width
    var hCell = 20 // cell height

    init(){
        cellmap = Array(repeating:
            Array(repeating:false, count:xCell), count:yCell)

        cellmap = self.initialiseMap(xIndex: xCell, yIndex:yCell)
    }

    func initialiseMap(xIndex:Int, yIndex:Int) -> [[Bool]]{
        var map:[[Bool]] = Array(repeating:
            Array(repeating:false, count:xIndex), count:yIndex)

        for y in 0...(yIndex - 1) {
            for x in 0...(xIndex - 1) {

                let diceRoll = Int(arc4random_uniform(100))

                if diceRoll < chanceToStartAlive {
                    map[y][x] = true
                } else {
                    map[y][x] = false
                }
            }
        }
        return map
    }

    func addSprite(scene:SKScene){
        for (indexY, row) in cellmap.enumerated(){
            for (indexX, isWall) in row.enumerated(){
                if isWall {

                    let wall = SKSpriteNode(color: UIColor.red, size: CGSize(width: wCell, height: hCell))
                    wall.position = CGPoint(x: (indexX * wCell) + (wCell / 2) , y: (indexY * hCell) + (hCell / 2)  )
                    scene.addChild(wall)
                }
            }
        }
    }

    func countAliveNeighbours(x:Int, y:Int) -> Int{

        var count = 0
        var neighbour_x = 0
        var neighbour_y = 0

        for i in -1...1 {

            for j in -1...1 {

                neighbour_x = x + j
                neighbour_y = y + i


                if(i == 0 && j == 0){
                } else if(neighbour_x < 0 || neighbour_y < 0 || neighbour_y >= cellmap.count || neighbour_x >= cellmap[0].count){
                    count = count + 1
                } else if(cellmap[neighbour_y][neighbour_x]){
                    count = count + 1
                }

            }

        }

        return count

    }

    func applyRules(){

        var newMap:[[Bool]] = Array(repeating:
            Array(repeating:false, count:xCell), count:yCell)



        for y in 0...(cellmap.count - 1) {
            for x in 0...(cellmap[0].count - 1) {
                let nbs = countAliveNeighbours( x: x, y: y);
                if(cellmap[y][x]){
                    if(nbs < deathLimit){
                        newMap[y][x] = false;
                    }
                    else{
                        newMap[y][x] = true;
                    }
                } else{
                    if(nbs > birthLimit){
                        newMap[y][x] = true;
                    }
                    else{
                        newMap[y][x] = false;
                    }
                }
            }
        }
        cellmap = newMap
    }
}

let view:SKView = SKView(frame: CGRect(x: 0, y: 0, width: 768, height: 1024))

let scene:SKScene = SKScene(size: CGSize(width: 768, height: 1024))
scene.scaleMode = SKSceneScaleMode.aspectFit

PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = view

let aCave = Cave()

aCave.applyRules()
aCave.applyRules()

aCave.addSprite(scene: scene)
view.presentScene(scene)
于 2017-10-02T15:23:20.583 回答