Skip to content

Instantly share code, notes, and snippets.

@shiracamus
Last active December 14, 2019 12:39
Show Gist options
  • Save shiracamus/c2b09af21e50c4fde86ab73a251ca113 to your computer and use it in GitHub Desktop.
Save shiracamus/c2b09af21e50c4fde86ab73a251ca113 to your computer and use it in GitHub Desktop.
import java.util.Scanner;
enum Cell {
EMPTY("[ ]"),
PLAYER1("[O]"),
PLAYER2("[X]");
private final String text;
private Cell(final String text) {
this.text = text;
}
public String toString() {
return text;
}
}
class Board {
public final int width;
public final int height;
private final Cell[][] cells;
Board(int width, int height) {
this.width = width;
this.height = height;
this.cells = new Cell[height][width];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
cells[y][x] = Cell.EMPTY;
}
}
}
void put(int x, int y, Cell cell) {
cells[y][x] = cell;
}
boolean isInside(int x, int y) {
return 0 <= x && x < width && 0 <= y && y < height;
}
boolean isCell(int x, int y, Cell cell) {
return isInside(x, y) && cells[y][x] == cell;
}
boolean isEmpty(int x, int y) {
return isCell(x, y, Cell.EMPTY);
}
void print() {
for (int x = 0; x < width; x++) {
System.out.printf("[%2d]", x);
}
System.out.println();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
System.out.print(cells[y][x]);
}
System.out.println();
}
System.out.println();
}
}
class Rule {
public final Board board;
public final int connectionsToWin;
public final int minColumn;
public final int maxColumn;
private static final int[][] DIRECTIONS = new int[][] {
{1, 0}, {0, 1}, {1, 1}, {-1, 1}
};
Rule(Board board, int connectionsToWin) {
this.board = board;
this.connectionsToWin = connectionsToWin;
minColumn = 0;
maxColumn = board.width - 1;
}
boolean isValid(int column) {
return board.isInside(column, 0);
}
boolean isAvailable(int column) {
return board.isEmpty(column, 0);
}
boolean put(int column, Cell cell) {
int row = fall(column);
board.put(column, row, cell);
return isWin(column, row, cell);
}
int fall(int column) {
int row = 0;
while (board.isEmpty(column, row)) {
row++;
}
return row - 1;
}
boolean isWin(int x, int y, Cell cell) {
for (var d : DIRECTIONS) {
int dx = d[0], dy = d[1];
int connections = 1;
for (int cx = x - dx, cy = y - dy; board.isCell(cx, cy, cell); cx -= dx, cy -= dy) {
connections++;
}
for (int cx = x + dx, cy = y + dy; board.isCell(cx, cy, cell); cx += dx, cy += dy) {
connections++;
}
if (connections >= connectionsToWin) {
return true;
}
}
return false;
}
}
interface Strategy {
boolean put(Cell cell, Rule rule); // return ture if win
}
class Player {
public final String name;
public final Cell cell;
private String text;
private Strategy strategy;
Player(String name, Cell cell, Strategy strategy) {
this.name = name;
this.cell = cell;
this.text = name + cell;
this.strategy = strategy;
}
public String toString() {
return text;
}
boolean play(Rule rule) {
return strategy.put(cell, rule);
}
}
class InteractiveStrategy implements Strategy {
private final Scanner keyboard = new Scanner(System.in);
{
keyboard.useDelimiter(System.lineSeparator());
}
public boolean put(Cell cell, Rule rule) {
return rule.put(selectColumn(rule), cell);
}
public int selectColumn(Rule rule) {
while (true) {
System.out.printf("番号(%d〜%d)を入力してください: ", rule.minColumn, rule.maxColumn);
String text = keyboard.next().trim();
if (text.length() != 1 || !Character.isDigit(text.charAt(0))) {
System.out.println("入力が不正です。");
continue;
}
int column = Integer.parseInt(text);
if (!rule.isValid(column)) {
System.out.println("入力が不正です。");
continue;
}
if (!rule.isAvailable(column)) {
System.out.println("[ " + column + "]にはこれ以上入れられません。");
continue;
}
return column;
}
}
}
public class ConnectFour {
private final Rule rule;
private final Board board;
private final Player player1, player2;
ConnectFour() {
this(7, 6, 4);
}
ConnectFour(int width, int height, int connectionsToWin) {
board = new Board(width, height);
rule = new Rule(board, connectionsToWin);
Strategy interactive = new InteractiveStrategy();
player1 = new Player("player1", Cell.PLAYER1, interactive);
player2 = new Player("player2", Cell.PLAYER2, interactive);
}
void start() {
char num = "零一二三四五六七八九十".charAt(rule.connectionsToWin);
System.out.println("重力付き" + num + "目並べ開始");
play();
System.out.println("終了");
}
void play() {
Player player = player1;
board.print();
for (int turn = 0; turn < board.width * board.height; turn++) {
System.out.println(player + "の番です。");
boolean win = player.play(rule);
System.out.println();
board.print();
if (win) {
System.out.println(player + "の勝ち!!");
return;
}
player = player == player1 ? player2 : player1;
}
System.out.println("引き分け");
}
public static void main(String[] args) {
new ConnectFour().start();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment