Javascriptで外国で有名なゲーム”CONNECT4”を作ってみた

こんにちは、Mottyです。
今回もJavascriptを使ったテーマでやっていきます。

##はじめに
Connect4をご存知いらっしゃる方は多いかと思いますが、簡単に申し上げますと四目並べです。
![CONNECT4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302420/f029983c-ce55-3dd2-9e1f-3b99b48c23a6.jpeg)


先攻と後攻が交互にボード上に駒を打ち、縦横斜めのいづれかに４目以上並べれば勝ち・・・というシンプルなゲームです。
Javascriptの勉強の題材にはちょうど良いかなと思って、
自分の家にも４目並べがありますのでどなたか一緒に遊びませんか（急なお誘い）

##開発の準備
・HTML/CSS/Javascript
・Node.js（デバッグ用）
・Bootstrap4（ボタン用）

描画ソフトはペイント、
開発環境はVisualStudioCodeで行いました。

全部解説すると冗長になるので、作ってみて勉強になった部分だけ載せていきたいと思います。
↓完成版はこんな感じになりました。
![Screenshot.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302420/05cd74c4-5e28-2d29-585a-957c69c0bd75.png)

##盤面の描画

ボードゲーム開発において悩んだのは、盤面をどう扱うか、ということでした。HTMLに直書きしても
よかったのですが、盤面情報を配列に持たせておいてそれを元に画面に描画していく、というような
やり方を行いました。（いわゆるModel-View分離型というやつですかね・・・？）



```script.js

    var boardarray = [
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0],
            [0,0,0,0,0,0,0]]


        function load_board(array)
        {
            board.innerHTML = "";
            for (let i = 0; i < array.length; i++) {
                for (let j = 0; j < array[i].length; j++) {
                    if(array[i][j] == 0)
                    {
                        board.appendChild(blank.cloneNode(true))
                    }                    
                    else if(array[i][j] == 1)
                    {
                        board.appendChild(red.cloneNode(true))
                    }
                    else if(array[i][j] == -1)
                    {
                        board.appendChild(yellow.cloneNode(true))
                    }
                }
            board.innerHTML += "<br>";
            }
        }

```

load_board(array)では、先攻を１、後攻を−１としております。
ユーザーの入力を受け取って適宜盤面を更新し、それを読み込むというロジックでやってますね。

##勝利判定
以下、勝利判定の関数です。ユーザーが石打ちを入力するたびに稼働します。
縦横ななめのいずれかが４つ以上並んでいれば良いので、打った位置から周り４方向（実質は８方向？）確認し、
いずれかの方向において自分と同じ石の数が連続して３つ以上あれば、1(先攻)/-1(後攻）、なければ0を返すfunctionにチェックしてもらってます。

![Something went wrong]()


```script.js

        function VictorysNumber(boardarr, Row, Col)　//ボードと現在行・現在列を引数として代入
            //8方向を見て連続番号を管理する配列に格納していく。
            //格納した配列をもとに、勝利かどうかを判定。
            //→方向が0番、以降45°左回転するごとに番号を1番加算し、合計7番までの8方向を定義する。
            {
            var continuousNum = [0,0,0,0,0,0,0,0]//1,2,3,4,5,6,7,8番方向
            const directionList =[
            [0,1],//0番
            [-1,1],//1
            [-1,0],//2
            [-1,-1],//3
            [0,-1],//4
            [1,-1],//5
            [1,0],//6
            [1,1]] //7
        
            //スコープははじめ置かれた石と同じ
            var scopeRow = Row;
            var scopeColumn = Col;

        //スコープ開始
  
        for (let i = 0; i < 8; i++) {   
            //textlog.value += "勝利判定関数の開始。ScopeRow="+scopeRow+ "、scopeColumn = " +scopeColumn +"です。\n";
            //textlog.value += i+"番方向を見ます。";
            while(true)
            {
                //与えられた方向への移動操作
                scopeRow += directionList[i][0];
                scopeColumn += directionList[i][1];
                try
                {
                    if(0 <= scopeRow <= 5 && 0 <= scopeColumn <= 6 &&
                        boardarr[scopeRow][scopeColumn] == boardarr[Row][Col]) //起点と今見ている場所が同じであればカウントを増やす
                    {                       
                        continuousNum[i]++; 
                        //textlog.value += i +"番方向に" + continuousNum[i] + "個の連続した石が発見されました。\n";
                    }
                    else
                    {
                        //textlog.value += i +"番方向には同じ石は見つかりませんでした。\n";
                        break; //値が同じでなければ（連番でなければ）break
                    }
                }
                catch(e)
                {
                    break; //ボードを超えた値を参照するとエラーが出る。飛び越えてもbreak.
                }
            }
            //スコープを元の位置に戻す。
            scopeRow = Row;
            scopeColumn = Col;
        }
                //勝利判定
                if( continuousNum[0] + continuousNum[5] == 3 ||
                continuousNum[1] + continuousNum[6] == 3 ||
                continuousNum[2] + continuousNum[7] == 3 ||
                continuousNum[3] + continuousNum[8] == 3 )
                {
                    return turn; //勝利者決定
                }
                else
                {
                    return 0; //勝負がついていない場合は0を返す。
                }
        }
```

※これは以前のExcelで<a href = "https://qiita.com/Yt330110713/items/79e42274731333f23bd4">五目並べを作った</a>ときとほぼ同じアルゴリズムを採用しております。


##終わりに
やはりJavascriptを少しでもいいから勉強すると、View画面作成も怖じ気づかなくなりますね・・・！
今ならなんでもできそうな気がしますが、きっと気のせいで実は色々と奥が深い分野だと思います（）

全ソースコードはgithubに載せております。
 https://github.com/YukiYamamotty0713/connect4/

参考URL
今回は下記の動画を大変参考にさせていただきました。メモ帳を使って1時間でオセロゲームを
仕上げるという凄腕のプログラマーさんの動画です。
・ニコニコ動画・【プログラミング】オセロを1時間で作ってみた【実況解説】
https://www.nicovideo.jp/watch/sm8391299