囲碁アプリケーションをつくる(4)〜クリックしたら碁石を描画する〜

2017/10/08

▼囲碁アプリケーションをつくるシリーズ
囲碁アプリケーションをつくる(1)
囲碁アプリケーションをつくる(2)〜ざっくりとした仕様とバージョン管理〜
囲碁アプリケーションをつくる(3)〜canvasで碁盤を描画する〜

▼GitHub
https://github.com/shogo0525/go

▼ざっくりとした仕様

◆STEP1:とりあえず囲碁っぽくなるフェーズ
・碁盤をcanvasで描画する。まずは19路盤から。
・碁盤上をクリックしたら、黒石または白石が置けるようになる。基本的には交互に色が変わっていく。
・引数を渡すと、19路盤以外にも13路盤や9路盤など自由なサイズで碁盤を描画できるようになる。MAXは19路。

◆STEP2:囲碁のロジックを組み込む
・石を取る、コウなど囲碁のルールを組み込んで行く
・ここでは試合計算など、終局に関わることは判断しない◆STEP3:互先の棋譜データを記録できるようになる
・SGFといった、囲碁の棋譜データの形式に変換できるようにする
・戻る、進むボタンを用意して、自由に盤面上の碁石を操れるようにする

◆STEP1000:弱小コンピューターとの対戦ができるようになる

***

第4回目では、碁盤上をクリックしたら碁石を描画するようにしていきます。

もうすでに難しくなってきました・・・(汗) ただ今回に実装によって、仕様のSTEP1のクリアが目前となってきました!

一部省略していますが、今回追加したコードは下記になります。コメントも加えているのでざっくりと見てみてください。


    canvas.addEventListener('click', onClick, false);
    function onClick(e) {
      // getBoundingClientRect()でcanvasの左上の座標を取得
      var rect = e.target.getBoundingClientRect();
      // クリック座標であるe.clientX,e.clientYからrectの値を引く
      var x = e.clientX - rect.left;
      var y = e.clientY - rect.top;

      //クリック場所が碁盤の外側なら何もしない
      if (x < cellSize || x > cellSize * boardSize ||
          y < cellSize || y > cellSize * boardSize) {
        return;
      }

      // xZahyo, yZahyoは1~19の値をとる(19路盤の場合)
      var xZahyo = getZahyo(x);
      var yZahyo = getZahyo(y);

      drawStone(xZahyo, yZahyo);

      nextTurn();
    }

    // x座標もしくはy座標を取得するメソッド
    function getZahyo(param) {
      var sho = parseInt(param / cellSize);
      var amari = param % cellSize;
      var zahyo;
      if (amari > cellSize / 2) {
        zahyo = sho + 1;
      } else {
        zahyo = sho;
      }
      return zahyo;
    }

    function drawStone(xZahyo, yZahyo) {
      if (turn == 'B'){
        // 黒石
        ctx.fillStyle = '#000000';
      } else {
        // 白石
        ctx.fillStyle = '#ffffff';
        // 白石には枠をつける
        ctx.strokeStyle = "#000000";
      }

      ctx.beginPath();
      // zahyoにcellSizeをかけた値が実際に描画する位置になる
      ctx.arc(xZahyo * cellSize, yZahyo * cellSize, cellSize/2.1, 0, Math.PI*2, false);
      ctx.closePath();
      ctx.fill();
      ctx.stroke();
    }

難しかったのは、クリックした位置から実際に碁石を描画する位置を計算することでした。

getBoundingClientRect()メソッドは今回初めて知りましたし、碁盤の外をクリックしたら描画ロジックから外すのは少し手こずりましたね。細かな計算に疲れました(汗)

「書いてみてしまえば大したことがない」というのがプログラムを組んでいるとよくありまして、今回もそんな感じでした。実際に、プログラマーは書くより考えることに時間をかけてたりします。優秀なプログラマーは、頭の中でざーっとロジックをまとめて、切りがついたら一気にパチパチとキーボードを叩いていくらしいですね。

今回は、手番(turn)が切り替わる簡単なロジックも用意し、黒石と白石が交互に描画されるようにしました。

ただ、単に碁石が描画がされるだけであって、「どの座標(位置)にどの碁石が打たれたか」はデータとして残していません。なので、一度打った箇所にまた上から打つことができちゃったりします(笑)

次回はそこらへんをうまく制御するように実装していきたいと思います!!

●クリックして碁石を表示するプログラムはこちら