【ステージ#4】 繰り返しと条件分岐に関するプログラミング問題

《難易度★★☆》for文による反復処理、if分による条件分岐処理の基礎的な理解とスキルを試すプログラミング問題です。また、canvasを使ったグラフィックの描画も扱います。

問題

グレーの枠の中に、黄色の正方形を5つ横に並べて表示するコード(HTML,CSSに加え今回はJavaScriptも)がすでに用意されています。これをベースとして、以下の問題の指示にしたがってコードを追加しなさい。

  • 問題4-1:黄色の正方形が縦横5つずつ並べて表示されるようにしなさい
  • 問題4-2:さらに偶数行は黄色の正方形の代わりに水色の円が表示されるようにしなさい(水色の円を表示する関数はすでに問題のjavascriptに用意されています)
  • 問題4-3:黄色の正方形と水色の円が市松模様(チェスボードのような)に表示されるようにしなさい

See the Pen ステージ#4問題 by programmingbird (@programmingbird) on CodePen.

問題コード(JavaScript)の確認

まず今回は問題の段階からJavaScriptがしっかり書いてあるので、その中身をざっと見てみる。コメント文にそって。最初の//canvasの準備はcanvasを使うためのお約束コードなのでとりあえずスルー。//「トリガー」の設定だけど今回はトリガーと言ってもボタンをクリックしたりするわけではないのでイベントリスナーの設定とかではなく読み込みと同時にいきなりfor文の繰り返し処理が始まるようになっています。そのfor文の中で繰り返し実行されるユーザー定義関数がsquare

//「アクション」の設定でそのsquareの内容を書いている。x,y座標を引数として渡すと縦横とも99pxの正方形を描く関数になっている。

問題4-1の解説と解答例

解説(発想のしかた)

【トリガーの設定】 問題4-1では正方形を縦にも5個ずつ並べろと言われているので、for文を2重にしてやればよい。 今あるカウンターiのループを、新しいカウンターjで囲んでやる。jを100倍してy座標として使えばよさそうだな。

//「トリガー」の設定
for (var j = 0; j < 5; j++) {
  for (var i = 0; i < 5; i++) {
    square(i * 100, j * 100);
  }
}

解答例

See the Pen ステージ#4問題4-1 by programmingbird (@programmingbird) on CodePen.

問題4-2の解説と解答例

解説(発想のしかた)

①  問題4-1で書いたコードに、「偶数列かどうか」を判定する条件分岐を追加してやればよさそう。「偶数列」というのは要はカウンターiが偶数のときということになる。偶数→2で割り切れる→2で割った時のあまりが0 なので、演算子%を使おう。if文で分岐を書く。水色の円を表示させる「アクション」は後で書くとして関数名はcircleにしておこう。squareと同じくx,y座標を引数として渡す前提で。

//「トリガー」の設定
for (var j = 0; j < 5; j++) {
  for (var i = 0; i < 5; i++) {
    if (i % 2 == 0) {
      square(i * 100, j * 100);
    } else {
      circle(i * 100, j * 100);
    }
  }
}

② 【アクションの設定】circleの中身を書く。円弧を書く命令arcだとx,y座標が円の中心になるが、正方形と同じく左上に基準を合わせたほうが便利そうなので、半径の50pxを座標にたし算して調整しておく。(渡されたx,y座標より右下に50pxずつずれたところを中心として半径50pxの円を描くようにする)

function circle(x, y) {
  ctx.beginPath();
  ctx.fillStyle = "#4099d7";
  ctx.arc(x + 50, y + 50, 50, 0, Math.PI * 2, true);
  ctx.fill();
}

解答例

See the Pen ステージ#4問題4-2/a> by programmingbird (@programmingbird) on CodePen.

問題4-3の解説と解答例

解説(発想のしかた)

【トリガーの設定】基本的には問題4-2と同じ。でも「市松模様」をどうコードで表現するかがさっきより難しそうだ。「奇数行の偶数列」と「偶数行の奇数列」を円にすれば、市松模様になる。if文をたくさん書けば表現できるけどなんだか美しくはない…。正方形にするのは円のときの逆だから「奇数行の奇数列」「偶数行の偶数列」か…。あ!奇数+奇数も偶数+偶数も偶数になるよな。反対に奇数+偶数は奇数になるから、カウンターのiとjの和が奇数のときだけ円にする、というコードを書けば市松模様を描けそうだ。

//「トリガー」の設定
for (var j = 0; j < 5; j++) {
  for (var i = 0; i < 5; i++) {
    if ((i + j) % 2 == 0) {
      square(i * 100, j * 100);
    } else {
      circle(i * 100, j * 100);
    }
  }
}

解答例

See the Pen ステージ#4問題4-3 by programmingbird (@programmingbird) on CodePen.