2次元ランダムウォーク
Posted feedbacks - Scala
scala+swingで書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | import java.awt.BorderLayout
import java.awt.Color
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.Graphics
import java.awt.Point
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.io.BufferedWriter
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStreamWriter
import java.io.PrintWriter
import java.util.Random
import javax.swing.JButton
import javax.swing.JFileChooser
import javax.swing.JFrame
import javax.swing.JMenu
import javax.swing.JMenuBar
import javax.swing.JMenuItem
import javax.swing.JPanel
class RandomWalk(step:int) {
private var _trace:List[Point] = null
private val rand:Random = new Random
def walk:RandomWalk = {
var p = new Point(0,0)
trace = (new Range(1,step,1)).map[Point] { i => p = move(p); p }.toList
this
}
private def move(p:Point):Point = rand.nextInt(4) match {
case 0 => new Point(p.x + 1, p.y)
case 1 => new Point(p.x - 1, p.y)
case 2 => new Point(p.x, p.y + 1)
case 3 => new Point(p.x, p.y - 1)
case _ => p
}
def trace_=(trace:List[Point]) = { _trace = trace }
def trace = _trace
}
class Button(l:String,c:ActionEvent=>Unit) extends JButton with ActionListener {
setText(l)
addActionListener(this)
override def actionPerformed(e:ActionEvent) = c(e)
}
class MenuItem(l:String,c:ActionEvent=>Unit) extends JMenuItem with ActionListener {
setText(l)
addActionListener(this)
override def actionPerformed(e:ActionEvent) = c(e)
}
class Panel extends JPanel {
var _trace:List[Point] = null
def trace_=(trace:List[Point]) = { _trace = trace }
def trace = _trace
override def paint(g:Graphics):Unit = {
val max:int = trace.foldLeft(0) { (m,p) => List(p.x,p.y).foldLeft(m) { (m,l) => Math.max(m,Math.abs(l)) } }
val pitch:double = getWidth.asInstanceOf[double] / (max * 2)
def drawLine(c:Point,trace:List[Point]):Unit = {
trace match {
case List() => ()
case (p::rest) => {
g.drawLine(
(c.x * pitch).asInstanceOf[int] + getWidth / 2,
getWidth / 2 - (c.y * pitch).asInstanceOf[int],
(p.x * pitch).asInstanceOf[int] + getWidth / 2,
getWidth / 2 - (p.y * pitch).asInstanceOf[int]
)
drawLine(p,rest)
}
}
}
g.clearRect(0,0,getWidth,getHeight)
g.setColor(Color.BLACK)
drawLine(new Point(0,0),trace)
}
}
class Plotter(title:String,step:int) extends JFrame {
var walker = (new RandomWalk(step)).walk
var _panel:Panel = null
def panel_=(panel:Panel) = { _panel = panel }
def panel = _panel
def walk:Unit = {
walker.walk
panel.trace = walker.trace
}
def walk(e:ActionEvent):Unit = {
walk
repaint()
}
def save(e:ActionEvent):Unit = {
val fc:JFileChooser = new JFileChooser()
try {
if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
val f:File = fc.getSelectedFile
val w:PrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f))))
def writeTrace(trace:List[(int,Point)]):Unit = {
trace match {
case List() => ()
case (i::rest) => {
w.printf("%d\t%d\t%d\n",Array(Integer.valueOf(i._1),Integer.valueOf(i._2.x),Integer.valueOf(i._2.y)))
writeTrace(rest)
}
}
}
writeTrace((new Range(1,walker.trace.size,1)).toList.zip(walker.trace))
w.close
}
} catch {
case e => e.printStackTrace
}
}
def quit(e:ActionEvent):Unit = {
System.exit(0)
}
}
object Main extends Application {
var p = new Plotter("random walk",10000)
val mb = new JMenuBar
val fm = new JMenu("file")
val em = new JMenu("walk")
val c = p.getContentPane
val pp = new Panel
val bp = new JPanel
c.setLayout(new BorderLayout)
pp.setPreferredSize(new Dimension(300,300))
c.add(pp,BorderLayout.CENTER)
p.panel = pp
bp.setLayout(new FlowLayout)
bp.add(new Button("walk",p.walk))
bp.add(new Button("save",p.save))
c.add(bp,BorderLayout.SOUTH)
fm.add(new MenuItem("save",p.save))
fm.add(new MenuItem("quit",p.quit))
mb.add(fm)
em.add(new MenuItem("walk",p.walk))
mb.add(em)
p.setJMenuBar(mb)
p.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
p.setResizable(false)
p.pack
p.walk
p.setVisible(true)
}
|

ytakenaka
#6806()
Rating2/2=1.00
2次元ランダムウォークをつくってみてください。
******
元は3本建てにしようかと思ったけど、上の一本に絞りました。おまけとして、3本とも下に補足しておきます。作れるようでしたら作ってみてください。
1.一次元のランダムウォークを作ってください。
1.1 データファイルに残してください。 フォーマット:時間 位置
おまけ)
可視化が簡単な処理系・プログラミング言語でしたら実際に可視化してみてください。フォーマットしたファイルをスプレッドシートやplotutilitiesなどの可視化ソフトを使って、実際に動きをかくにんしてみましょう。:-)
2.同じように2次元のランダムウォークを作ってください。
2.1 1.1と同じようにしてください。
フォーマット:時間 x位置 y位置
3.凝りたければ、アニメーションにするもよし、3次元の動きをとるもよし、自分の想像力がいかせるところまでやってみてください。
http://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%B3%E3%83%80%E3%83%A0%E3%82%A6%E3%82%A9%E3%83%BC%E3%82%AF
分からないというヒトへの分かりにくいヒント:
今の位置から次の時間の位置が決まるのですが、決まりかたが、乱数で一歩後退するか一歩先にいくか?ということをやればよいです。
[ reply ]