ヘキサポーン Hexapawn C#
using System;
using System.Collections.Generic;
using System.Text;
enum HexPawnDefs : byte
{
None,
Black,
White,
Empty
}
class HpPoint
{
public int file { get; set; }
public int rank { get; set; }
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 override 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()
{
List<HpPoint> list = new List<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();
}
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()
{
Console.WriteLine("");
for (int rank = BOARD_SIZE - 1; rank >= 0; rank--)
{
Console.Write("\n +---+---+---+");
Console.Write("\n " + (rank + 1) + " |");
for (int file = 0; file < BOARD_SIZE; file++)
{
if (GetSquare(new HpPoint(file, rank)) == HexPawnDefs.Black)
Console.Write(" ○|");
else if (GetSquare(new HpPoint(file, rank)) == HexPawnDefs.White)
Console.Write(" ●|");
else if ((rank % 2) == (file % 2))
Console.Write(":::|");
else
Console.Write(" |");
}
if (rank == 2)
Console.Write(" 7 8 9");
else if (rank == 1)
Console.Write(" 4 5 6");
else if (rank == 0)
Console.Write(" 1 2 3");
}
Console.Write("\n +---+---+---+");
Console.Write("\n a b c\n");
}
public bool 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;
foreach( HpPoint pt in 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 : HpBoard
{
protected HpPoint From = null;
protected HpPoint To = null;
public HpBoardMove()
{
}
public HpBoardMove(HpBoardMove bdmove)
{
HpPoint[] all = HpBoard.GetAllPoints();
foreach (HpPoint pt in all)
SetSquare(pt, bdmove.GetSquare(pt));
From = bdmove.From;
To = bdmove.To;
}
public void SetMove(HpPoint from, HpPoint to)
{
From = from;
To = to;
}
public bool 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 bool TestEqual(HpBoardMove bdmove)
{
HpPoint[] all = HpBoard.GetAllPoints();
foreach (HpPoint pt in 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();
foreach (HpPoint pt in all)
mirror.SetSquare(pt, GetSquare(pt.Mirror()));
return mirror;
}
};
class Game
{
private List<HpBoardMove> DefeatList = new List<HpBoardMove>();
private Random RandObj = new Random();
private HexPawnDefs PlayerColor = HexPawnDefs.White;
private HexPawnDefs MatchBoxColor = HexPawnDefs.Black;
public bool ExistDefeatList(HpBoardMove bdmove)
{
HpBoardMove mirror = bdmove.MakeMirror();
foreach (HpBoardMove defeat in DefeatList)
{
if (defeat.TestEqual(bdmove))
return true;
if (defeat.TestEqual(mirror))
return true;
}
return false;
}
public bool MatchBoxTurn(HpBoardMove bdmove)
{
HpPoint[] allsq = HpBoard.GetAllPoints();
for (int i = 0; i < 20; i++)
{
int p = RandObj.Next(allsq.Length);
int q = RandObj.Next(allsq.Length);
if (p != q)
{
HpPoint t = allsq[p];
allsq[p] = allsq[q];
allsq[q] = t;
}
}
foreach (HpPoint from in allsq)
{
if (bdmove.GetSquare(from) != MatchBoxColor)
continue;
foreach (HpPoint to in allsq)
{
bdmove.SetMove(from, to);
if (bdmove.IsValidMove() && !ExistDefeatList(bdmove))
{
Console.Write("\nマッチ箱: " + from.ToString() + " を " + to.ToString() + " へ");
return true;
}
}
}
Console.Write("\nリザインします。");
return false;
}
HpPoint InputSquarePoint(string strGuide)
{
for (; ; )
{
Console.Write(strGuide);
ConsoleKeyInfo kinfo = Console.ReadKey();
switch (kinfo.KeyChar)
{
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)
{
HpPoint from, to;
for (; ; )
{
from = InputSquarePoint("\n駒を選んでください(1~9):");
if (PlayerColor == bdmove.GetSquare(from) && bdmove.IsMoveablePawn(from))
break;
else
Console.Write("\n動かせる駒がありません");
}
for (; ; )
{
to = InputSquarePoint("\nどこに動かしますか?(1~9):");
bdmove.SetMove(from, to);
if (bdmove.IsValidMove())
break;
else
Console.Write("\nそこには動かせません");
}
}
public void Play()
{
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)
Console.Write("\n白の勝ちです。\n");
else if (winner == HexPawnDefs.Black)
Console.Write("\n黒の勝ちです。\n");
if (winner != MatchBoxColor && lastMatchBoxMove != null)
DefeatList.Add(lastMatchBoxMove);
}
};
class HexPawn
{
static void Main(string[] args)
{
ConsoleKeyInfo reply;
Game game = new Game();
do
{
game.Play();
Console.Write("終了する場合は'Q'、続ける場合は他のキーを押してください");
reply = Console.ReadKey();
} while (reply.Key != ConsoleKey.Q);
}
}