♬《148》憧れの背中

♬ 憧れの背中

勝利の喜びはない
いつか君に 追いつきたい

その背中 消えたら
グランドに 倒れて
汗にまみれて
起き上がれない


慰めの言葉もなく
やっと君を 追い越しても

その背中 褪せない
差し出した その手を
握り返して
夕陽にかざす


風に戦いでる プラタナスの影
今はもう 遠い街 同じ空
名前を呼ばれ…


託された夢は 果たせず
もしも君が 見ていたなら

僕の背を 目指して
走り出した 誰かが
旧いアルバム
時を運んだ

    • 148#2017-04e:憧れの背中

Oh脳《005》雛祭りと苺大福(ずんだ餡)!?

ひな祭りには、菱餅。その菱餅にも謂れがあって…

《抜粋》下から「緑・白・赤」の順番で配置されている菱餅は、雪の下に新芽が芽吹き、梅の花が咲いている情景。下から「白・緑・赤」の順番のときは、雪の中から新芽が吹き出、桃の花が咲いている情景です。《中略》今でも雛人形はお子さまに降りかかる災いの身代わりになってくれるものとしての役割も持ち合わせています。
www.tougyoku.com

そこで、菱餅に準えて「雛祭り仕様の苺大福」を拵えてみました。

f:id:shiorichannel:20210306095331p:plain
いちご大福:ひな祭り仕様

餡には「ずんだ」を使ったので

  • 白(雪)
  • 緑(新芽)
  • 赤(桃の花)

の三色が楽しめます。そして、我が家の庭にも…

f:id:shiorichannel:20210306101305j:plain

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)
                 ^
// ---------------------------------------- */

Java.use(better, Scala); S4(E3) 15パズル

#Scalaの栞

Java.use(better, Scala); Season4(Episode1) 15パズル

変数を介して値を設定する

ときに、res3 とは何でしょうか。そこで、型を確認すると、

scala> :type res3
scala.swing.MainFrame

その変数を束縛している対象は、ウインドー MainFrame だと分ります。res3 は、隠れたウインドーを参照するための、隠れた変数です。というのも、対話形式では、実行した結果を後で参照できるように、隠れた変数が順に(res0, res1, ...)用意されるからです。

f:id:shiorichannel:20210222165803p:plain
変数と束縛

隠れた変数 res3 は、ウインドーに束縛されます。それなら、res3 を介して値を設定すると、隠れたウインドーが見えるようになるはずです。そこで、

scala> res3.visible = true

変数 res3 を介して、ウインドーの属性 visible に値 true を設定すると、ウインドーが現れます。このときの値 true は、真を表わす論理値です。同様に、

scala> res3.title = "A"

変数 res3 を介して、ウインドーの属性 title に値 "A" を設定すると、それがウインドーのタイトルに表示されます。二重引用符で囲まれた "A" は、文字列を表わします。すると、タイトルが違うのでウインドーを区別できます。
一般に、属性に値を設定(属性値を変更)するときには、次の書式に従います。

scala> オブジェクト.属性 = 値

この二重引用符には意味があります。というのも、それがないと、変数やモジュールなどと解釈されるからです。それを二重引用符で括ると「文字の並び」をそのまま解釈して欲しいという利用者の意図が、コンピューターに伝わります。
文字列のように、変数を介する必要がない、オブジェクトそのものを表現したものをリテラル〔literal〕と呼びます。そして、意味のあるオブジェクトはどれも、リテラルに帰着します。

変数を介して値を獲得する

変数を入力すると、その値が出力されます。これは、変数を評価したときに、その変数が束縛されている対象(オブジェクト)が得られるからです。
ときに、変数 res3 の値(型ではなく)は何でしょうか。変数 res3 を評価すると、その変数が束縛されているウインドーが得られます。そして、入力した変数を評価した結果として、得られたウインドーの情報が出力されます。このとき、

scala> res3
res4: scala.swing.MainFrame = scala.swing.Frame$$anon$1[frame2,0,22,128x37,layout=java.awt.BorderLayout,title=A,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,22,128x15,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=449,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]
f:id:shiorichannel:20210222165848p:plain
異なる変数とその値

変数 res3 を評価した結果を参照するために、また新たな変数 res4 が用意されます。res4 で始まる出力から、設定されたタイトル title=A を確認できます。このとき、2つの変数 res3 および res4 はどちらも、同じウインドーに束縛されます。それが事実なら、

scala> res4.title = "C"

変数 res3 に代えて、変数 res4 を介しても、タイトルを変更できるはずです。変数 res4 に代えて、変数 res3 を介して、その属性値を確認すると、

scala> res3.title
res5: String = C
20131210031803
f:id:shiorichannel:20210222165948p:plain
メソッド呼び出しとリターン値

文字列 "C" が得られます。ここでも、その結果を参照するために、また新たな変数 res5 が用意されます。このとき、単純な文字列と複雑なウインドーとの間に、本質的な違いはありません。どちらも一人前のオブジェクトです。

変数  res5    res0
---------------------------------------------------
型   String  scala.swing.MainFrame
値   C       scala.swing.Frame$$anon$1[frame0,...]

一般に、属性の値を獲得(属性値を参照)するときには、次の書式に従います。
scala> オブジェクト.属性
変数: 型 = 値
変数 res5 の型は文字列 String で、その値は文字列 C です。また、2つの変数 res3 および res4 がどちらも、同じウインドーに束縛される事実は、

scala> res3 == res4
res6: Boolean = true

でも確認できます。ここでも、また新たな変数 res6 が用意され、その型は論理型 Boolean で、その値は真を表わす true だと分ります。文字列と同様に、true もリテラルのひとつで、すでに何度も登場しています。

f:id:shiorichannel:20210222170032p:plain
属性

Created: 2012/12/18|Last updated: 2013/12/10 16:13:34

Scala.use(better)《tips432》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年 11月13日 水曜日 17時58分00秒 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
----------------------------------------
(16,16) -> (0,0)
(45,16) -> (2,0)
(74,17) -> (4,0)
(31,41) -> (1,3)
(57,40)
(45,68) -> (2,6)
$ 
 */
package cherry.pie

// ----------------------------------------
import swing._
object <span style="color: #ff5252">application</span> 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(200,200))
  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)

  // ----------------------------------------
  import scala.collection.mutable.ArrayBuffer
  val tiles = ArrayBuffer.empty[Honeycomb]
  tiles += Honeycomb(0,0)
  tiles += Honeycomb(2,0)
  tiles += Honeycomb(4,0)
  tiles += Honeycomb(1,3)
  tiles += Honeycomb(2,6)

  // ----------------------------------------
  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 peer = Hexagon(x0, y0)
  def contains(p: Point) = peer.contains(p)
  def paint(g: Graphics2D) = peer.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 defaultDrawColor = Color.black
}

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

  val bounds = points(scale)
  def xPoints = bounds map { case (x,_) => x }
  def yPoints = bounds map { case (_,y) => y }
  def points(scale: Int) = {
    import scala.collection.mutable.ListBuffer
    val buf = ListBuffer.empty[(Int,Int)]
    vertices foreach { case (x,y) =>
      val px = (x0+x)*dx*scale + x0
      val py = (y0+y)*dy*scale + y0 - y0/3
      buf += *2
    }
    buf.toArray
  }

  // ----------------------------------------
  def paint(g: Graphics2D, fillColor: Color) {
    g.setColor(fillColor)
    g.fillPolygon(xPoints, yPoints, nPoints)
    g.setColor(defaultDrawColor)
    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
  }
}

// ----------------------------------------
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(defaultDrawColor)
    g.drawRect(x, y, width, height)
  }
  def contains(p: Point) = peer.contains(p)
  override 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(defaultDrawColor)
    g.drawString(s, x, y)
  }
  def contains(p: Point) = false
  override 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)
                 ^

/

*1:1,0),(2,1),(2,3),(1,4),(0,3),(0,1

*2:px, py

Scala.use(better)《tips431》Hexothello

f:id:shiorichannel:20210219132931p:plain
アプリケーション

》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.03"
  // ----------------------------------------
  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年 11月 1日 金曜日 00時10分03秒 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
----------------------------------------
(1,1)4(2,1)5(2,2)7(2,3)1(3,3)13(3,2)12(3,1)3(3,0)11(2,0)10(2,1)7(2,2)1(3,2)3(3,1)11(3,0)10(2,0)7(1,0)4(0,0)2(0,1)8(0,2)6(1,2)9(2,2)3(3,2)11(3,1)10(3,0)7(2,0)4(1,0)2(0,0)8(1,0)8(1,1)5(1,2)3(2,2)11(1,2)11(0,2)9(0,1)6(0,1)0(0,0)8(1,0)5(2,0)2(2,1)1(1,1)3(0,1)8(1,1)8(1,0)2(2,0)1(2,1)3(1,1)2(0,1)8(0,0)5(1,0)1(1,1)8(2,1)2(2,1)0(3,1)7(3,0)4(2,0)3(1,0)8(1,1)2(2,1)7(2,0)8(3,0)3(3,1)4(2,1)8(1,1)7(1,2)9(2,2)11(2,2)0(3,2)10(3,1)8(2,1)7(1,1)9(1,2)11(1,2)0(0,2)6(0,1)5(1,1)11(1,2)6(2,2)10(2,1)9(1,1)6(0,1)11(0,2)5(1,2)10(1,1)11(2,1)6(3,1)7(3,2)8(3,3)12(2,3)13(1,3)15(0,3)14(0,2)10(1,2)11(2,2)9(2,3)15(1,3)14(0,3)10(0,2)11(1,2)9(1,3)10(0,3)11(0,2)9(1,2)10(1,3)11(2,3)14(3,3)13(2,3)13(2,2)15(3,2)12(2,2)12(0,2)10(1,2)11(0,2)10(0,3)9(1,3)14(2,3)15(2,3)0(3,3)13$ 
 */
package cherry.pie

// ----------------------------------------
import swing._
object <span style="color: #ff5252">application</span> 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(250,250))
  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 nullTile = NullTile(3,3)

  import scala.collection.mutable.ArrayBuffer
  val tiles = ArrayBuffer.empty[Tile]
  0 to 14 foreach { i => tiles += Tile(i%4, i/4, i+1) }
  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 =>
    }
  }
  def shuffle(count: Int) {
    val random = new scala.util.Random
    0 to count foreach { _ => move(tiles(random.nextInt(15))) }
  }
  def move(tile: Tile) = tile.swap(nullTile)

  // ----------------------------------------
  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)
  }
}

》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,a"
}

// ----------------------------------------
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 defaultDrawColor = Color.black
}

// ----------------------------------------
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(defaultDrawColor)
    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(defaultDrawColor)
    g.drawString(s, x, y)
  }
  def contains(p: Point) = false
  def move(x: Int, y: Int) = { this.x = x; this.y = y }
}

Java.use(better, Scala); S4(E2) 15パズル

#Scalaの栞

Java.use(better, Scala); Season4(Episode2) 15パズル 

[:contents] 

対話形式の意義

最初に、次のコードの断片を入力します。すると、

scala> new swing.MainFrame { visible = true }
res0: scala.swing.MainFrame = scala.swing.Frame$$anon$1[frame0,0,22,128x37,layout=java.awt.BorderLayout,title=,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,22,128x15,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=449,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

f:id:shiorichannel:20210219155056p:plain

ウインドーとターミナル

ディスプレーの左上隅にウインドーが現れ、その情報がターミナルに出力されます。そこで、res0 で始まる出力から、その詳細を読み取ります。

まず、正式には scala.swing.MainFrame で、scala. の部分は省略可能と分ります。次に、128x37 から、ウインドーの寸法(幅x高さ)が分ります。そして、128x15 から、タイトルの部分を除いたウインドーの高さが 15(かつ、タイトルの高さが 22=37-15)と分ります。他の情報は、後述します。

では、一部を省略して入力すると、どうなるでしょうか。すると、

scala> new swing.MainFrame
res1: scala.swing.MainFrame = scala.swing.Frame$$anon$1[frame1,0,22,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=449,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

ウインドーは表示されずに、res1: で始まる情報だけを出力します。ウインドーは寸法を持たない 0x0 なので、隠れて見えない hidden のが分ります。

f:id:shiorichannel:20210220162632p:plain

入力と出力

対話形式では、利用者が「入力」したコードをコンピューターが解釈して、実行した結果に関する情報を「出力」します。つまり、入出力を介して、利用者とコンピューターが「対話」を繰り返しながら、試行錯誤によって経験を積みます。

サブコマンド :type

さらに省略すると、どうなるでしょうか。すると、

scala> new MainFrame
:8: error: not found: type MainFrame
       new MainFrame
           ^

 エラーメッセージを出力します。そこから原因を探ると、型 MainFrame を確認できないのが分ります。そこで、help にあったサブコマンド :type を利用して、その型を確認します。サブコマンドは、コロン「:」に続けて入力します。

scala> :type MainFrame
Failed to determine type.

やはり、型を決定できません。そこで、swing. を明記すると、 

scala> :type swing.MainFrame
<notype>

今度は「型なし」です。そして、swing だけを確認すると、

scala> :type swing
package swing

swing は、パッケージだと分ります。サブコマンド :type を利用すると、有効な型の情報が得られます。が、その型が無効なら、それこそ「形無し」です。

import

import を利用すると、正式な名前を省略できるので便利です。たとえば、

scala> import swing.MainFrame
import swing.MainFrame

swing.MainFrame に代えて、これを省略した末尾の MainFrame だけで認識できます。実はこの swing.MainFrame も、scala.swing.MainFrame を省略したものです。すると、

scala> new MainFrame
res3: scala.swing.MainFrame = scala.swing.Frame$$anon$1[frame2,0,22,0x0,invalid,hidden,layout=java.awt.BorderLayout,title=,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=449,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

今度は、同じコードの断片を入力しても、エラーメッセージを出力しません。変わらずウインドーは現れませんが、実行した結果に関する情報を出力します。 

Created: 2012/12/18Last updated: 2013/12/10 16:12:06