Skip to content

Instantly share code, notes, and snippets.

@shiracamus
Last active November 28, 2019 06:26
Show Gist options
  • Save shiracamus/19b9d49664af3640025e432bd5afda1c to your computer and use it in GitHub Desktop.
Save shiracamus/19b9d49664af3640025e432bd5afda1c to your computer and use it in GitHub Desktop.
import java.util.*;
import java.util.stream.*;
import java.awt.*;
import java.awt.Point;
import java.awt.event.*;
import javax.swing.*;
interface Disk {
public void paint(Graphics g, Point p, int size);
public String toString();
}
class Disks {
static final Disk NONE, BLACK, WHITE;
static {
NONE = new Disk() {
public void paint(Graphics g, Point p, int size) {
}
public String toString() {
return "□";
}
};
BLACK = new Disk() {
public void paint(Graphics g, Point p, int size) {
int r = (size / 2) * 4 / 5;
g.setColor(Color.black);
g.fillOval(p.x - r, p.y - r, r * 2, r * 2);
}
public String toString() {
return "×";
}
};
WHITE = new Disk() {
public void paint(Graphics g, Point p, int size) {
int r = (size / 2) * 4 / 5;
g.setColor(Color.white);
g.fillOval(p.x - r, p.y - r, r * 2, r * 2);
}
public String toString() {
return "●";
}
};
}
private static final Map<Disk, Disk> OPPOSITE = new HashMap<Disk, Disk>() {
{
put(NONE, NONE);
put(BLACK, WHITE);
put(WHITE, BLACK);
}
};
static Disk opposite(Disk disk) {
return OPPOSITE.get(disk);
}
}
class Square {
private Disk disk;
Square() {
this.disk = Disks.NONE;
}
boolean is_used() {
return this.disk != Disks.NONE;
}
boolean is(Disk disk) {
return this.disk == disk;
}
void put(Disk disk) {
this.disk = disk;
}
void reverse() {
this.disk = Disks.opposite(this.disk);
}
void paint(Graphics g, Point p, int size) {
disk.paint(g, p, size);
}
public String toString() {
return disk.toString();
}
}
class Board {
final Square[][] squares = new Square[8][8];
final int[][] eval_black = new int[8][8];
final int[][] eval_white = new int[8][8];
private static final Color COLOR = new Color(0, 85, 0);
private static final Point[] DIRECTION = {
new Point(-1, -1),
new Point( 0, -1),
new Point( 1, -1),
new Point(-1, 0),
new Point( 1, 0),
new Point(-1, 1),
new Point( 0, 1),
new Point( 1, 1),
};
Board() {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
squares[x][y] = new Square();
}
}
squares[3][3].put(Disks.WHITE);
squares[4][3].put(Disks.BLACK);
squares[3][4].put(Disks.BLACK);
squares[4][4].put(Disks.WHITE);
}
boolean isOnBoard(int x, int y) {
return 0 <= x && x < 8 && 0 <= y && y < 8;
}
long count(Disk disk) {
return Arrays.stream(squares)
.flatMap(Stream::of)
.filter(m -> m.is(disk))
.count();
}
class Reversible {
final ArrayList<Point> points = new ArrayList<Point>();
void add(Point point) {
points.add(point);
}
void removeAll() {
points.clear();
}
int count() {
return points.size();
}
void reverse() {
points.forEach(p -> squares[p.x][p.y].reverse());
}
}
Reversible getReversible(int x, int y, Point d, Disk s) {
Disk opposite = Disks.opposite(s);
Reversible reversible = new Reversible();
x += d.x;
y += d.y;
while (isOnBoard(x, y) && squares[x][y].is(opposite)) {
reversible.add(new Point(x, y));
x += d.x;
y += d.y;
}
if (!(isOnBoard(x, y) && squares[x][y].is(s)))
reversible.removeAll();
return reversible;
}
int countReversible(int x, int y, Disk s) {
if (squares[x][y].is_used())
return -1;
return Arrays.stream(DIRECTION)
.mapToInt(d -> getReversible(x, y, d, s).count())
.sum();
}
void putAndReverse(int x, int y, Disk s) {
squares[x][y].put(s);
Arrays.stream(DIRECTION).forEach(d -> getReversible(x, y, d, s).reverse());
}
void evaluate() {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
eval_black[x][y] = countReversible(x, y, Disks.BLACK);
eval_white[x][y] = countReversible(x, y, Disks.WHITE);
}
}
}
void printBoard() {
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
System.out.printf("%s ", squares[x][y]);
}
System.out.println();
}
}
void printEvaluation() {
System.out.println("Black(" + Disks.BLACK + "):");
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
System.out.printf("%2d ", eval_black[x][y]);
}
System.out.println();
}
System.out.println("White(" + Disks.WHITE + "):");
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
System.out.printf("%2d ", eval_white[x][y]);
}
System.out.println();
}
}
void paint(Graphics g, int square_size) {
// Background
g.setColor(Color.black);
g.fillRect(0, 0, square_size * 10, square_size * 10);
// Board
g.setColor(Board.COLOR);
g.fillRect(square_size, square_size, square_size * 8, square_size * 8);
// Horizontal Lines
g.setColor(Color.black);
for (int x = 0; x < 9; x++) {
g.drawLine(square_size * (x + 1), square_size, square_size * (x + 1), square_size * 9);
}
// Vertical Lines
g.setColor(Color.black);
for (int y = 0; y < 9; y++) {
g.drawLine(square_size, square_size * (y + 1), square_size * 9, square_size * (y + 1));
}
// Dots
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 2; y++) {
g.fillRect(square_size * (3 + 4 * x) - (square_size / 16),
square_size * (3 + 4 * y) - (square_size / 16),
square_size / 8,
square_size / 8);
}
}
// Disks
Point p = new Point();
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
p.x = square_size * (x + 1) + square_size / 2;
p.y = square_size * (y + 1) + square_size / 2;
squares[x][y].paint(g, p, square_size);
}
}
}
}
class Player {
private final String name;
private final Disk disk;
private final int[][] evaluation;
Player(String name, Disk disk, int[][] evaluation) {
this.name = name;
this.disk = disk;
this.evaluation = evaluation;
}
public String toString() {
return name;
}
boolean putable(Board board, int x, int y) {
return evaluation[x][y] >= 1;
}
void putAndReverse(Board board, int x, int y) {
board.putAndReverse(x, y, disk);
}
long count(Board board) {
return board.count(disk);
}
boolean pass() {
return Arrays.stream(evaluation)
.flatMapToInt(Arrays::stream)
.allMatch(n -> n <= 0);
}
}
public class Reversi extends JPanel {
private static final int SQUARE_SIZE = 80;
private final Board board = new Board();
private final Player player1 = new Player("黒", Disks.BLACK, board.eval_black);
private final Player player2 = new Player("白", Disks.WHITE, board.eval_white);
private Player player = player1;
public Reversi() {
setPreferredSize(new Dimension(800, 800));
addMouseListener(new MouseHandler());
}
void turnPlayer() {
player = player == player1 ? player2 : player1;
}
public void paintComponent(Graphics g) {
board.paint(g, SQUARE_SIZE);
}
void showMessage(String message, String title) {
JOptionPane.showMessageDialog(this, message, title, JOptionPane.INFORMATION_MESSAGE);
}
void showMessage(String message) {
showMessage(message, "情報");
}
void endGameAndExit() {
long num_player1 = player1.count(board);
long num_player2 = player2.count(board);
String message = "["
+ player1 + ":" + num_player1 + ","
+ player2 + ":" + num_player2 + "]で";
if (num_player1 > num_player2) {
message += player1 + "の勝ち";
} else if (num_player1 <= num_player2) {
message += player2 + "の勝ち";
} else {
message += "引き分け";
}
showMessage(message, "ゲーム終了");
System.exit(0);
}
class MouseHandler extends MouseAdapter {
public void mouseClicked(MouseEvent me) {
board.printBoard();
Point point = me.getPoint();
System.out.println("(" + point.x + "," + point.y + ")");
int x = point.x / SQUARE_SIZE - 1;
int y = point.y / SQUARE_SIZE - 1;
if (!(0 <= x && x < 8 && 0 <= y && y < 8)) return;
System.out.println("[" + x + "]" + "[" + y + "]");
int btn = me.getButton();
if (player == player1 && btn == MouseEvent.BUTTON1 ||
player == player2 && btn == MouseEvent.BUTTON3) {
put(x, y);
}
}
}
void put(int x, int y) {
board.evaluate();
if (!player.putable(board, x, y)) {
System.out.println("そこに石を置けません");
return;
}
player.putAndReverse(board, x, y);
repaint();
board.printBoard();
board.evaluate();
board.printEvaluation();
if (player1.pass() && player2.pass()) {
endGameAndExit();
}
turnPlayer();
if (player.pass()) {
showMessage(player + "はパスです");
turnPlayer();
}
showMessage(player + "の番です");
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.getContentPane().setLayout(new FlowLayout());
f.getContentPane().add(new Reversi());
f.pack();
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment