ヘキサポーン Hexapawn VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Text
Module HexPawn
Enum HexPawnDefs As Byte
None
Black
White
Empty
End Enum
Class HpPoint
Public Property file As Integer
Public Property rank As Integer
Public Sub New()
file = -1
rank = -1
End Sub
Public Sub New(f As Integer, r As Integer)
file = f
rank = r
End Sub
Public Function Mirror() As HpPoint
Dim PtMirror As New HpPoint(Me.file, Me.rank)
If PtMirror.file = 0 Then
PtMirror.file = 2
ElseIf PtMirror.file = 2 Then
PtMirror.file = 0
End If
Return PtMirror
End Function
Public Overrides Function ToString() As String
Dim s As String = ""
s += ChrW(Asc("a"c) + Me.file)
s += ChrW(Asc("1"c) + Me.rank)
Return s
End Function
End Class
Class HpBoard
Protected Shared BOARD_SIZE As Integer = 3
Protected Squares As HexPawnDefs(,) = New HexPawnDefs(BOARD_SIZE - 1, BOARD_SIZE - 1) {}
Public Sub New()
For file As Integer = 0 To BOARD_SIZE - 1
SetSquare(New HpPoint(file, 2), HexPawnDefs.Black)
SetSquare(New HpPoint(file, 1), HexPawnDefs.Empty)
SetSquare(New HpPoint(file, 0), HexPawnDefs.White)
Next
End Sub
Public Shared Function GetAllPoints() As HpPoint()
Dim list As New List(Of HpPoint)()
For rank As Integer = 0 To BOARD_SIZE - 1
For file As Integer = 0 To BOARD_SIZE - 1
list.Add(New HpPoint(file, rank))
Next
Next
Return list.ToArray()
End Function
Public Function GetSquare(pt As HpPoint) As HexPawnDefs
Return GetSquare(pt.file, pt.rank)
End Function
Public Function GetSquare(file As Integer, rank As Integer) As HexPawnDefs
If 0 <= file AndAlso file < BOARD_SIZE AndAlso 0 <= rank AndAlso rank < BOARD_SIZE Then
Return Squares(file, rank)
Else
Return HexPawnDefs.None
End If
End Function
Public Sub SetSquare(pt As HpPoint, pawn As HexPawnDefs)
SetSquare(pt.file, pt.rank, pawn)
End Sub
Public Sub SetSquare(file As Integer, rank As Integer, pawn As HexPawnDefs)
If 0 <= file AndAlso file < BOARD_SIZE AndAlso 0 <= rank AndAlso rank < BOARD_SIZE Then
Squares(file, rank) = pawn
End If
End Sub
Public Sub Show()
Console.WriteLine("")
For rank As Integer = BOARD_SIZE - 1 To 0 Step -1
Console.Write(vbLf & " +---+---+---+")
Console.Write(vbLf & " " & (rank + 1) & " |")
For file As Integer = 0 To BOARD_SIZE - 1
If GetSquare(New HpPoint(file, rank)) = HexPawnDefs.Black Then
Console.Write(" ○|")
ElseIf GetSquare(New HpPoint(file, rank)) = HexPawnDefs.White Then
Console.Write(" ●|")
ElseIf (rank Mod 2) = (file Mod 2) Then
Console.Write(":::|")
Else
Console.Write(" |")
End If
Next
If rank = 2 Then
Console.Write(" 7 8 9")
ElseIf rank = 1 Then
Console.Write(" 4 5 6")
ElseIf rank = 0 Then
Console.Write(" 1 2 3")
End If
Next
Console.Write(vbLf & " +---+---+---+")
Console.Write(vbLf & " a b c" & vbLf)
End Sub
Public Function IsMoveablePawn(pt As HpPoint) As Boolean
Dim dir As Integer
Dim opp As HexPawnDefs
If GetSquare(pt) = HexPawnDefs.White Then
dir = 1
opp = HexPawnDefs.Black
ElseIf GetSquare(pt) = HexPawnDefs.Black Then
dir = -1
opp = HexPawnDefs.White
Else
Return False
End If
If GetSquare(pt.file, pt.rank + dir) = HexPawnDefs.Empty Then
Return True
ElseIf GetSquare(pt.file - 1, pt.rank + dir) = opp Then
Return True
ElseIf GetSquare(pt.file + 1, pt.rank + dir) = opp Then
Return True
Else
Return False
End If
End Function
Public Function CheckFinish(NextTurn As HexPawnDefs) As HexPawnDefs
For file As Integer = 0 To BOARD_SIZE - 1
If GetSquare(file, BOARD_SIZE - 1) = HexPawnDefs.White Then
Return HexPawnDefs.White
ElseIf GetSquare(file, 0) = HexPawnDefs.Black Then
Return HexPawnDefs.Black
End If
Next
Dim all As HpPoint() = HpBoard.GetAllPoints()
Dim cntWhite As Integer = 0
Dim cntBlack As Integer = 0
For Each pt As HpPoint In all
If IsMoveablePawn(pt) Then
If HexPawnDefs.White = GetSquare(pt) Then
cntWhite += 1
ElseIf HexPawnDefs.Black = GetSquare(pt) Then
cntBlack += 1
End If
End If
Next
If NextTurn = HexPawnDefs.White AndAlso cntWhite = 0 Then
Return HexPawnDefs.Black
ElseIf NextTurn = HexPawnDefs.Black AndAlso cntBlack = 0 Then
Return HexPawnDefs.White
End If
Return HexPawnDefs.Empty
End Function
End Class
Class HpBoardMove
Inherits HpBoard
Protected PtFrom As HpPoint = Nothing
Protected PtTo As HpPoint = Nothing
Public Sub New()
End Sub
Public Sub New(bdmove As HpBoardMove)
Dim all As HpPoint() = HpBoard.GetAllPoints()
For Each pt As HpPoint In all
SetSquare(pt, bdmove.GetSquare(pt))
Next
PtFrom = bdmove.PtFrom
PtTo = bdmove.PtTo
End Sub
Public Sub SetMove(f As HpPoint, t As HpPoint)
PtFrom = f
PtTo = t
End Sub
Public Function IsValidMove() As Boolean
Dim df As Integer = PtTo.file - PtFrom.file
Dim dr As Integer = PtTo.rank - PtFrom.rank
If GetSquare(PtFrom) = HexPawnDefs.White Then
If GetSquare(PtTo) = HexPawnDefs.Empty AndAlso df = 0 AndAlso dr = 1 Then
Return True
ElseIf GetSquare(PtTo) = HexPawnDefs.Black AndAlso (df = 1 OrElse df = -1) AndAlso dr = 1 Then
Return True
End If
ElseIf GetSquare(PtFrom) = HexPawnDefs.Black Then
If GetSquare(PtTo) = HexPawnDefs.Empty AndAlso df = 0 AndAlso dr = -1 Then
Return True
ElseIf GetSquare(PtTo) = HexPawnDefs.White AndAlso (df = 1 OrElse df = -1) AndAlso dr = -1 Then
Return True
End If
End If
Return False
End Function
Public Function TestEqual(bdmove As HpBoardMove) As Boolean
Dim all As HpPoint() = HpBoard.GetAllPoints()
For Each pt As HpPoint In all
If Me.GetSquare(pt) <> bdmove.GetSquare(pt) Then
Return False
End If
Next
If PtFrom.file <> bdmove.PtFrom.file OrElse PtFrom.rank <> bdmove.PtFrom.rank OrElse PtTo.file <> bdmove.PtTo.file OrElse PtTo.rank <> bdmove.PtTo.rank Then
Return False
End If
Return True
End Function
Public Sub MovePawn()
SetSquare(PtTo, GetSquare(PtFrom))
SetSquare(PtFrom, HexPawnDefs.Empty)
End Sub
Public Function MakeMirror() As HpBoardMove
Dim mirror As New HpBoardMove()
mirror.SetMove(PtFrom.Mirror(), PtTo.Mirror())
Dim all As HpPoint() = HpBoard.GetAllPoints()
For Each pt As HpPoint In all
mirror.SetSquare(pt, GetSquare(pt.Mirror()))
Next
Return mirror
End Function
End Class
Class Game
Private DefeatList As New List(Of HpBoardMove)()
Private RandObj As New Random()
Private PlayerColor As HexPawnDefs = HexPawnDefs.White
Private MatchBoxColor As HexPawnDefs = HexPawnDefs.Black
Public Function ExistDefeatList(bdmove As HpBoardMove) As Boolean
Dim mirror As HpBoardMove = bdmove.MakeMirror()
For Each defeat As HpBoardMove In DefeatList
If defeat.TestEqual(bdmove) Then
Return True
End If
If defeat.TestEqual(mirror) Then
Return True
End If
Next
Return False
End Function
Public Function MatchBoxTurn(bdmove As HpBoardMove) As Boolean
Dim allsq As HpPoint() = HpBoard.GetAllPoints()
For i As Integer = 0 To 19
Dim p As Integer = RandObj.Next(allsq.Length)
Dim q As Integer = RandObj.Next(allsq.Length)
If p <> q Then
Dim t As HpPoint = allsq(p)
allsq(p) = allsq(q)
allsq(q) = t
End If
Next
For Each f As HpPoint In allsq
If bdmove.GetSquare(f) <> MatchBoxColor Then
Continue For
End If
For Each t As HpPoint In allsq
bdmove.SetMove(f, t)
If bdmove.IsValidMove() AndAlso Not ExistDefeatList(bdmove) Then
Console.Write(vbLf & "マッチ箱: " & f.ToString() & " を " & t.ToString() & " へ")
Return True
End If
Next
Next
Console.Write(vbLf & "リザインします。")
Return False
End Function
Private Function InputSquarePoint(strGuide As String) As HpPoint
While True
Console.Write(strGuide)
Dim kinfo As ConsoleKeyInfo = Console.ReadKey()
Select Case kinfo.KeyChar
Case "7"c
Return New HpPoint(0, 2)
Case "8"c
Return New HpPoint(1, 2)
Case "9"c
Return New HpPoint(2, 2)
Case "4"c
Return New HpPoint(0, 1)
Case "5"c
Return New HpPoint(1, 1)
Case "6"c
Return New HpPoint(2, 1)
Case "1"c
Return New HpPoint(0, 0)
Case "2"c
Return New HpPoint(1, 0)
Case "3"c
Return New HpPoint(2, 0)
End Select
End While
Return New HpPoint(-1, -1)
End Function
Public Sub PlayerTurn(bdmove As HpBoardMove)
Dim PtFrom As New HpPoint(-1, -1)
Dim PtTo As New HpPoint(-1, -1)
While True
PtFrom = InputSquarePoint(vbLf & "駒を選んでください(1~9):")
If PlayerColor = bdmove.GetSquare(PtFrom) AndAlso bdmove.IsMoveablePawn(PtFrom) Then
Exit While
Else
Console.Write(vbLf & "動かせる駒がありません")
End If
End While
While True
PtTo = InputSquarePoint(vbLf & "どこに動かしますか?(1~9):")
bdmove.SetMove(PtFrom, PtTo)
If bdmove.IsValidMove() Then
Exit While
Else
Console.Write(vbLf & "そこには動かせません")
End If
End While
End Sub
Public Sub Play()
Dim board As New HpBoardMove()
Dim lastMatchBoxMove As HpBoardMove = Nothing
Dim winner As HexPawnDefs = HexPawnDefs.None
Dim turn As HexPawnDefs = HexPawnDefs.White
board.Show()
While winner <> HexPawnDefs.White AndAlso winner <> HexPawnDefs.Black
If turn = PlayerColor Then
PlayerTurn(board)
Else
If MatchBoxTurn(board) Then
lastMatchBoxMove = New HpBoardMove(board)
Else
winner = PlayerColor
Exit While
End If
End If
board.MovePawn()
board.Show()
If turn = HexPawnDefs.Black Then
turn = HexPawnDefs.White
Else
turn = HexPawnDefs.Black
End If
winner = board.CheckFinish(turn)
End While
If winner = HexPawnDefs.White Then
Console.Write(vbLf & "白の勝ちです。" & vbLf)
ElseIf winner = HexPawnDefs.Black Then
Console.Write(vbLf & "黒の勝ちです。" & vbLf)
End If
If winner <> MatchBoxColor AndAlso lastMatchBoxMove IsNot Nothing Then
DefeatList.Add(lastMatchBoxMove)
End If
End Sub
End Class
Sub Main()
Dim reply As ConsoleKeyInfo
Dim game As New Game()
Do
game.Play()
Console.Write("終了する場合は'Q'、続ける場合は他のキーを押してください")
reply = Console.ReadKey()
Loop While reply.Key <> ConsoleKey.Q
End Sub
End Module