この記事の詳しい内容には四国新聞 WEB朝刊の「どう組み合わせればいい?」ページから有料記事に進むことで読めます。
目次
概要
かめのロボットを動かして線を引きます。ロボットには次の4つの命令を出すことができます。
命令:
- 進む(n) nマス分進む
- 左回り() その場で左を向く
- 右回り() その場で右を向く
- ここから m回繰り返す ここまで 台形で囲んだ命令をm回繰り返す
さてここで問題です。ロボットが下図のような線を引くには、下のフローチャートの空欄ア、イ、ウにどんな数と命令を入れればよいでしょう?
論理を考える
フローチャートを日本語の疑似コードで表すと、
(ア)回繰り返し
進む(1)
(イ)
進む(1)
(ウ)
繰り返しここまで
のようになります。
頭の中だけで考えるのは難しいので、絵を描いてみましょう。下図の(1)は進む(1)、(2)は(イ)、(3)は進む(1)、(4)は(ウ)です。(5)、(6)、(7)、(8)は(1)から(4)の繰り返しです。
ということは、(ア)は数値2で、(イ)は命令:左回り()、(ウ)は命令:右回り() です。これが問題の答えです。コードにすると、次のようになります。
for (let i = 0; i < 2; i++) {
kame.goForward(1);
kame.turnToLeft();
kame.goForward(1);
kame.turnToRight();
}
全コード
以下は、前の「25:くり返しの中にくり返し」で扱った、指定時間だけ待つPromiseを使った全コードです。
const rows = 3; // 横向きの行数
const columns = 3; // 縦向きの列数
const gutter = 0; // 矩形間の空き
const w = 50; // 矩形の幅
const h = 50; // 矩形の高さ
// 矩形の開始位置をずらす量 => (offsetX,offsetY)から始まる
const offsetX = 60;
const offsetY = 60;
let kame, kameImages;
let isAction = false;
function preload() {
// かめの右向き、下向き、左向き、上向きの画像を読み込み、
// そのイメージを右、下、左、上の順に配列に入れる
const right = loadImage('images/right.png');
const down = loadImage('images/down.png');
const left = loadImage('images/left.png');
const up = loadImage('images/up.png');
kameImages = [right, down, left, up];
}
function setup() {
createCanvas(300, 300);
// イメージの基点をイメージセンターにするモード
imageMode(CENTER);
// Kameインスタンスを作成
kame = new Kame(60, 160, kameImages);
}
function mousePressed() {
if (!isAction) {
kameAction();
isAction = true;
}
}
function waitUntill(ms) {
const promise = new Promise(executor);
// Promiseのコンストラクタに渡すexecutor()関数
function executor(resolve, reject) {
if (isNaN(ms)) {
reject('数値でない');
}
else {
// ms秒まったら解決
window.setTimeout(() => {
resolve('成功');
}, ms);
}
}
// というPromiseオブジェクトを返す
return promise;
}
// かめを動かす
async function kameAction() {
// 2回繰り返す
for (let i = 0; i < 2; i++) {
kame.goForward(1);
await waitUntill(1000); // 1000ミリ秒待つ
kame.turnToLeft();
await waitUntill(1000); // 1000ミリ秒待つ
kame.goForward(1);
await waitUntill(1000); // 1000ミリ秒待つ
kame.turnToRight();
await waitUntill(1000); // 1000ミリ秒待つ
}
}
function draw() {
background(220);
// グリッドの線の太さ
strokeWeight(1);
// 矩形を格子状に並べて描く
for (let c = 0; c < columns; c++) {
for (let r = 0; r < rows; r++)
// 行数(rows) x 列数(columns)に矩形を描く
rect(offsetX + c * (gutter + w), offsetY + r * (gutter + h), w, h);
}
// カメが引く線の太さ
strokeWeight(7);
kame.drawLine() // カメが線を引く
kame.display(); // カメを描画
}
class Kame {
constructor(x, y, imgs) {
this.x = x;
this.y = y;
// 向いている向きの配列 [右、下、左、上]の順番
this.directions = ['right', 'down', 'left', 'up'];
// 現在の方向を数値で表す
this.currentDirection = 0;
// 現在の方向を文字列で表す
this.direction = this.directions[this.currentDirection];
// カメのイメージ
this.images = imgs;
// 向きによってイメージを変える
this.image = this.images[this.currentDirection];
// カメの1歩は50ピクセル = グリッドの正方形の一辺の長さと同じ
this.step = 50;
// 移動する座標を保持する配列
this.prevousXs = [];
this.prevousYs = [];
// 最初の位置を追加する
this.prevousXs.push(this.x);
this.prevousYs.push(this.y);
}
// カメのイメージを描画する
display() {
image(this.image, this.x, this.y);
}
// 右を向く
turnToRight() {
this.currentDirection++;
// 循環させる
if (this.currentDirection >= 4) {
this.currentDirection = 0;
}
// カメの新しい向き
this.direction = this.directions[this.currentDirection];
// カメの新しいイメージ
this.image = this.images[this.currentDirection];
}
// 左を向く
turnToLeft() {
this.currentDirection--;
if (this.currentDirection <= -1) {
this.currentDirection = 3;
}
this.direction = this.directions[this.currentDirection];
this.image = this.images[this.currentDirection];
}
// stepsマス分だけ前進
goForward(steps) {
// 前進と言っても、今の向きによって方向は変わる
// 今の向きが右なら
if (this.direction === 'right') {
// 右にstepsマス分(50 * steps ピクセル)移動
this.x += this.step * steps;
}
else if (this.direction === 'down') {
this.y += this.step * steps;
}
else if (this.direction === 'left') {
this.x -= this.step * steps;
}
else if (this.direction === 'up') {
this.y -= this.step * steps;
}
// 新しいxy位置を配列に追加
this.prevousXs.push(this.x);
this.prevousYs.push(this.y);
}
// 通ってきた位置を結ぶ線を引く
drawLine() {
for (let i = 0; i < this.prevousXs.length; i++) {
line(this.prevousXs[i], this.prevousYs[i], this.prevousXs[i - 1], this.prevousYs[i - 1]);
}
}
}
下の画面をクリックすると、かめのロボットが移動しお題通りの線を引きます。