1. gushwell

    Posted

    gushwell
Changes in title
+2次元ランダムウォークを可視化する
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,203 @@
+
+## はじめに
+
+前の投稿では、[1次元ランダムウオーク](https://qiita.com/gushwell/items/59e11f0029b45515fe19)のプログラムを書いたので、今度は2次元ランダムウォークのプログラムを書いてみました。
+
+(x,y)にある点の次の位置を(x+1,y) (x-1,y) (x,y+1) (x,y-1)の4つとし、それぞれが、1/4の確率である場合の動きを可視化するプログラムです。
+
+この記事の最後に、CodePenのページを埋め込んでいるので、動きを確認できます。
+
+## MyCanvasクラス
+
+1次元ランダムウォークの時と同じように、まず、MyCanvasクラスを定義します。
+
+```js
+class MyCanvas {
+ constructor (id, width, height) {
+ this.canvas = document.getElementById(id);
+ this.ctx = this.canvas.getContext('2d');
+ if (width)
+ this.ctx.canvas.width = width;
+ if (height)
+ this.ctx.canvas.height = height;
+ this.width = this.ctx.canvas.width;
+ this.height = this.ctx.canvas.height;
+ }
+
+ drawPoint(x1, y1, size, color = '#000') {
+ this.ctx.save();
+ this.ctx.beginPath();
+ this.ctx.fillStyle = color;
+ this.ctx.fillRect(x1, y1, size, size);
+ this.ctx.restore();
+ }
+
+ // すべてをクリア
+ clearAll() {
+ this.ctx.clearRect(0, 0, this.width, this.height);
+ }
+}
+```
+
+`drawPoint`メソッドと`clearAll`メソッドだけをもつ簡単なクラスです。
+
+## Walkerクラス
+
+次は、Walkerクラスです。これは、ランダムウオークを行うこのプログラムの核となるクラスです。ひとつの点の動きを扱います。複数の点を同時に動かす場合には、このインスタンスを複数生成することになります。
+
+walkメソッドを呼び出すたびに、ランダムに一歩だけ座標が動きます。なお、ここでは描画は行っていません。
+
+```js
+class Walker {
+ constructor (size) {
+ this.x = 0;
+ this.y = 0;
+ this.maxHeight = 0;
+ this.maxWidth = 0;
+ this.size = size;
+ }
+
+ walk() {
+ var d = Math.floor(Math.random() * 4) + 1;
+ var diffx = 0, diffy = 0;
+ switch (d) {
+ case 1:
+ diffx = +this.size;
+ break;
+ case 2:
+ diffx = -this.size;
+ break;
+ case 3:
+ diffy = +this.size;
+ break;
+ case 4:
+ diffy = -this.size;
+ break;
+ }
+ if (0 < this.x + diffx && this.x + diffx < this.maxWidth - this.size)
+ this.x += diffx;
+ if (0 < this.y + diffy && this.y + diffy < this.maxHeight - this.size)
+ this.y += diffy;
+ return {x:this.x, y:this.y};
+ };
+}
+```
+
+
+## Prigramクラス
+
+最後が、Walkerクラスのwalkメソッドを繰り返し呼び出し、描画を行うメイン処理を行うメインのプログラムです。
+
+`Promise`と`async/await`を使って、無限ループ風のコードを書こうとしたのですが、CodePenだと、無限ループはダメだよ、とエラーになってしまうので、`setInterval`を使った従来の書き方にしました。
+
+
+```js
+class Program {
+ constructor() {
+ this.height = 300;
+ this.width = 300;
+
+ this.canvas = new MyCanvas('mycanvas', this.width, this.height);
+ this.loop = true;
+ }
+
+ run() {
+ let btn = document.querySelector('#startButton');
+ btn.onclick = () => this.start();
+ let btn2 = document.querySelector('#stopButton');
+ btn2.onclick = () => this.stop();
+ }
+
+ start() {
+ this.canvas.clearAll();
+ const size = 2;
+ var walker = new Walker(size);
+ walker.x = this.width / 2;
+ walker.y = this.height / 2;
+ walker.maxWidth = this.width;
+ walker.maxHeight = this.height;
+ this.canvas.drawPoint(walker.x, walker.y, size);
+
+ this.loop = true;
+ let timer = setInterval(() => {
+ this.canvas.drawPoint(walker.x, walker.y, size, '#ccc');
+ walker.walk();
+ this.canvas.drawPoint(walker.x, walker.y, size, '#000');
+ if (this.loop === false)
+ clearInterval(timer);
+ }, 20);
+ }
+
+ stop() {
+ this.loop = false;
+ }
+}
+
+window.onload = function() {
+ var pgm = new Program();
+ pgm.run();
+};
+
+```
+
+## HTML
+
+
+HTMLは以下の通り。
+
+```html
+<!DOCTYPE html >
+<html lang="ja">
+<head>
+ <meta charset="utf-8">
+ <title>sample</title>
+ <style>
+ #mycanvas {
+ background-color: beige;
+ }
+ </style>
+</head>
+<body>
+ <div>
+ <button id="startButton" type="button">Start</button>
+ <button id="stopButton" type="button">Stop</button>
+ </div>
+ <div>
+ <canvas id="mycanvas" width="200" height="200"></canvas>
+ </div>
+ <script src="randomwalk2d.1.js"></script>
+</body>
+</html>
+```
+
+## 実行結果
+
+
+![スクリーンショット 2019-03-08 20.47.21.png](https://qiita-image-store.s3.amazonaws.com/0/29415/b6a645b9-533e-e6fb-32ce-76a44c7abb5f.png "スクリーンショット 2019-03-08 20.47.21.png")
+
+
+このプログラムですが、いいかげんな作りなので、Startボタンを複数クリックすると、クリックした数だけ点が生成され、複数の点が同時に動くようになります。
+
+以下が、そのスクリーンショット。
+
+![スクリーンショット 2019-03-08 20.47.44.png](https://qiita-image-store.s3.amazonaws.com/0/29415/a494452e-35fc-5be6-f4ee-90685bb8a833.png "スクリーンショット 2019-03-08 20.47.44.png")
+
+ちょっと、点が小さいですが、5つの黒点があるのがわかると思います。
+
+## CodePenで書いて、埋め込んでみた
+
+CodePenのコードを埋め込んでみました。Startボタンを押せば、ランダムウォークが開始されます。
+
+
+眺めてるだけでも楽しいです(笑)
+
+
+<p class="codepen" data-height="420" data-theme-id="0" data-default-tab="js,result" data-user="gushwell" data-slug-hash="EMmomB" style="height: 420px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid black; margin: 1em 0; padding: 1em;" data-pen-title="randomwalk2d">
+ <span>See the Pen <a href="https://codepen.io/gushwell/pen/EMmomB/">
+ randomwalk2d</a> by Gushwell (<a href="https://codepen.io/gushwell">@gushwell</a>)
+ on <a href="https://codepen.io">CodePen</a>.</span>
+</p>
+<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
+
+
+