Imports System.Drawing
Imports System.Windows.Forms
Imports System.Media

Public Class Form1
    Inherits Form

    ' Game constants
    Private Const ROWS As Integer = 6
    Private Const COLS As Integer = 7
    Private Const CELL_SIZE As Integer = 80
    Private Const ANIMATION_STEPS As Integer = 20
    Private Const DROP_SPEED As Integer = 10

    ' Colors
    Private ReadOnly PLAYER1_COLOR As Color = Color.FromArgb(220, 0, 0)     ' Bright Red
    Private ReadOnly PLAYER2_COLOR As Color = Color.FromArgb(255, 255, 0)    ' Bright Yellow
    Private ReadOnly BOARD_COLOR As Color = Color.FromArgb(0, 0, 150)      ' Dark Blue
    Private ReadOnly BOARD_BORDER_COLOR As Color = Color.FromArgb(0, 0, 100)
    Private ReadOnly EMPTY_CELL_COLOR As Color = Color.FromArgb(240, 240, 240) ' Light Gray
    Private ReadOnly HIGHLIGHT_COLOR As Color = Color.FromArgb(100, 255, 100)  ' Green highlight

    ' Game state
    Private gameBoard(ROWS - 1, COLS - 1) As Integer
    Private currentPlayer As Integer = 1
    Private gameOver As Boolean = False
    Private player1Wins As Integer = 0
    Private player2Wins As Integer = 0
    Private movesCount As Integer = 0
    Private lastMoveRow As Integer = -1
    Private lastMoveCol As Integer = -1

    ' Animation
    Private animatingDisc As Boolean = False
    Private animationRow As Integer = 0
    Private animationCol As Integer = 0
    Private animationStep As Integer = 0
    Private animationPlayer As Integer = 0
    Private animationTimer As New Timer()

    ' Sound
    Private dropSound As SoundPlayer
    Private winSound As SoundPlayer
    Private drawSound As SoundPlayer

    ' Dynamic controls
    Private boardPanel As Panel
    Private columnButtons(COLS - 1) As Button
    Private statusLabel As Label
    Private restartButton As Button
    Private newGameButton As Button
    Private scoreLabel As Label
    Private movesLabel As Label
    Private player1Label As Label
    Private player2Label As Label

    Public Sub New()
        ' Form setup
        Me.Text = "Four in a Row - Enhanced"
        Me.Size = New Size(750, 800)
        Me.StartPosition = FormStartPosition.CenterScreen
        Me.BackColor = Color.FromArgb(240, 240, 245)
        Me.DoubleBuffered = True

        ' Load sounds (using system sounds as fallback)
        Try
            ''dropSound = New SoundPlayer(My.Resources.drop)
        Catch
            dropSound = Nothing
        End Try

        Try
            ''winSound = New SoundPlayer(My.Resources.win)
        Catch
            winSound = Nothing
        End Try

        Try
            ''drawSound = New SoundPlayer(My.Resources.draw)
        Catch
            drawSound = Nothing
        End Try

        ' Setup animation timer
        animationTimer.Interval = 10
        AddHandler animationTimer.Tick, AddressOf AnimationTimer_Tick

        InitializeGame()
        CreateControls()
        ResetGame()
    End Sub

    Private Sub InitializeGame()
        For row As Integer = 0 To ROWS - 1
            For col As Integer = 0 To COLS - 1
                gameBoard(row, col) = 0
            Next
        Next
        movesCount = 0
        lastMoveRow = -1
        lastMoveCol = -1
    End Sub

    Private Sub CreateControls()
        ' Create title label
        Dim titleLabel As New Label()
        titleLabel.Text = "FOUR IN A ROW"
        titleLabel.Font = New Font("Arial", 24, FontStyle.Bold)
        titleLabel.ForeColor = Color.DarkBlue
        titleLabel.Size = New Size(400, 40)
        titleLabel.Location = New Point(Me.Width \ 2 - 200, 10)
        titleLabel.TextAlign = ContentAlignment.MiddleCenter
        Me.Controls.Add(titleLabel)

        ' Create player indicators
        player1Label = New Label()
        player1Label.Text = "PLAYER 1"
        player1Label.Font = New Font("Arial", 12, FontStyle.Bold)
        player1Label.ForeColor = PLAYER1_COLOR
        player1Label.Size = New Size(100, 30)
        player1Label.Location = New Point(50, 40)
        Me.Controls.Add(player1Label)

        player2Label = New Label()
        player2Label.Text = "PLAYER 2"
        player2Label.Font = New Font("Arial", 12, FontStyle.Bold)
        player2Label.ForeColor = PLAYER2_COLOR
        player2Label.Size = New Size(100, 30)
        player2Label.Location = New Point(Me.Width - 150, 40)
        Me.Controls.Add(player2Label)

        ' Create board panel with shadow effect
        boardPanel = New Panel()
        boardPanel.Size = New Size(CELL_SIZE * COLS + 10, CELL_SIZE * ROWS + 10)
        boardPanel.Location = New Point(Me.Width \ 2 - boardPanel.Width \ 2, 120)
        boardPanel.BackColor = BOARD_BORDER_COLOR
        AddHandler boardPanel.Paint, AddressOf BoardPanel_Paint
        Me.Controls.Add(boardPanel)

        ' Create column buttons with hover effects
        For col As Integer = 0 To COLS - 1
            columnButtons(col) = New Button()
            With columnButtons(col)
                .Text = "↓"
                .Size = New Size(CELL_SIZE - 10, 40)
                .Location = New Point(boardPanel.Left + col * CELL_SIZE + 5, boardPanel.Top - 50)
                .Tag = col
                .Font = New Font("Arial", 16, FontStyle.Bold)
                .BackColor = Color.White
                .FlatStyle = FlatStyle.Flat
                .FlatAppearance.BorderColor = Color.DarkGray
                .FlatAppearance.BorderSize = 2
                .FlatAppearance.MouseOverBackColor = Color.FromArgb(230, 230, 255)
                .FlatAppearance.MouseDownBackColor = Color.FromArgb(200, 200, 255)
                AddHandler .Click, AddressOf ColumnButton_Click
                AddHandler .MouseEnter, AddressOf ColumnButton_MouseEnter
                AddHandler .MouseLeave, AddressOf ColumnButton_MouseLeave
            End With
            Me.Controls.Add(columnButtons(col))
        Next

        ' Create status label
        statusLabel = New Label()
        statusLabel.Size = New Size(600, 40)
        statusLabel.Location = New Point(Me.Width \ 2 - 300, boardPanel.Bottom + -0)
        statusLabel.Font = New Font("Arial", 14, FontStyle.Bold)
        statusLabel.TextAlign = ContentAlignment.MiddleCenter
        Me.Controls.Add(statusLabel)

        ' Create score label
        scoreLabel = New Label()
        scoreLabel.Size = New Size(300, 30)
        scoreLabel.Location = New Point(Me.Width \ 2 - 150, statusLabel.Bottom + 0)
        scoreLabel.Font = New Font("Arial", 11)
        scoreLabel.TextAlign = ContentAlignment.MiddleCenter
        Me.Controls.Add(scoreLabel)

        ' Create moves label
        movesLabel = New Label()
        movesLabel.Size = New Size(300, 30)
        movesLabel.Location = New Point(Me.Width \ 2 - 150, scoreLabel.Bottom - 10)
        movesLabel.Font = New Font("Arial", 10)
        movesLabel.TextAlign = ContentAlignment.MiddleCenter
        Me.Controls.Add(movesLabel)

        ' Create buttons
        restartButton = New Button()
        restartButton.Text = "Restart Game"
        restartButton.Size = New Size(140, 40)
        restartButton.Location = New Point(Me.Width \ 2 - 150, movesLabel.Bottom + 0)
        restartButton.Font = New Font("Arial", 10, FontStyle.Bold)
        restartButton.BackColor = Color.LightGray
        restartButton.FlatStyle = FlatStyle.Flat
        AddHandler restartButton.Click, AddressOf RestartButton_Click
        Me.Controls.Add(restartButton)

        newGameButton = New Button()
        newGameButton.Text = "New Game"
        newGameButton.Size = New Size(140, 40)
        newGameButton.Location = New Point(Me.Width \ 2 + 10, movesLabel.Bottom + 0)
        newGameButton.Font = New Font("Arial", 10, FontStyle.Bold)
        newGameButton.BackColor = Color.LightGreen
        newGameButton.FlatStyle = FlatStyle.Flat
        AddHandler newGameButton.Click, AddressOf NewGameButton_Click
        Me.Controls.Add(newGameButton)

        UpdateScoreDisplay()
    End Sub

    Private Sub BoardPanel_Paint(sender As Object, e As PaintEventArgs)
        Dim g As Graphics = e.Graphics
        g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

        ' Draw board background with gradient
        Using brush As New Drawing2D.LinearGradientBrush(
            New Point(0, 0),
            New Point(boardPanel.Width, boardPanel.Height),
            BOARD_COLOR,
            Color.FromArgb(0, 0, 180))

            g.FillRectangle(brush, 5, 5, CELL_SIZE * COLS, CELL_SIZE * ROWS)
        End Using

        ' Draw holes for discs
        For row As Integer = 0 To ROWS - 1
            For col As Integer = 0 To COLS - 1
                Dim discColor As Color = EMPTY_CELL_COLOR
                Dim borderColor As Color = Color.Gray

                ' Check if this is the last move
                Dim isLastMove As Boolean = (row = lastMoveRow AndAlso col = lastMoveCol)

                ' Determine disc color
                Select Case gameBoard(row, col)
                    Case 1
                        discColor = PLAYER1_COLOR
                        borderColor = Color.DarkRed
                    Case 2
                        discColor = PLAYER2_COLOR
                        borderColor = Color.DarkGoldenrod
                End Select

                ' Draw disc with shadow and highlight
                Dim rect As New Rectangle(
                    col * CELL_SIZE + 10,
                    row * CELL_SIZE + 10,
                    CELL_SIZE - 20,
                    CELL_SIZE - 20
                )

                ' Draw shadow
                If gameBoard(row, col) <> 0 Then
                    Using shadowBrush As New SolidBrush(Color.FromArgb(50, 0, 0, 0))
                        g.FillEllipse(shadowBrush, rect.X + 3, rect.Y + 3, rect.Width, rect.Height)
                    End Using
                End If

                ' Draw disc
                Using brush As New SolidBrush(discColor)
                    g.FillEllipse(brush, rect)
                End Using

                ' Draw border
                Using pen As New Pen(borderColor, 2)
                    g.DrawEllipse(pen, rect)
                End Using

                ' Highlight last move
                If isLastMove Then
                    Using pen As New Pen(HIGHLIGHT_COLOR, 3)
                        g.DrawEllipse(pen, rect)
                    End Using
                End If

                ' Draw inner highlight for 3D effect
                If gameBoard(row, col) <> 0 Then
                    Dim highlightRect As New Rectangle(
                        rect.X + rect.Width \ 4,
                        rect.Y + rect.Height \ 4,
                        rect.Width \ 2,
                        rect.Height \ 2
                    )
                    Using highlightBrush As New SolidBrush(Color.FromArgb(100, 255, 255, 255))
                        g.FillEllipse(highlightBrush, highlightRect)
                    End Using
                End If
            Next
        Next

        ' Draw animation if active
        If animatingDisc Then
            Dim yPos As Integer = animationRow * CELL_SIZE + 10 + (animationStep * DROP_SPEED)
            Dim discColor As Color = If(animationPlayer = 1, PLAYER1_COLOR, PLAYER2_COLOR)

            Dim rect As New Rectangle(
                animationCol * CELL_SIZE + 10,
                yPos,
                CELL_SIZE - 20,
                CELL_SIZE - 20
            )

            Using brush As New SolidBrush(discColor)
                g.FillEllipse(brush, rect)
            End Using

            Using pen As New Pen(Color.Black, 2)
                g.DrawEllipse(pen, rect)
            End Using
        End If
    End Sub

    Private Sub ColumnButton_MouseEnter(sender As Object, e As EventArgs)
        If gameOver OrElse animatingDisc Then Return

        Dim col As Integer = CInt(CType(sender, Button).Tag)
        Dim button As Button = CType(sender, Button)

        ' Change button color based on current player
        button.BackColor = If(currentPlayer = 1,
                             Color.FromArgb(255, 200, 200),
                             Color.FromArgb(255, 255, 200))
        button.FlatAppearance.BorderColor = If(currentPlayer = 1, PLAYER1_COLOR, PLAYER2_COLOR)
    End Sub

    Private Sub ColumnButton_MouseLeave(sender As Object, e As EventArgs)
        Dim button As Button = CType(sender, Button)
        button.BackColor = Color.White
        button.FlatAppearance.BorderColor = Color.DarkGray
    End Sub

    Private Sub ColumnButton_Click(sender As Object, e As EventArgs)
        If gameOver OrElse animatingDisc Then Return

        Dim col As Integer = CInt(CType(sender, Button).Tag)
        StartDiscDrop(col)
    End Sub

    Private Sub StartDiscDrop(col As Integer)
        ' Find the lowest empty row
        For row As Integer = ROWS - 1 To 0 Step -1
            If gameBoard(row, col) = 0 Then
                ' Start animation
                animatingDisc = True
                animationRow = row
                animationCol = col
                animationPlayer = currentPlayer
                animationStep = 0
                animationTimer.Start()

                ' Disable buttons during animation
                For Each btn As Button In columnButtons
                    btn.Enabled = False
                Next

                ' Play drop sound
                PlaySound(dropSound)
                Return
            End If
        Next

        ' Column is full
        MessageBox.Show("This column is full! Choose another column.",
                       "Invalid Move",
                       MessageBoxButtons.OK,
                       MessageBoxIcon.Warning)
    End Sub

    Private Sub AnimationTimer_Tick(sender As Object, e As EventArgs)
        animationStep += 1

        ' Check if animation is complete
        If animationStep * DROP_SPEED >= animationRow * CELL_SIZE Then
            animationTimer.Stop()
            animatingDisc = False

            ' Place disc on board
            gameBoard(animationRow, animationCol) = animationPlayer
            lastMoveRow = animationRow
            lastMoveCol = animationCol
            movesCount += 1

            ' Re-enable buttons
            For Each btn As Button In columnButtons
                btn.Enabled = True
            Next

            ' Force redraw
            boardPanel.Invalidate()

            ' Check game state
            ProcessMoveResult()
        Else
            ''boardPanel.Invalidate()
        End If
    End Sub

    Private Sub ProcessMoveResult()
        ' Check for win
        If CheckWin(lastMoveRow, lastMoveCol) Then
            gameOver = True
            statusLabel.Text = $"Player {currentPlayer} wins!"
            statusLabel.ForeColor = If(currentPlayer = 1, PLAYER1_COLOR, PLAYER2_COLOR)

            ' Update scores
            If currentPlayer = 1 Then
                player1Wins += 1
            Else
                player2Wins += 1
            End If

            PlaySound(winSound)
            HighlightWinningCells()
        ElseIf IsBoardFull() Then
            ' Check for draw
            gameOver = True
            statusLabel.Text = "It's a draw!"
            statusLabel.ForeColor = Color.DarkGray
            PlaySound(drawSound)
        Else
            ' Switch player
            currentPlayer = If(currentPlayer = 1, 2, 1)
            statusLabel.Text = $"Player {currentPlayer}'s turn"
            statusLabel.ForeColor = If(currentPlayer = 1, PLAYER1_COLOR, PLAYER2_COLOR)
        End If

        UpdateScoreDisplay()

        ' Update player labels to show current player
        If Not gameOver Then
            player1Label.Font = New Font("Arial", 12, If(currentPlayer = 1, FontStyle.Bold, FontStyle.Regular))
            player2Label.Font = New Font("Arial", 12, If(currentPlayer = 2, FontStyle.Bold, FontStyle.Regular))
        End If
    End Sub

    Private Function CheckWin(row As Integer, col As Integer) As Boolean
        Dim player As Integer = gameBoard(row, col)
        If player = 0 Then Return False

        ' Check all four directions
        Return CheckDirection(row, col, 0, 1) OrElse   ' Horizontal
               CheckDirection(row, col, 1, 0) OrElse   ' Vertical
               CheckDirection(row, col, 1, 1) OrElse   ' Diagonal down-right
               CheckDirection(row, col, 1, -1)         ' Diagonal down-left
    End Function

    Private Function CheckDirection(row As Integer, col As Integer, deltaRow As Integer, deltaCol As Integer) As Boolean
        Dim player As Integer = gameBoard(row, col)
        Dim count As Integer = 1

        ' Check in positive direction
        For i As Integer = 1 To 3
            Dim newRow As Integer = row + i * deltaRow
            Dim newCol As Integer = col + i * deltaCol

            If newRow < 0 OrElse newRow >= ROWS OrElse newCol < 0 OrElse newCol >= COLS Then
                Exit For
            End If

            If gameBoard(newRow, newCol) = player Then
                count += 1
            Else
                Exit For
            End If
        Next

        ' Check in negative direction
        For i As Integer = 1 To 3
            Dim newRow As Integer = row - i * deltaRow
            Dim newCol As Integer = col - i * deltaCol

            If newRow < 0 OrElse newRow >= ROWS OrElse newCol < 0 OrElse newCol >= COLS Then
                Exit For
            End If

            If gameBoard(newRow, newCol) = player Then
                count += 1
            Else
                Exit For
            End If
        Next

        Return count >= 4
    End Function

    Private Sub HighlightWinningCells()
        ' This would highlight the winning combination
        ' For simplicity, we're just marking the last move
        boardPanel.Invalidate()
    End Sub

    Private Function IsBoardFull() As Boolean
        For col As Integer = 0 To COLS - 1
            If gameBoard(0, col) = 0 Then Return False
        Next
        Return True
    End Function

    Private Sub PlaySound(soundPlayer As SoundPlayer)
        If soundPlayer IsNot Nothing Then
            Try
                soundPlayer.Play()
            Catch
                ' Ignore sound errors
            End Try
        End If
    End Sub

    Private Sub UpdateScoreDisplay()
        scoreLabel.Text = $"Score: Player 1 - {player1Wins} | Player 2 - {player2Wins}"
        movesLabel.Text = $"Moves: {movesCount}"
    End Sub

    Private Sub ResetGame()
        InitializeGame()
        currentPlayer = 1
        gameOver = False

        statusLabel.Text = "Player 1's turn"
        statusLabel.ForeColor = PLAYER1_COLOR

        player1Label.Font = New Font("Arial", 12, FontStyle.Bold)
        player2Label.Font = New Font("Arial", 12, FontStyle.Regular)

        boardPanel.Invalidate()
        UpdateScoreDisplay()
    End Sub

    Private Sub RestartButton_Click(sender As Object, e As EventArgs)
        ResetGame()
    End Sub

    Private Sub NewGameButton_Click(sender As Object, e As EventArgs)
        ' Reset scores too
        player1Wins = 0
        player2Wins = 0
        ResetGame()
    End Sub

    Protected Overrides Sub OnFormClosing(e As FormClosingEventArgs)
        ' Clean up resources
        If dropSound IsNot Nothing Then dropSound.Dispose()
        If winSound IsNot Nothing Then winSound.Dispose()
        If drawSound IsNot Nothing Then drawSound.Dispose()
        animationTimer.Dispose()
        MyBase.OnFormClosing(e)
    End Sub

    ' Alternative sound implementation using SystemSounds
    Private Sub PlaySystemSound(soundType As SystemSoundType)
        Select Case soundType
            Case SystemSoundType.Drop
                System.Media.SystemSounds.Asterisk.Play()
            Case SystemSoundType.Win
                System.Media.SystemSounds.Exclamation.Play()
            Case SystemSoundType.Draw
                System.Media.SystemSounds.Beep.Play()
        End Select
    End Sub

    Private Enum SystemSoundType
        Drop
        Win
        Draw
    End Enum

End Class
