Scala.use(better)《tips433》Hexothello

App15Window.scala

/*
 * Copyright (c) 2010-2013, KOTSUBU-chan and/or its affiliates.
 * Copyright (c) 1998, Atelier-AYA.
 * All rights reserved.
 */ 
package cherry.pie

// ----------------------------------------
import swing._
object App15Window extends MainFrame {
  val version =          App15Window
    .getClass.getName+": #1.0.02 J"
  // ----------------------------------------
  title = "15 puzzle"
  contents = new App15View(new Dimension(200,200))
  peer.setLocationRelativeTo(null)
}

// ----------------------------------------
class App15View(size: Dimension) extends FlowPanel {
  preferredSize = size
  new Publisher {
    import swing.event.MouseClicked
    reactions += {
      case MouseClicked(_,point,_,_,_) => update(point)
    }
  }.listenTo(mouse.clicks)

  import scala.collection.mutable.ArrayBuffer
  val tiles = ArrayBuffer.empty[Tile]
  0 to 14 foreach { i => tiles += Tile(i%4, i/4, i+1) }
  val nullTile = NullTile(3,3)
  tiles += nullTile
  shuffle(100)

  // ----------------------------------------
  import java.awt.Point
  def update(point: Point) =
    detect(point) match {
    case Some(tile: Tile) => move(tile); repaint
    case None =>
    }
  def detect(point: Point) = {
    tiles find { _.contains(point) } match {
    case Some(tile) =>
;print(tile)
      if (tile.isInContactWith(nullTile)) Some(tile) else None
    case None =>
    }
  }
  override def paintComponent(g: Graphics2D) =
    tiles foreach { _.paint(g) }

  def shuffle(count: Int) {
    val random = new scala.util.Random()
    0 to count foreach { e => move(tiles(random.nextInt(15))) }
  }
  def move(tile: Tile) = tile.swap(nullTile)
}

Apple.scala

/*
 * Copyright (c) 2010-2013, KOTSUBU-chan and/or its affiliates.
 * Copyright (c) 1998, Atelier-AYA.
 * All rights reserved.
 * ----------------------------------------
$ scalac -encoding "SJIS" -d bin src/{Apple,AppWindow,App15Window,Shape,Game}.scala
$ date; scala -cp bin cherry.pie.application
 * ----------------------------------------
2013年 10月27日 日曜日 12時42分32秒 JST
 ----------------------------------------
cherry.pie.application$: #1.0.03
cherry.pie.appWindow$: #1.0.03
cherry.pie.Shape$: #1.0.03
cherry.pie.Game$: #1.0.03
 ----------------------------------------
(13,14)
(58,14) -> (3,0)
(43,40) -> (2,3)
(29,66) -> (1,6)
(15,96) -> (0,9)
$ 
 */
package cherry.pie

// ----------------------------------------
import swing._
object application extends SimpleSwingApplication {
  val version =          application
    .getClass.getName+": #1.0.03"
  // ----------------------------------------
  println("-"*40)
  println(application.version)
  println(appWindow.version)
  println(Shape.version)
  println(Game.version)
  println("-"*40)
  def top = appWindow
  // ----------------------------------------
  App15Window.visible = true
}

AppWindow.scala

/*
 * Copyright (c) 2010-2013, KOTSUBU-chan and/or its affiliates.
 * Copyright (c) 1998, Atelier-AYA.
 * All rights reserved.
 */ 
package cherry.pie

// ----------------------------------------
import swing._
object appWindow extends MainFrame {
  val version =          appWindow
    .getClass.getName+": #1.0.03"
  // ----------------------------------------
  title = "Honeycomb"
  contents = new View(new Dimension(270,242))
  peer.setLocationRelativeTo(null)
}

// ----------------------------------------
class View(size: Dimension) extends FlowPanel {
  preferredSize = size
  new Publisher {
    import swing.event.MouseClicked
    reactions += {
      case MouseClicked(_,p,_,_,_) => update(p)
    }
  }.listenTo(mouse.clicks)

  // ----------------------------------------
  val tiles = createTiles

  def createTiles = {
    import scala.collection.mutable.ArrayBuffer
    val res = ArrayBuffer.empty[Honeycomb]
    3 to 13 by 2 foreach { e =>
      res += Honeycomb(e,0)
      res += Honeycomb(e,24)
    }
    2 to 14 by 2 foreach { e =>
      res += Honeycomb(e,3)
      res += Honeycomb(e,21)
    }
    1 to 15 by 2 foreach { e =>
      res += Honeycomb(e,6)
      res += Honeycomb(e,12)
      res += Honeycomb(e,18)
    }
    0 to 16 by 2 foreach { e =>
      res += Honeycomb(e,9)
      res += Honeycomb(e,15)
    }
    res.toArray
  }

  // ----------------------------------------
  import java.awt.Point
  def update(point: Point) = {
;print("(%d,%d)" format (point.x, point.y))
    tiles find { _.contains(point) } match {
    case Some(tile) =>
;print(" -> "+tile)
    case None =>
    }
;println
  }

  // ----------------------------------------
  override def paintComponent(g: Graphics2D) =
    tiles foreach { _.paint(g) }
}

Game.scala

/*
 * Copyright (c) 2010-2013, KOTSUBU-chan and/or its affiliates.
 * Copyright (c) 1998, Atelier-AYA.
 * All rights reserved.
 */ 
package cherry.pie

// ----------------------------------------
object Game {
  val version =          Game
    .getClass.getName+": #1.0.03"
}

// ----------------------------------------
import java.awt._
object NullTile {
  def apply(x0: Int, y0: Int) = new Tile(x0, y0, 0) {
    override def paint(g: Graphics2D) =
      Rectangle(x*width, y*height, width, height)
        .paint(g, Color.lightGray)
  }
}
object Tile {
  def apply(x: Int, y: Int, n: Int) = new Tile(x, y, n)
}
class Tile(var x0: Int, var y0: Int, n: Int) {
  def x = x0
  def x_=(x: Int) { x0 = x }
  def y = y0
  def y_=(y: Int) { y0 = y }
  override def toString = "(%d,%d)%d" format (x,y,n)

  val (width, height) = (50, 50)
  val (px, py) = (x*width, y*height)
  val rect = Rectangle(px, py, width, height)
  val (dx, dy) = (4, 15)
  val symb = Symbol(n+"", px+dx, py+dy)

  def paint(g: Graphics2D) = {
    rect.paint(g)
    symb.paint(g)
  }
  def contains(p: Point) = rect.contains(p)

  def isInContactWith(that: Tile) = {
    val a = x - that.x
    val b = y - that.y
    a*a + b*b == 1
  }
  def swap(that: Tile) = {
    val (this_x, this_y) = (x, y)
    this.move(that.x, that.y)
    that.move(this_x, this_y)
  }
  def move(x: Int, y: Int) {
    this.x = x; this.y = y
    val (px, py) = (x*width, y*height)
    rect.move(px, py)
    symb.move(px+dx, py+dy)
  }
}

// ----------------------------------------
object Honeycomb {
  def apply(x: Int, y: Int) = new Honeycomb(x, y)
}
class Honeycomb(x0: Int, y0: Int) {
  override def toString = "(%d,%d)" format (x0,y0)
  val hex = Hexagon(x0, y0)
  def contains(p: Point) = hex.contains(p)
  def paint(g: Graphics2D) = hex.paint(g, Color.green)
}

Shape.scala

/*
 * Copyright (c) 2010-2013, KOTSUBU-chan and/or its affiliates.
 * Copyright (c) 1998, Atelier-AYA.
 * All rights reserved.
 */ 
package cherry.pie

// ----------------------------------------
object Shape {
  val version =          Shape
    .getClass.getName+": #1.0.03"
}

// ----------------------------------------
import java.awt._
trait Shape {
  def paint(g: Graphics2D)
  def contains(p: Point): Boolean
  def move(x: Int, y: Int)
}

// ----------------------------------------
abstract class Geometry extends Shape {
  def paint(g: Graphics2D, fillColor: Color)
  def paint(g: Graphics2D): Unit = paint(g, defaultFillColor)
  def defaultFillColor = Color.white
  def drawColor = Color.black
}

// ----------------------------------------
object Hexagon {
  def apply(x: Int, y: Int) = new Hexagon(x, y)
}
class Hexagon(var x0: Int, var y0: Int) extends Geometry {
  import scala.collection.immutable.List
  var vertices = List( (1,0),(2,1),(2,3),(1,4),(0,3),(0,1) )
  val (dx,dy) = (7,4)
  val scale = 2

  def xPoints_(scale: Int) =
    points(scale) map { case (x,y) => x }
  def yPoints_(scale: Int) =
    points(scale) map { case (x,y) => y }
  def points(scale: Int) = {
    import scala.collection.mutable.ListBuffer
    val buf = new ListBuffer[(Int,Int)]
    vertices foreach { case (x,y) =>
      val px = (x0+x)*dx*scale + x0
      val py = (y0+y)*dy*scale + y0 - y0/3
      buf += ( (px, py) )
    }
    buf.toArray
  }
  def paint(g: Graphics2D, fillColor: Color) {
    val xPoints = xPoints_(scale)
    val yPoints = yPoints_(scale)
    val nPoints = vertices.length
    g.setColor(fillColor)
    g.fillPolygon(xPoints, yPoints, nPoints)
    g.setColor(drawColor)
    g.drawPolygon(xPoints, yPoints, nPoints)
  }
  def contains(p: Point) = {
    val (x,y) = (1,2)
    val px = (x0+x)*dx*scale + x0
    val py = (y0+y)*dy*scale + y0 - y0/3
    val x1 = px - p.x 
    val y1 = py - p.y
    val xs = dx*scale
    x1*x1 + y1*y1 <= xs*xs
  }
  def move(x: Int, y: Int) = {}
}

// ----------------------------------------
object Rectangle {
  def apply(x: Int, y: Int, width: Int, height: Int) =
    (new Rectangle)(x, y, width, height)
}
class Rectangle extends Geometry {
  var peer: java.awt.Rectangle = _
  def apply(x: Int, y: Int, width: Int, height: Int) = {
    peer = new java.awt.Rectangle(x, y, width, height); this
  }
  def paint(g: Graphics2D, fillColor: Color) {
    val (x, y) = (peer.x, peer.y)
    val (width, height) = (peer.width, peer.height)
    g.setColor(fillColor)
    g.fillRect(x, y, width, height)
    g.setColor(drawColor)
    g.drawRect(x, y, width, height)
  }
  def contains(p: Point) = peer.contains(p)
  def move(x: Int, y: Int) = peer.setLocation(x,y)
}

// ----------------------------------------
object Symbol {
  def apply(s: String, x: Int, y: Int) = new Symbol(s, x, y)
}
class Symbol(s: String, var x: Int, var y: Int)
  extends Geometry {
  def paint(g: Graphics2D, fillColor: Color) {
    g.setColor(drawColor)
    g.drawString(s, x, y)
  }
  def contains(p: Point) = false
  def move(x: Int, y: Int) = { this.x = x; this.y = y }
}

/* ----------------------------------------
src/Shape.scala:31: error: object List is not a value
  val vertices = List(3,4)
                 ^
// ---------------------------------------- */