Реализация игры жизнь Конвея с скала


Я попытался создать оптимальные с точки зрения производительности и потребления память. Но и я старался сделать его функциональным и путь Scala. Я хочу сделать вам замечание о том, как сделать его более'stic скала

object LifeGame extends App {
    trait Matrix extends Iterable[(Int, Int)] {
        def apply(p: (Int, Int)): Boolean
        def update(p: (Int, Int), b: Boolean): Unit
        def newInstance: Matrix;
    }

    class SparseMapMatrix extends Matrix {
        type Point = (Int, Int)

        private var data = Set[(Int, Int)]()

        def apply(p: Point): Boolean = data.contains(p)

        def update(p: Point, b: Boolean) = if (b) data += p else data -= p

        def newInstance = new SparseMapMatrix()

        def iterator = data.iterator

        override def toString() = {
            val sb = new StringBuilder()
            def best(func: (Int, Int) => Int)(p1: Point, p2: Point) = (func(p1._1, p2._1), func(p1._2, p2._2))
            val minBoundary = ((0, 0) /: iterator)(best(math.min))
            val maxBoundary = ((0, 0) /: iterator)(best(math.max))
            for (i <- minBoundary._1 to maxBoundary._1) {
                sb.append("\n")
                for (j <- minBoundary._2 to maxBoundary._2) {
                    sb.append(if (this((i, j))) "x" else " ")
                }
            }
            sb.append("\nmin=%s, max=%s" format(minBoundary, maxBoundary))
            sb.toString()
        }
    }

    object Engine {
        def apply(input: Matrix): Matrix = {
            val result = input.newInstance
            def block2D(pp: (Int, Int)): Seq[(Int, Int)] =
                for (ii <- block1D(pp._1); jj <- block1D(pp._2)) yield (ii, jj)
            val liveCells = for (p <- input.iterator.flatMap(block2D).toSet[(Int, Int)].par) yield {
                val offsets = block2D(p).filter(_ != p)
                val nn = offsets.map(p => input(p)).count(_ == true)
                case class State(l: Boolean, n: Int)
                val newValue = State(input(p), nn) match {
                    case State(true, n) if n < 2 => false
                    case State(true, 2) | State(true, 3) => true
                    case State(true, n) if n > 3 => false
                    case State(false, 3) => true
                    case State(value, _) => value
                };
                 if(newValue) Some(p) else None
            }
            liveCells.seq.foreach { _ match { case Some(p:Point) => result(p) = true; case _ => ;}}
            result
        }
    }

    def block1D(i: Int) = i - 1 to i + 1

}


755
6
задан 1 октября 2011 в 01:10 Источник Поделиться
Комментарии
1 ответ

Главное-вещи, которые я изменил:


  • Матрица теперь совершенно неизменным

  • Код самодокументируемым (экстракт сложного кода для методов и т. д.)

  • Я удалил ненужное наследство

  • Я не люблю применять-методы, которые используются как содержит-методы -> изменить имя

  • Я удалил скобки в побочный эффект бесплатными методами

  • Множество улучшений синтаксис

Код:

object LifeGame extends App {
case class Point(x: Int = 0, y: Int = 0)

object Matrix {
def empty: Matrix =
Matrix(Set.empty)
}

case class Matrix(private val data: Set[Point]) {

def contains(p: Point): Boolean =
data contains p

def update(p: Point, b: Boolean) =
if (b) copy(data+p) else copy(data-p)

def iterator: Iterator[Point] =
data.iterator

override def toString = {
def best(func: (Int, Int) => Int)(p1: Point, p2: Point) =
Point(func(p1.x, p2.x), func(p1.y, p2.y))

val minBoundary = (Point() /: iterator) { best(math.min) }
val maxBoundary = (Point() /: iterator) { best(math.max) }

val sb = StringBuilder.newBuilder
for (i <- minBoundary.x to maxBoundary.x) {
sb.append("\n")
for (j <- minBoundary.y to maxBoundary.y) {
sb.append(if (this contains Point(i, j)) "x" else " ")
}
}
sb.append("\nmin=%s, max=%s" format (minBoundary, maxBoundary))
sb.toString
}
}

object Engine {

def newCell: (Boolean, Int) => Boolean = {
case (true, 0 | 1) => false
case (true, 2 | 3) => true
case (true, _) => false
case (false, n) => n == 3
}

def apply(input: Matrix): Matrix = {
def block1D(i: Int) =
Seq(i-1, i, i+1)

def block2D(p: Point) =
for (x <- block1D(p.x); y <- block1D(p.y)) yield Point(x, y)

def points =
(input.iterator flatMap block2D).toSet.par

def calcCell(p: Point) = {
val neighbours = block2D(p) filter { p != }
val alive = neighbours map { input contains } count { true == }

if (newCell(input contains p, alive)) Some(p)
else None
}

val cells = (points map calcCell).seq collect { case Some(p) => p }
(Matrix.empty /: cells) { (result, p) => result(p) = true }
}
}
}

4
ответ дан 1 октября 2011 в 04:10 Источник Поделиться