Imports System.Drawing
Imports System.Windows.Forms

Public Class Form1
    Private WithEvents playerGridPanel As Panel
    Private WithEvents enemyGridPanel As Panel
    Private WithEvents statusLabel As Label
    Private WithEvents restartButton As Button
    Private WithEvents shipStatusLabel As Label

    ' Game constants
    Private Const GRID_SIZE As Integer = 8
    Private Const CELL_SIZE As Integer = 40
    Private Const SHIP_COUNT As Integer = 5

    ' Game state
    Private playerGrid(,) As GridCell
    Private enemyGrid(,) As GridCell
    Private ships As List(Of Ship)
    Private gameStarted As Boolean = False
    Private playerTurn As Boolean = True
    Private enemyHits As Integer = 0
    Private playerHits As Integer = 0

    ' Ship definitions: name, size
    Private ReadOnly shipDefinitions As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer) From {
        {"Carrier", 5},
        {"Battleship", 4},
        {"Cruiser", 3},
        {"Submarine", 3},
        {"Destroyer", 2}
    }

    Private Class GridCell
        Public Property Button As Button
        Public Property HasShip As Boolean = False
        Public Property IsHit As Boolean = False
        Public Property ShipName As String = ""
    End Class

    Private Class Ship
        Public Property Name As String
        Public Property Size As Integer
        Public Property Positions As List(Of Point)
        Public Property Hits As Integer = 0
        Public Property IsSunk As Boolean = False

        Public Sub New(name As String, size As Integer)
            Me.Name = name
            Me.Size = size
            Positions = New List(Of Point)()
        End Sub
    End Class

    Public Sub New()
        InitializeComponent2()
        InitializeGame()
    End Sub

    Private Sub InitializeComponent2()
        Me.Text = "Naval Battle Game"
        Me.Size = New Size(900, 700)
        Me.StartPosition = FormStartPosition.CenterScreen

        ' Create title label
        Dim titleLabel As New Label With {
            .Text = "NAVAL BATTLE",
            .Font = New Font("Arial", 24, FontStyle.Bold),
            .ForeColor = Color.DarkBlue,
            .Size = New Size(300, 40),
            .Location = New Point(300, 20),
            .TextAlign = ContentAlignment.MiddleCenter
        }
        Me.Controls.Add(titleLabel)

        ' Create player grid label
        Dim playerLabel As New Label With {
            .Text = "YOUR FLEET",
            .Font = New Font("Arial", 12, FontStyle.Bold),
            .ForeColor = Color.DarkGreen,
            .Size = New Size(200, 30),
            .Location = New Point(50, 80),
            .TextAlign = ContentAlignment.MiddleLeft
        }
        Me.Controls.Add(playerLabel)

        ' Create enemy grid label
        Dim enemyLabel As New Label With {
            .Text = "ENEMY WATERS",
            .Font = New Font("Arial", 12, FontStyle.Bold),
            .ForeColor = Color.DarkRed,
            .Size = New Size(200, 30),
            .Location = New Point(450, 80),
            .TextAlign = ContentAlignment.MiddleLeft
        }
        Me.Controls.Add(enemyLabel)

        ' Create player grid panel
        playerGridPanel = New Panel With {
            .Size = New Size(GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE),
            .Location = New Point(50, 120),
            .BorderStyle = BorderStyle.FixedSingle
        }
        Me.Controls.Add(playerGridPanel)

        ' Create enemy grid panel
        enemyGridPanel = New Panel With {
            .Size = New Size(GRID_SIZE * CELL_SIZE, GRID_SIZE * CELL_SIZE),
            .Location = New Point(450, 120),
            .BorderStyle = BorderStyle.FixedSingle
        }
        Me.Controls.Add(enemyGridPanel)

        ' Create status label
        statusLabel = New Label With {
            .Text = "Place your ships! Click on your grid to position ships.",
            .Font = New Font("Arial", 10, FontStyle.Regular),
            .Size = New Size(800, 30),
            .Location = New Point(50, 600),
            .TextAlign = ContentAlignment.MiddleLeft
        }
        Me.Controls.Add(statusLabel)

        ' Create ship status label
        shipStatusLabel = New Label With {
            .Text = "Ships to place: Carrier (5), Battleship (4), Cruiser (3), Submarine (3), Destroyer (2)",
            .Font = New Font("Arial", 9, FontStyle.Italic),
            .Size = New Size(800, 30),
            .Location = New Point(50, 630),
            .ForeColor = Color.DarkSlateGray
        }
        Me.Controls.Add(shipStatusLabel)

        ' Create restart button
        restartButton = New Button With {
            .Text = "Restart Game",
            .Size = New Size(120, 40),
            .Location = New Point(390, 480),
            .Font = New Font("Arial", 10, FontStyle.Bold),
            .BackColor = Color.LightGray
        }
        AddHandler restartButton.Click, AddressOf RestartGame
        Me.Controls.Add(restartButton)

        ' Create score labels
        Dim playerScoreLabel As New Label With {
            .Text = "Your Hits: 0",
            .Font = New Font("Arial", 10, FontStyle.Bold),
            .Size = New Size(150, 25),
            .Location = New Point(50, 550),
            .ForeColor = Color.DarkGreen
        }
        Me.Controls.Add(playerScoreLabel)

        Dim enemyScoreLabel As New Label With {
            .Text = "Enemy Hits: 0",
            .Font = New Font("Arial", 10, FontStyle.Bold),
            .Size = New Size(150, 25),
            .Location = New Point(450, 550),
            .ForeColor = Color.DarkRed
        }
        Me.Controls.Add(enemyScoreLabel)
    End Sub

    Private Sub InitializeGame()
        ' Initialize grids
        playerGrid = New GridCell(GRID_SIZE - 1, GRID_SIZE - 1) {}
        enemyGrid = New GridCell(GRID_SIZE - 1, GRID_SIZE - 1) {}
        ships = New List(Of Ship)()

        ' Create player grid buttons
        For row As Integer = 0 To GRID_SIZE - 1
            For col As Integer = 0 To GRID_SIZE - 1
                Dim cell As New GridCell()
                Dim btn As New Button With {
                    .Size = New Size(CELL_SIZE, CELL_SIZE),
                    .Location = New Point(col * CELL_SIZE, row * CELL_SIZE),
                    .Tag = New Point(row, col),
                    .BackColor = Color.LightBlue,
                    .FlatStyle = FlatStyle.Flat
                }
                AddHandler btn.Click, AddressOf PlayerGrid_Click
                cell.Button = btn
                playerGrid(row, col) = cell
                playerGridPanel.Controls.Add(btn)
            Next
        Next

        ' Create enemy grid buttons
        For row As Integer = 0 To GRID_SIZE - 1
            For col As Integer = 0 To GRID_SIZE - 1
                Dim cell As New GridCell()
                Dim btn As New Button With {
                    .Size = New Size(CELL_SIZE, CELL_SIZE),
                    .Location = New Point(col * CELL_SIZE, row * CELL_SIZE),
                    .Tag = New Point(row, col),
                    .BackColor = Color.LightGray,
                    .FlatStyle = FlatStyle.Flat
                }
                AddHandler btn.Click, AddressOf EnemyGrid_Click
                cell.Button = btn
                enemyGrid(row, col) = cell
                enemyGridPanel.Controls.Add(btn)
            Next
        Next

        ' Initialize ships
        For Each shipDef In shipDefinitions
            ships.Add(New Ship(shipDef.Key, shipDef.Value))
        Next

        gameStarted = False
        playerTurn = True
        playerHits = 0
        enemyHits = 0

        UpdateShipStatus()
    End Sub

    Private Sub PlayerGrid_Click(sender As Object, e As EventArgs)
        If gameStarted Then Return

        Dim btn As Button = DirectCast(sender, Button)
        Dim location As Point = DirectCast(btn.Tag, Point)
        Dim row As Integer = location.X
        Dim col As Integer = location.Y

        ' Find next ship to place
        Dim shipToPlace As Ship = ships.FirstOrDefault(Function(s) Not s.Positions.Any())
        If shipToPlace Is Nothing Then
            statusLabel.Text = "All ships placed! Click 'Restart Game' to play again or start attacking enemy grid."
            gameStarted = True
            Return
        End If

        ' Try to place ship horizontally
        If CanPlaceShip(row, col, shipToPlace.Size, True) Then
            PlaceShip(row, col, shipToPlace, True)
        ElseIf CanPlaceShip(row, col, shipToPlace.Size, False) Then
            PlaceShip(row, col, shipToPlace, False)
        Else
            statusLabel.Text = $"Cannot place {shipToPlace.Name} here. Try another location."
            Return
        End If

        UpdateShipStatus()

        ' Check if all ships placed
        If ships.All(Function(s) s.Positions.Count > 0) Then
            statusLabel.Text = "All ships placed! Attack enemy grid by clicking on it."
            gameStarted = True
            PlaceEnemyShips()
        End If
    End Sub

    Private Function CanPlaceShip(row As Integer, col As Integer, size As Integer, horizontal As Boolean) As Boolean
        If horizontal Then
            If col + size > GRID_SIZE Then Return False
            For c As Integer = col To col + size - 1
                If playerGrid(row, c).HasShip Then Return False
            Next
        Else
            If row + size > GRID_SIZE Then Return False
            For r As Integer = row To row + size - 1
                If playerGrid(r, col).HasShip Then Return False
            Next
        End If
        Return True
    End Function

    Private Sub PlaceShip(row As Integer, col As Integer, ship As Ship, horizontal As Boolean)
        ship.Positions.Clear()

        If horizontal Then
            For c As Integer = col To col + ship.Size - 1
                playerGrid(row, c).HasShip = True
                playerGrid(row, c).ShipName = ship.Name
                playerGrid(row, c).Button.BackColor = Color.DarkGreen
                ship.Positions.Add(New Point(row, c))
            Next
        Else
            For r As Integer = row To row + ship.Size - 1
                playerGrid(r, col).HasShip = True
                playerGrid(r, col).ShipName = ship.Name
                playerGrid(r, col).Button.BackColor = Color.DarkGreen
                ship.Positions.Add(New Point(r, col))
            Next
        End If
    End Sub

    Private Sub PlaceEnemyShips()
        Dim random As New Random()

        For Each shipDef In shipDefinitions
            Dim placed As Boolean = False
            While Not placed
                Dim row As Integer = random.Next(0, GRID_SIZE)
                Dim col As Integer = random.Next(0, GRID_SIZE)
                Dim horizontal As Boolean = random.Next(0, 2) = 0

                If CanPlaceEnemyShip(row, col, shipDef.Value, horizontal) Then
                    PlaceEnemyShip(row, col, shipDef.Value, horizontal)
                    placed = True
                End If
            End While
        Next
    End Sub

    Private Function CanPlaceEnemyShip(row As Integer, col As Integer, size As Integer, horizontal As Boolean) As Boolean
        If horizontal Then
            If col + size > GRID_SIZE Then Return False
            For c As Integer = col To col + size - 1
                If enemyGrid(row, c).HasShip Then Return False
            Next
        Else
            If row + size > GRID_SIZE Then Return False
            For r As Integer = row To row + size - 1
                If enemyGrid(r, col).HasShip Then Return False
            Next
        End If
        Return True
    End Function

    Private Sub PlaceEnemyShip(row As Integer, col As Integer, size As Integer, horizontal As Boolean)
        If horizontal Then
            For c As Integer = col To col + size - 1
                enemyGrid(row, c).HasShip = True
            Next
        Else
            For r As Integer = row To row + size - 1
                enemyGrid(r, col).HasShip = True
            Next
        End If
    End Sub

    Private Sub EnemyGrid_Click(sender As Object, e As EventArgs)
        If Not gameStarted Or Not playerTurn Then Return

        Dim btn As Button = DirectCast(sender, Button)
        Dim location As Point = DirectCast(btn.Tag, Point)
        Dim row As Integer = location.X
        Dim col As Integer = location.Y

        If enemyGrid(row, col).IsHit Then
            statusLabel.Text = "You already attacked this location!"
            Return
        End If

        enemyGrid(row, col).IsHit = True

        If enemyGrid(row, col).HasShip Then
            btn.BackColor = Color.Red
            btn.Text = "X"
            playerHits += 1
            statusLabel.Text = "Hit! You scored a hit!"

            ' Check if all enemy ships are sunk
            If playerHits = ships.Sum(Function(s) s.Size) Then
                statusLabel.Text = "VICTORY! You sunk all enemy ships!"
                playerTurn = False
                Return
            End If
        Else
            btn.BackColor = Color.DarkGray
            btn.Text = "•"
            statusLabel.Text = "Miss! Enemy's turn..."
            playerTurn = False
            ' Enemy's turn after a delay
            Timer1.Start()
        End If

        UpdateScore()
    End Sub

    Private WithEvents Timer1 As New Timer()

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Timer1.Stop()
        EnemyTurn()
    End Sub

    Private Sub EnemyTurn()
        If Not gameStarted Or playerTurn Then Return

        Dim random As New Random()
        Dim row, col As Integer
        Dim attempts As Integer = 0

        ' Find a cell that hasn't been hit yet
        Do
            row = random.Next(0, GRID_SIZE)
            col = random.Next(0, GRID_SIZE)
            attempts += 1
        Loop While playerGrid(row, col).IsHit And attempts < 100

        playerGrid(row, col).IsHit = True

        If playerGrid(row, col).HasShip Then
            playerGrid(row, col).Button.BackColor = Color.Orange
            playerGrid(row, col).Button.Text = "X"
            enemyHits += 1
            statusLabel.Text = "Enemy hit your ship!"

            ' Check if player lost
            If enemyHits = ships.Sum(Function(s) s.Size) Then
                statusLabel.Text = "DEFEAT! All your ships have been sunk!"
                playerTurn = False
                Return
            End If
        Else
            playerGrid(row, col).Button.BackColor = Color.LightGray
            playerGrid(row, col).Button.Text = "•"
            statusLabel.Text = "Enemy missed! Your turn..."
        End If

        playerTurn = True
        UpdateScore()
    End Sub

    Private Sub UpdateScore()
        ' Update score displays
        For Each ctrl In Me.Controls
            If TypeOf ctrl Is Label Then
                Dim lbl As Label = DirectCast(ctrl, Label)
                If lbl.Text.StartsWith("Your Hits:") Then
                    lbl.Text = $"Your Hits: {playerHits}"
                ElseIf lbl.Text.StartsWith("Enemy Hits:") Then
                    lbl.Text = $"Enemy Hits: {enemyHits}"
                End If
            End If
        Next
    End Sub

    Private Sub UpdateShipStatus()
        Dim placedShips As Integer = ships.Count > 0
        Dim totalShips As Integer = ships.Count

        shipStatusLabel.Text = $"Ships placed: {placedShips}/{totalShips}"

        If placedShips = totalShips Then
            shipStatusLabel.Text &= " - Ready to battle!"
        End If
    End Sub

    Private Sub RestartGame(sender As Object, e As EventArgs)
        ' Clear panels
        playerGridPanel.Controls.Clear()
        enemyGridPanel.Controls.Clear()

        ' Reinitialize game
        InitializeGame()
        statusLabel.Text = "Game restarted! Place your ships on your grid."
    End Sub

    Protected Overrides Sub OnFormClosing(e As FormClosingEventArgs)
        Timer1.Dispose()
        MyBase.OnFormClosing(e)
    End Sub

    <STAThread>
    Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New Form1())
    End Sub

End Class
