ヘキサポーン 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