ヘキサポーン Hexapawn Java
import java.io.*;
import java.util.*;
enum HexPawnDefs
{
None,
Black,
White,
Empty
}
class HpPoint
{
public int file;
public int rank;
public HpPoint()
{
file = -1;
rank = -1;
}
public HpPoint(int f, int r)
{
file = f;
rank = r;
}
public HpPoint Mirror()
{
HpPoint mirror = new HpPoint(this.file, this.rank);
if (mirror.file == 0)
mirror.file = 2;
else if (mirror.file == 2)
mirror.file = 0;
return mirror;
}
public String ToString()
{
String s = "";
s += (char)('a' + this.file);
s += (char)('1' + this.rank);
return s;
}
}
class HpBoard
{
protected static int BOARD_SIZE = 3;
protected HexPawnDefs[][] Squares = new HexPawnDefs[BOARD_SIZE][BOARD_SIZE];
public HpBoard()
{
for (int file = 0; file < BOARD_SIZE; file++)
{
SetSquare(new HpPoint(file, 2), HexPawnDefs.Black);
SetSquare(new HpPoint(file, 1), HexPawnDefs.Empty);
SetSquare(new HpPoint(file, 0), HexPawnDefs.White);
}
}
public static HpPoint[] GetAllPoints()
{
ArrayList<HpPoint> list = new ArrayList<HpPoint>();
for (int rank = 0; rank < BOARD_SIZE; rank++)
{
for (int file = 0; file < BOARD_SIZE; file++)
list.add(new HpPoint(file, rank));
}
return list.toArray(new HpPoint[0]);
}
public HexPawnDefs GetSquare(HpPoint pt)
{
return GetSquare(pt.file, pt.rank);
}
public HexPawnDefs GetSquare(int file, int rank)
{
if (0 <= file && file < BOARD_SIZE
&& 0 <= rank && rank < BOARD_SIZE)
{
return Squares[file][rank];
}
else
{
return HexPawnDefs.None;
}
}
public void SetSquare(HpPoint pt, HexPawnDefs pawn)
{
SetSquare(pt.file, pt.rank, pawn);
}
public void SetSquare(int file, int rank, HexPawnDefs pawn)
{
if (0 <= file && file < BOARD_SIZE
&& 0 <= rank && rank < BOARD_SIZE)
{
Squares[file][rank] = pawn;
}
}
public void Show()
{
System.out.println("");
for (int rank = BOARD_SIZE - 1; rank >= 0; rank--)
{
System.out.print("\n +---+---+---+");
System.out.print("\n " + (rank + 1) + " |");
for (int file = 0; file < BOARD_SIZE; file++)
{
if (GetSquare(new HpPoint(file, rank)) == HexPawnDefs.Black)
System.out.print(" ○|");
else if (GetSquare(new HpPoint(file, rank)) == HexPawnDefs.White)
System.out.print(" ●|");
else if ((rank % 2) == (file % 2))
System.out.print(":::|");
else
System.out.print(" |");
}
if (rank == 2)
System.out.print(" 7 8 9");
else if (rank == 1)
System.out.print(" 4 5 6");
else if (rank == 0)
System.out.print(" 1 2 3");
}
System.out.print("\n +---+---+---+");
System.out.print("\n a b c\n");
}
public boolean IsMoveablePawn(HpPoint pt)
{
int dir;
HexPawnDefs opp;
if (GetSquare(pt) == HexPawnDefs.White)
{
dir = 1;
opp = HexPawnDefs.Black;
}
else if (GetSquare(pt) == HexPawnDefs.Black)
{
dir = -1;
opp = HexPawnDefs.White;
}
else
{
return false;
}
if (GetSquare(pt.file, pt.rank + dir) == HexPawnDefs.Empty)
return true;
else if (GetSquare(pt.file - 1, pt.rank + dir) == opp)
return true;
else if (GetSquare(pt.file + 1, pt.rank + dir) == opp)
return true;
else
return false;
}
public HexPawnDefs CheckFinish(HexPawnDefs next)
{
for (int file = 0; file < BOARD_SIZE; file++)
{
if (GetSquare(file, BOARD_SIZE - 1) == HexPawnDefs.White)
return HexPawnDefs.White;
else if (GetSquare(file, 0) == HexPawnDefs.Black)
return HexPawnDefs.Black;
}
HpPoint[] all = HpBoard.GetAllPoints();
int cntWhite = 0;
int cntBlack = 0;
for( HpPoint pt : all )
{
if (IsMoveablePawn(pt))
{
if (HexPawnDefs.White == GetSquare(pt))
cntWhite++;
else if (HexPawnDefs.Black == GetSquare(pt))
cntBlack++;
}
}
if (next == HexPawnDefs.White && cntWhite == 0)
return HexPawnDefs.Black;
else if (next == HexPawnDefs.Black && cntBlack == 0)
return HexPawnDefs.White;
return HexPawnDefs.Empty;
}
};
class HpBoardMove extends HpBoard
{
protected HpPoint From = null;
protected HpPoint To = null;
public HpBoardMove()
{
}
public HpBoardMove(HpBoardMove bdmove)
{
HpPoint[] all = HpBoard.GetAllPoints();
for (HpPoint pt : all)
SetSquare(pt, bdmove.GetSquare(pt));
From = bdmove.From;
To = bdmove.To;
}
public void SetMove(HpPoint from, HpPoint to)
{
From = from;
To = to;
}
public boolean IsValidMove()
{
int df = To.file - From.file;
int dr = To.rank - From.rank;
if (GetSquare(From) == HexPawnDefs.White)
{
if (GetSquare(To) == HexPawnDefs.Empty && df == 0 && dr == 1)
return true;
else if (GetSquare(To) == HexPawnDefs.Black && (df == 1 || df == -1) && dr == 1)
return true;
}
else if (GetSquare(From) == HexPawnDefs.Black)
{
if (GetSquare(To) == HexPawnDefs.Empty && df == 0 && dr == -1)
return true;
else if (GetSquare(To) == HexPawnDefs.White && (df == 1 || df == -1) && dr == -1)
return true;
}
return false;
}
public boolean TestEqual(HpBoardMove bdmove)
{
HpPoint[] all = HpBoard.GetAllPoints();
for (HpPoint pt : all)
{
if (this.GetSquare(pt) != bdmove.GetSquare(pt))
return false;
}
if (this.From.file != bdmove.From.file || this.From.rank != bdmove.From.rank
|| this.To.file != bdmove.To.file || this.To.rank != bdmove.To.rank)
return false;
return true;
}
public void MovePawn()
{
SetSquare(To, GetSquare(From));
SetSquare(From, HexPawnDefs.Empty);
}
public HpBoardMove MakeMirror()
{
HpBoardMove mirror = new HpBoardMove();
mirror.SetMove(From.Mirror(), To.Mirror());
HpPoint[] all = HpBoard.GetAllPoints();
for (HpPoint pt : all)
mirror.SetSquare(pt, GetSquare(pt.Mirror()));
return mirror;
}
};
class HexPawn
{
private ArrayList<HpBoardMove> DefeatList = new ArrayList<HpBoardMove>();
private Random RandObj = new Random();
private HexPawnDefs PlayerColor = HexPawnDefs.White;
private HexPawnDefs MatchBoxColor = HexPawnDefs.Black;
public boolean ExistDefeatList(HpBoardMove bdmove)
{
HpBoardMove mirror = bdmove.MakeMirror();
for (HpBoardMove defeat : DefeatList)
{
if (defeat.TestEqual(bdmove))
return true;
if (defeat.TestEqual(mirror))
return true;
}
return false;
}
public boolean MatchBoxTurn(HpBoardMove bdmove)
{
HpPoint[] allsq = HpBoard.GetAllPoints();
for (int i = 0; i < 20; i++)
{
int p = RandObj.nextInt(allsq.length);
int q = RandObj.nextInt(allsq.length);
if (p != q)
{
HpPoint t = allsq[p];
allsq[p] = allsq[q];
allsq[q] = t;
}
}
for (HpPoint from : allsq)
{
if (bdmove.GetSquare(from) != MatchBoxColor)
continue;
for (HpPoint to : allsq)
{
bdmove.SetMove(from, to);
if (bdmove.IsValidMove() && !ExistDefeatList(bdmove))
{
System.out.print("\nマッチ箱: " + from.ToString() + " を " + to.ToString() + " へ");
return true;
}
}
}
System.out.print("\nリザインします。");
return false;
}
HpPoint InputSquarePoint(String strGuide) throws IOException
{
BufferedReader br = new BufferedReader(
new InputStreamReader( System.in ) );
for (; ; )
{
System.out.print(strGuide);
String line = br.readLine();
if( line.length() == 0 )
continue;
switch ( line.charAt(0) )
{
case '7':
return new HpPoint(0, 2);
case '8':
return new HpPoint(1, 2);
case '9':
return new HpPoint(2, 2);
case '4':
return new HpPoint(0, 1);
case '5':
return new HpPoint(1, 1);
case '6':
return new HpPoint(2, 1);
case '1':
return new HpPoint(0, 0);
case '2':
return new HpPoint(1, 0);
case '3':
return new HpPoint(2, 0);
}
}
}
public void PlayerTurn(HpBoardMove bdmove) throws IOException
{
HpPoint from, to;
for (; ; )
{
from = InputSquarePoint("\n駒を選んでください(1~9):");
if (PlayerColor == bdmove.GetSquare(from) && bdmove.IsMoveablePawn(from))
break;
else
System.out.print("\n動かせる駒がありません");
}
for (; ; )
{
to = InputSquarePoint("\nどこに動かしますか?(1~9):");
bdmove.SetMove(from, to);
if (bdmove.IsValidMove())
break;
else
System.out.print("\nそこには動かせません");
}
}
public void Play() throws IOException
{
HpBoardMove board = new HpBoardMove();
HpBoardMove lastMatchBoxMove = null;
HexPawnDefs winner = HexPawnDefs.None;
HexPawnDefs turn = HexPawnDefs.White;
board.Show();
while (winner != HexPawnDefs.White && winner != HexPawnDefs.Black)
{
if (turn == PlayerColor)
{
PlayerTurn(board);
}
else
{
if (MatchBoxTurn(board))
{
lastMatchBoxMove = new HpBoardMove(board);
}
else
{
winner = PlayerColor;
break;
}
}
board.MovePawn();
board.Show();
if (turn == HexPawnDefs.Black)
turn = HexPawnDefs.White;
else
turn = HexPawnDefs.Black;
winner = board.CheckFinish(turn);
}
if (winner == HexPawnDefs.White)
System.out.print("\n白の勝ちです。\n");
else if (winner == HexPawnDefs.Black)
System.out.print("\n黒の勝ちです。\n");
if (winner != MatchBoxColor && lastMatchBoxMove != null)
DefeatList.add(lastMatchBoxMove);
}
public static void main( String[] args ) throws IOException
{
String reply;
char q;
HexPawn game = new HexPawn();
do
{
game.Play();
System.out.print("終了する場合は'Q'、続ける場合は他のキーを押してください");
BufferedReader br = new BufferedReader(
new InputStreamReader( System.in ) );
reply = br.readLine();
if( reply.length() > 0 )
q = reply.charAt(0);
else
q = 0;
} while (q != 'q' && q != 'Q');
}
}