Scala,将物体放在圆周上

时间:2012-01-12 05:31:59

标签: oop scala cycle

我正在尝试用等间隔的点填充圆周。这是代码(它使用了一些处理,但对理解并不重要):

class Circle (x: Float, y: Float, subdivisions: Int, radius: Float) extends WorldObject(x, y) {

  def subs = subdivisions
  def r = radius
  val d = r + r

  def makePoints() : List[Glyph] = { 
    val step = PConstants.TWO_PI / subdivisions
    val points = List.make(subdivisions, new Glyph())

    for(i <- 0 to subdivisions - 1) {
      points(i) position (PApplet.cos(step * i) * r + xPos, PApplet.sin(step * i) * r + yPos)
    }

    points
  }

  val points: List[Glyph] = makePoints()

  override def draw() {
    applet fill 0
    applet stroke 255
    applet ellipse(x, y, d, d)
    applet fill 255

    points map(_.update())
  }

}

class Glyph(x: Float, y: Float) extends WorldObject(x, y){
    def this() = this(0, 0)

    override def draw() {
      applet ellipse(xPos, yPos, 10, 10)
    }
}

object WorldObject {

}

abstract class WorldObject(var xPos: Float, var yPos: Float) {
  def this() = this(0, 0)
  def x = xPos
  def y = yPos

  def update() {
    draw()
  }

  def draw()

  def position(x: Float, y: Float) {
    xPos = x
    yPos = y
  }

  def move(dx: Float, dy: Float) {
    xPos += dx
    yPos += dy
  }
}

我得到的奇怪结果是所有点都位于一个地方。我已尝试println次检查... makePoints()方法中的检查显示一切正常,但在Circle.draw()或甚至在makePoints()显示结果后立即检查我在屏幕上看到它 - 所有点都位于一个地方,就在最后一个点生成的位置,即x=430.9017 y=204.89435,位于x=400 y=300的一个圆,并细分为5个点。所以他们都被收集到最后一个人所在的地方。

为什么会出现这种行为?我做错了什么?


UPD:我们已经找到了原因,见下文:

回答这个问题,用户未知更改了代码以使用fill方法而不是make。它们之间的主要相关区别是make预先计算它的参数而fill没有。因此make用完全相同的项填充列表。但是,fill会在每次添加时重复计算。以下是Scala源代码中这些方法的源代码:

  /** Create a list containing several copies of an element.
   *
   *  @param n    the length of the resulting list
   *  @param elem the element composing the resulting list
   *  @return     a list composed of n elements all equal to elem
   */
  @deprecated("use `fill' instead", "2.8.0")
  def make[A](n: Int, elem: A): List[A] = {
    val b = new ListBuffer[A]
    var i = 0
    while (i < n) {
      b += elem
      i += 1
    }
    b.toList
  }

fill方法:

  /** Produces a $coll containing the results of some element computation a number of times.
   *  @param   n  the number of elements contained in the $coll.
   *  @param   elem the element computation
   *  @return  A $coll that contains the results of `n` evaluations of `elem`.
   */
  def fill[A](n: Int)(elem: => A): CC[A] = {
    val b = newBuilder[A]
    b.sizeHint(n)
    var i = 0
    while (i < n) {
      b += elem
      i += 1
    }
    b.result
  }

1 个答案:

答案 0 :(得分:1)

我前后改变了很多变量(def x = ... =&gt; def x()=,x / this.x和x / xPos等等)添加了println语句并删除了(P)applet -stuff,这让编译器抱怨。

提供可编辑,可运行的独立演示将是有益的。这是:

class Circle (x: Float, y: Float, subdivisions: Int, radius: Float) 
    extends WorldObject (x, y) {

  def subs = subdivisions
  def r = radius
  val d = r + r

  def makePoints() : List[Glyph] = { 
//    val step = PConstants.TWO_PI / subdivisions
    val step = 6.283F / subdivisions
    val points = List.fill (subdivisions) (new Glyph ())
    for (i <- 0 to subdivisions - 1) {
//      points (i) position (PApplet.cos (step * i) * r + xPos, 
//          PApplet.sin (step * i) * r + yPos)
                val xx = (math.cos (step * i) * r).toFloat + xPos
                val yy = (math.sin (step * i) * r).toFloat + yPos
                println (xx + ": " + yy)
      points (i) position (xx, yy)
    }
    points
  }

  val points: List [Glyph] = makePoints ()
  override def draw () {
  /*
    applet fill 0
    applet stroke 255
    applet ellipse(x, y, d, d)
    applet fill 255
  */
//    println ("Circle:draw () upd-> " + super.x () + "\t" + y () + "\t" + d); 
    points map (_.update ())
    println ("Circle:draw () <-upd " + x + "\t" + y + "\t" + d); 
  }
}

class Glyph (x: Float, y: Float) extends WorldObject (x, y) {
    def this () = this (0, 0)
    override def draw() {
      // applet ellipse (xPos, yPos, 10, 10)
      println ("Glyph:draw (): " + xPos + "\t" + yPos + "\t" + 10); 
    }
}

object Circle {
    def main (as: Array [String]) : Unit = {
        val c = new Circle (400, 300, 5, 100)
        c.draw ()       
    }
}

object WorldObject {

}

abstract class WorldObject (var xPos: Float, var yPos: Float) {

  def this () = this (0, 0)
  def x = xPos
  def y = yPos

  def update () {
    draw ()
  }

  def draw ()

  def position (x: Float, y: Float) {
    xPos = x
    yPos = y
    // println (x + " ?= " + xPos + " ?= " + (this.x ()))
  }

  def move (dx: Float, dy: Float) {
    xPos += dx
    yPos += dy
  }
}

我的结果是:

500.0: 300.0
430.9052: 395.1045
319.10266: 358.78452
319.09177: 241.23045
430.8876: 204.88977
Glyph:draw (): 500.0    300.0   10
Glyph:draw (): 430.9052 395.1045    10
Glyph:draw (): 319.10266    358.78452   10
Glyph:draw (): 319.09177    241.23045   10
Glyph:draw (): 430.8876 204.88977   10
Circle:draw () <-upd 400.0  300.0   200.0

你能发现差异吗?

您应该创建代码的副本,并逐步删除代码,这不是重现错误,检查错误是否仍然存在的必要条件。然后你应该达到一个小得多的问题,或者自己找出错误。