コンソール上で遊べる重力付き四目並べ

#はじめに
今回はコンソール上で重力付き四目並べを遊んでみました！
こんな感じに動きます。
![connect.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547629/e2b6b1fc-9650-eeff-0b77-b28a2ccf4f47.gif)


お遊び程度で作ったので判定部分に漏れがあるかもしれませんが、今後はこれをベースにCPU対戦を追加など改良を加えていこうと思います。
一応重力付き四目並べについて
>
wiki
https://ja.wikipedia.org/wiki/%E5%9B%9B%E7%9B%AE%E4%B8%A6%E3%81%B9

#使用環境
・Windows 7
・Java 8
・Eclipse

#ソース紹介
今回のソースを紹介します。

```Java:ConnectFour.java
package connect.main;

import java.util.Random;
import java.util.Scanner;

public class ConnectFour {

	public static void main(String[] args) {

		System.out.println("重力付き四目並べ開始");

		// 0:player1 1:player2
		int player = 0;
		Random random = new Random();
		int turn = 0;
		int[][] bord = new int[6][7];
		int i;

		// 盤面初期化(-1)
		for(i = 0; i < 6; i++) {
			for(int j = 0; j < 7; j++) {
				bord[i][j] = -1;
			}
		}

		// 0 || 1
		player = random.nextInt(2);


		Scanner scan = new Scanner(System.in);
		scan.useDelimiter(System.lineSeparator());
		while(true) {
			System.out.println();
			printPlayer(player);

			// コンソールに盤面出力
			printBord(bord);

			// 盤面いっぱいになったら引き分け
			if(turn >= 42) {
				System.out.println("引き分け");
				break;
			}

			// コンソールからの入力とバリデーション
			System.out.println("番号(0～6)を入力してください。");
			String line = scan.next();
			if(line.trim().length() == 0 || line.trim().length() > 1) {
				System.out.println("入力が不正です。");
				continue;
			}
			if(!Character.isDigit(line.charAt(0))) {
				System.out.println("入力が不正です。");
				continue;
			}
			int num = Integer.parseInt(line);
			if(num < 0 || num > 6) {
				System.out.println("入力が不正です。");
				continue;
			}
			for(i = 0; i < 6; i++) {
				if(bord[i][num] == -1) {
					bord[i][num] = player;
					break;
				}
			}
			if(i >= 6) {
				System.out.println("[ " + num + "]にはこれ以上入れられません。");
				continue;
			}
			if(isWin(bord, i , num, player)) {
				System.out.println();
				printBord(bord);
				System.out.println((player == 0 ? "player1[○]":"player2[×]")+"の勝ち!!");
				break;
			}
			player = (player * -1) + 1;
			turn++;
		}
		scan.close();

		System.out.println("終了");

	}

	public static void printPlayer(int player) {
		switch(player){
		case 0:
			System.out.println("player1[○]の番です。");
			break;
		case 1:
			System.out.println("player2[×]の番です。");
			break;
		default:
			System.out.println("エラー");
			return;
		}
	}

	public static void printBord(int[][] bord) {
		for(int j = 0; j < 7; j++) {

			if(j == 6) {
				System.out.println("[ " + j + "]");
			}else {
				System.out.print("[ " + j + "]");
			}
		}
		for(int i = 5; i >= 0; i--) {
			for(int j = 0; j < 7; j++) {
				String a = "";
				a = (bord[i][j] == 0) ? "[○]" : (bord[i][j] == 1) ? "[×]" : "[  ]";
				if(j == 6) {
					System.out.println(a);
				}else {
					System.out.print(a);
				}
			}
		}
	}

	public static boolean isWin(int[][] bord, int i, int j, int player) {
		int yoko = 1;// -
		int tate = 1;// |
		int sura = 1;// /
		int back = 1;// \
		int y = i;
		int x = j;

		// 横方向チェック(右)
		while(x < 6) {
			if(bord[i][x+1] == player) {
				yoko++;
			}else {
				break;
			}
			x++;
		}
		x = j;
		// 横方向チェック(左)
		while(x > 0) {
			if(bord[i][x-1] == player) {
				yoko++;
			}else {
				break;
			}
			x--;
		}
		if(yoko >= 4) {
			return true;
		}

		// 縦方向チェック(上)
		while(y < 5) {
			if(bord[y+1][j] == player) {
				tate++;
			}else {
				break;
			}
			y++;
		}
		y = i;
		// 縦方向チェック(下)
		while(y > 0) {
			if(bord[y-1][j] == player) {
				tate++;
			}else {
				break;
			}
			y--;
		}
		if(tate >= 4) {
			return true;
		}
		y = i;
		x = j;
		// /方向チェック(上)
		while(y < 5 && x < 6) {
			if(bord[y+1][x+1] == player) {
				sura++;
			}else {
				break;
			}
			y++;
			x++;
		}
		y = i;
		x = j;
		// /方向チェック(下)
		while(y > 0 && x > 0) {
			if(bord[y-1][x-1] == player) {
				sura++;
			}else {
				break;
			}
			y--;
			x--;
		}
		if(sura >= 4) {
			return true;
		}
		y = i;
		x = j;
		// \方向チェック(上)
		while(y < 5 && x > 0) {
			if(bord[y+1][x-1] == player) {
				back++;
			}else {
				break;
			}
			y++;
			x--;
		}
		y = i;
		x = j;
		// \方向チェック(下)
		while(y > 0 && x < 6) {
			if(bord[y-1][x+1] == player) {
				back++;
			}else {
				break;
			}
			y--;
			x++;
		}
		if(back >= 4) {
			return true;
		}

		return false;
	}
}
```

ソースはこれで全部です！
全体の流れをざっくり説明すると、
1.player1・2を奇数偶数(0or1)でランダムに先攻を決める。
2.盤面を-1で初期化する。
3.どちらの順番か表示し、盤面を表示する。
4.どこにコマを入れるか番号をコンソールから取得する。
5.入力チェック。
6.盤面に空きがあれば、盤面上にセットする。
7.駒を設置した位置から、縦横ななめの勝利判定をして、条件に当てはまれば終了。
8.playerを切り替え、turnをインクリメントする。
9.3からループ

#勝利判定について
自分が置いた駒から上下左右、スラッシュ、バックスラッシュ方向に判定する。
※重力付きなので自分の置いた駒の上には駒が存在するはずがないので、上方向はいらないですね
自分が置いた駒が基準となるので変数はそれぞれ初期値1にする（現在位置は現playerが今置いた駒）
>
tate = 1;
yoko = 1;
sura = 1;
back = 1;

以下の条件毎にループさせる
>
①
現在位置から見て↑方向がplayerの駒なら
tate++;
現在位置を↑方向にずらしてループ
違う場合は連続しないのでループ終わり

>
②
現在位置から見て↓方向がplayerの駒なら
tate++;
現在位置を↓方向にずらしてループ
違う場合は連続しないのでループ終わり

>
①と②の結果は
tate = ↑方向の連続駒数 + ↓方向の連続駒数 + 1(初期値);
と同じになる。

>
①、②と同じように←→↙↗↖↘方向に適用させると
yoko = ← + → + 1;
sura = ↙ + ↗ + 1;
back = ↖ + ↘ + 1;
が得られる。

>
どれか一つでも >= 4 の条件に当てはまれば現playerの勝利

注意点は各変数を初期値1にすることと、現在位置から見て次のマスをループ条件で見ることです。
現在位置で判断してしまうと、基準点が重なってしまうからです。(初期値0で最終的に-1すれば基準点でも問題ないですが)
例:[3][3]を基準点とし見ていく
（上方向判定）
現在位置[3][3]がplayerなのでインクリメント
上方向に移り現在位置[4][3]...
（下方向判定）
現在位置[3][3]がplayerなのでインクリメント
下方向に移り現在位置[2][3]...

現在位置[3][3]で被りますね。

#まとめ
コピペすればすぐにでも遊べるはずです！
重力付き四目並べは学生の頃遊んでからプチブームの波があります(笑)
暇つぶしがてら遊んでみてください！