1. gushwell

    No comment

    gushwell
Changes in body
Source | HTML | Preview
@@ -1,203 +1,202 @@
## はじめに
前の投稿では、[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);
- // const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
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.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>