Imports System.Drawing
Imports System.Windows.Forms

Public Class Form1
    Inherits Form

    Private gridSize As Integer = 6 ' Default 6x6 grid
    Private tiles(,) As Button
    Private tileSize As Integer = 50
    Private padding As Integer = 5
    Private selectedTiles As New List(Of Point)
    Private random As New Random()
    Private score As Integer = 0
    Private lblScore As Label
    Private btnReset As Button
    Private btnNewGame As Button
    Private cmbGridSize As ComboBox

    Public Sub New()
        InitializeForm()
        InitializeControls()
        InitializeGame()
    End Sub

    Private Sub InitializeForm()
        Me.Text = "None Without Game"
        Me.Size = New Size(600, 600)
        Me.StartPosition = FormStartPosition.CenterScreen
        Me.BackColor = Color.LightGray
    End Sub

    Private Sub InitializeControls()
        ' Score label
        lblScore = New Label()
        lblScore.Text = "Score: 0"
        lblScore.Font = New Font("Arial", 12, FontStyle.Bold)
        lblScore.ForeColor = Color.DarkBlue
        lblScore.Location = New Point(20, 20)
        lblScore.AutoSize = True
        Me.Controls.Add(lblScore)

        ' Grid size combo box
        Dim lblGridSize As New Label()
        lblGridSize.Text = "Grid Size:"
        lblGridSize.Location = New Point(20, 50)
        lblGridSize.AutoSize = True
        Me.Controls.Add(lblGridSize)

        cmbGridSize = New ComboBox()
        cmbGridSize.Items.AddRange({"4x4", "5x5", "6x6", "7x7", "8x8"})
        cmbGridSize.SelectedIndex = 2 ' 6x6
        cmbGridSize.Location = New Point(90, 50)
        cmbGridSize.Size = New Size(60, 25)
        AddHandler cmbGridSize.SelectedIndexChanged, AddressOf GridSizeChanged
        Me.Controls.Add(cmbGridSize)

        ' Reset button
        btnReset = New Button()
        btnReset.Text = "Reset Selection"
        btnReset.Location = New Point(170, 50)
        btnReset.Size = New Size(120, 25)
        AddHandler btnReset.Click, AddressOf ResetSelection
        Me.Controls.Add(btnReset)

        ' New Game button
        btnNewGame = New Button()
        btnNewGame.Text = "New Game"
        btnNewGame.Location = New Point(300, 50)
        btnNewGame.Size = New Size(100, 25)
        AddHandler btnNewGame.Click, AddressOf NewGame
        Me.Controls.Add(btnNewGame)
    End Sub

    Private Sub InitializeGame()
        ' Clear existing tiles
        If tiles IsNot Nothing Then
            For Each tile As Button In tiles
                If tile IsNot Nothing Then
                    Me.Controls.Remove(tile)
                    tile.Dispose()
                End If
            Next
        End If

        ' Initialize tile array
        tiles = New Button(gridSize - 1, gridSize - 1) {}

        ' Calculate starting position for grid
        Dim startX As Integer = (Me.ClientSize.Width - (gridSize * (tileSize + padding))) \ 2
        Dim startY As Integer = 120

        ' Create tiles dynamically
        For row As Integer = 0 To gridSize - 1
            For col As Integer = 0 To gridSize - 1
                Dim tile As New Button()
                tile.Size = New Size(tileSize, tileSize)
                tile.Location = New Point(startX + col * (tileSize + padding), startY + row * (tileSize + padding))
                tile.Tag = New Point(row, col)
                tile.BackColor = GetRandomTileColor()
                tile.Font = New Font("Arial", 8, FontStyle.Bold)
                tile.Text = GetRandomSymbol()
                tile.ForeColor = Color.White

                AddHandler tile.Click, AddressOf Tile_Click
                AddHandler tile.MouseEnter, AddressOf Tile_MouseEnter
                AddHandler tile.MouseLeave, AddressOf Tile_MouseLeave

                tiles(row, col) = tile
                Me.Controls.Add(tile)
                tile.BringToFront()
            Next
        Next
    End Sub

    Private Function GetRandomTileColor() As Color
        Dim colors() As Color = {
            Color.DarkRed,
            Color.DarkGreen,
            Color.DarkBlue,
            Color.DarkOrange,
            Color.Purple,
            Color.Teal
        }
        Return colors(random.Next(colors.Length))
    End Function

    Private Function GetRandomSymbol() As String
        Dim symbols() As String = {"★", "●", "◆", "▲", "■", "♥", "♣", "♦"}
        Return symbols(random.Next(symbols.Length))
    End Function

    Private Sub Tile_Click(sender As Object, e As EventArgs)
        Dim tile As Button = DirectCast(sender, Button)
        Dim position As Point = DirectCast(tile.Tag, Point)

        If selectedTiles.Contains(position) Then
            ' Deselect tile
            selectedTiles.Remove(position)
            tile.BackColor = Color.FromArgb(tile.BackColor.R, tile.BackColor.G, tile.BackColor.B)
            tile.FlatStyle = FlatStyle.Standard
        Else
            ' Select tile
            selectedTiles.Add(position)
            tile.BackColor = Color.FromArgb(
                Math.Min(tile.BackColor.R + 50, 255),
                Math.Min(tile.BackColor.G + 50, 255),
                Math.Min(tile.BackColor.B + 50, 255)
            )
            tile.FlatStyle = FlatStyle.Flat
            tile.FlatAppearance.BorderColor = Color.Yellow
            tile.FlatAppearance.BorderSize = 3
        End If

        CheckForCompletion()
    End Sub

    Private Sub Tile_MouseEnter(sender As Object, e As EventArgs)
        Dim tile As Button = DirectCast(sender, Button)
        If Not selectedTiles.Contains(DirectCast(tile.Tag, Point)) Then
            tile.BackColor = Color.FromArgb(
                Math.Min(tile.BackColor.R + 30, 255),
                Math.Min(tile.BackColor.G + 30, 255),
                Math.Min(tile.BackColor.B + 30, 255)
            )
        End If
    End Sub

    Private Sub Tile_MouseLeave(sender As Object, e As EventArgs)
        Dim tile As Button = DirectCast(sender, Button)
        Dim position As Point = DirectCast(tile.Tag, Point)

        If selectedTiles.Contains(position) Then
            tile.BackColor = Color.FromArgb(
                Math.Min(tile.BackColor.R - 50, 255),
                Math.Min(tile.BackColor.G - 50, 255),
                Math.Min(tile.BackColor.B - 50, 255)
            )
        Else
            tile.BackColor = Color.FromArgb(
                Math.Max(tile.BackColor.R - 30, 0),
                Math.Max(tile.BackColor.G - 30, 0),
                Math.Max(tile.BackColor.B - 30, 0)
            )
        End If
    End Sub

    Private Sub CheckForCompletion()
        If selectedTiles.Count < 2 Then Return

        ' Check if selected tiles form a valid group (no isolated tiles)
        If IsValidGroup() Then
            score += selectedTiles.Count * 10
            lblScore.Text = $"Score: {score}"

            Dim pos1 As Integer = selectedTiles.Count

            ' Remove the selected tiles
            For Each pos In selectedTiles
                Dim tile As Button = tiles(pos.X, pos.Y)
                tile.Visible = False
                tile.Enabled = False
            Next

            selectedTiles.Clear()
            MessageBox.Show($"Good job! +{pos1 * 10} points", "Group Completed",
                          MessageBoxButtons.OK, MessageBoxIcon.Information)
        End If
    End Sub

    Private Function IsValidGroup() As Boolean
        ' A group is valid if no tile is isolated from others
        ' Using flood fill algorithm to check connectivity
        Dim visited As New HashSet(Of Point)()
        Dim queue As New Queue(Of Point)()

        ' Start from first selected tile
        queue.Enqueue(selectedTiles(0))
        visited.Add(selectedTiles(0))

        While queue.Count > 0
            Dim current As Point = queue.Dequeue()

            ' Check all 4 directions
            Dim neighbors As New List(Of Point) From {
                New Point(current.X - 1, current.Y), ' Up
                New Point(current.X + 1, current.Y), ' Down
                New Point(current.X, current.Y - 1), ' Left
                New Point(current.X, current.Y + 1)  ' Right
            }

            For Each neighbor In neighbors
                If selectedTiles.Contains(neighbor) AndAlso Not visited.Contains(neighbor) Then
                    visited.Add(neighbor)
                    queue.Enqueue(neighbor)
                End If
            Next
        End While

        ' All selected tiles should be visited if they form a connected group
        Return visited.Count = selectedTiles.Count
    End Function

    Private Sub ResetSelection()
        For Each pos In selectedTiles
            Dim tile As Button = tiles(pos.X, pos.Y)
            tile.BackColor = Color.FromArgb(
                Math.Max(tile.BackColor.R - 50, 0),
                Math.Max(tile.BackColor.G - 50, 0),
                Math.Max(tile.BackColor.B - 50, 0)
            )
            tile.FlatStyle = FlatStyle.Standard
        Next
        selectedTiles.Clear()
    End Sub

    Private Sub NewGame()
        score = 0
        lblScore.Text = "Score: 0"
        selectedTiles.Clear()
        InitializeGame()
    End Sub

    Private Sub GridSizeChanged(sender As Object, e As EventArgs)
        Select Case cmbGridSize.SelectedIndex
            Case 0 : gridSize = 4
            Case 1 : gridSize = 5
            Case 2 : gridSize = 6
            Case 3 : gridSize = 7
            Case 4 : gridSize = 8
        End Select
        NewGame()
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        MyBase.OnPaint(e)

        ' Draw game title
        Using brush As New SolidBrush(Color.DarkBlue)
            Using font As New Font("Arial", 16, FontStyle.Bold)
                e.Graphics.DrawString("NONE WITHOUT", font, brush,
                                    New PointF(Me.ClientSize.Width \ 2 - 80, 10))
            End Using
        End Using

        ' Draw instructions
        Using brush As New SolidBrush(Color.DarkSlateGray)
            Using font As New Font("Arial", 9, FontStyle.Regular)
                e.Graphics.DrawString("Select connected groups of tiles", font, brush,
                                    New PointF(20, 80))
                e.Graphics.DrawString("No tile should be isolated from the group", font, brush,
                                    New PointF(20, 95))
            End Using
        End Using
    End Sub

    Public Shared Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New Form1())
    End Sub
End Class
