Gra w zapamiętywanie położenia

Bardzo lubię grać w gry logiczne, szczególnie takie, które rozwijają. Dzisiaj zaprezentuje wam jak stworzyć jedną z takich gier:

Zaczynamy standardowo od położenia i wymienienia wszystkich elementów Formy.

 

Element type Element name Properties
Form Form1 Name: Form1
Size: 1233; 709
Text: Zapamiętywanie położenia
BackColor: Black
StartPosition: CenterScreen
Panel gameControlPanel Name: gameControlPanel
BackColor: 50;50;50
Size: 617;87
Location: 24;13
PictureBox PictureBox6 Parent: gameControlPanel
BackColor: 50;50;50
Size: 189;63
Location: 14;11
Label startLabel Parent: PictureBox6
Name: startLabel
BackColor: 50;50;50
Size: 164;39
Location: 25;23
Text: Start
TextAlign: BottomCenter
ForeColor: White
Font: Arial; 20,25pt; style=Bold
Label  Label8 Parent: gameControlPanel
Name: Label8
BackColor: 50;50;50
Size: 169;56
Location: 197;11
Text: Poziom:
TextAlign: MiddleRight
ForeColor: White
Font: Arial; 18pt; style=Bold
Label  Label7 Parent: gameControlPanel
Name: Label7
BackColor: 50;50;50
Size: 45;29
Location: 388;23
Text: –
TextAlign: BottomCenter
ForeColor: White
Font: Arial; 20,25pt; style=Bold
Label  level Parent: gameControlPanel
Name: level
BackColor: 50;50;50
Size: 92;46
Location: 441;9
Text: 1
TextAlign: BottomCenter
ForeColor: White
Font: Arial; 20,25pt; style=Bold
Label  Label3 Parent: gameControlPanel
Name: Label3
BackColor: 50;50;50
Size: 45;29
Location: 541;23
Text: +
TextAlign: BottomCenter
ForeColor: White
Font: Arial; 20,25pt; style=Bold
Panel mainBoard Name: mainBoard
BackColor: 241;241;241
Enable: False
Location: 495;242
Size: 280;207
Visible: false
Panel  timeControlPanel Name: timeControlPanel
BackColor: 50;50;50
Location: 21;555
Size: 301;94
Anchor: Bottom,Left
PictureBox  PictureBox11 Parent: timeControlPanel
Name: PictureBox11
BackColor: 50;50;50
Location: 11;10
Size: 80;74Image: white-clock-png-3.jpg
Panel  Panel6 Parent: timeControlPanel
Name: Panel6
BackColor: Transparent
Location: 111;15
Size: 165;62
Panel  Panel7 Parent: Panel6
Name: Panel7
BackColor: white
Location: 3;2
Size: 160;57
Panel  Panel2 Parent: Panel7
Name: Panel2
BackColor: Black
Location: 0;0
Size: 160;57
Panel  Panel15 Name: Panel15
BackColor: 50;50;50
Location: 330;555
Size: 319;94
Anchor: Bottom, Left
Label  Label5 Parent: Panel15
Name: Label5
Font: Arial; 15,75pt; style=Bold
ForeColor: White
Location: 10;6
BackColor: 50;50;50
Size: 187;81
Text: Pozostało:
TextAlign: MiddleRight
Label  left Parent: Panel15
Name: left
Font: Microsoft Sans Serif; 21,75pt; style=Bold
ForeColor: Red
Location: 191;6
BackColor: 50;50;50
Size: 121;81
TextAlign: MiddleLeft
Text: 0
Panel  Panel23 Name: Panel23
BackColor: 50;50;50
Location: 657;555
Size: 256;94
Anchor: Bottom, Left
Label  Label4 Parent: Panel23
Name: Label4
Font: Arial; 15,75pt; style=Bold
ForeColor: White
Location: 157;81
BackColor: 50;50;50
Size: 157;81
TextAlign: MiddleRight
Text: Szanse:
Label  lives Parent: Panel23
Name: lives
Font: Microsoft Sans Serif; 21,75pt; style=Bold
ForeColor: 0;192;0
Location: 160;6
BackColor: Transparent
Size: 92;81
TextAlign: MiddleLeft
Text: 0
Panel  Panel14 Name: Panel14
BackColor: 50;50;50
Location: 921;555
Size: 275;94
Anchor: Bottom, Left
Label points Parent: Panel14
Name: points
Font: Microsoft Sans Serif; 21,75pt; style=Bold
ForeColor: Red
Location: 149;6
BackColor: 50;50;50
Size: 121;81
TextAlign: MiddleLeft
Text: 0
Label  Label12 Parent: Panel14
Name: Label12
Font: Arial; 15,75pt; style=Bold
ForeColor: White
Location: 27;6
BackColor: 50;50;50
Size: 121;81
TextAlign: MiddleRight
Text: Punkty:
Timer Timer1 Name: Timer1

Dodajemy elementy do formy:

 

Postarałem się o prosty schemat logiczny, który ukazuje sposób działania gry:

Aplikacja nie jest mocno skomplikowana i będzie działała w następujący sposób:

  1. Klikając przycisk „Start” uruchamiamy Timer i metodę createNewGame(…)  ta metoda ustawia wszystko, wielkość planszy układa obiekty itp.
  2. Gdy czas się skończy, ukrywamy nasze obiekty przy użyciu metody hideSquares(), teraz czas na gracza.
  3. Kiedy wszystkie elementy zostaną odsłonięte (lub gracz popełni błąd), uruchamia się metoda checker, która sprawdza stan gry i decyduje czy uruchomić następną plansze czy może dla naszego gracza to jest już koniec gry.

Nasz projekt składał się będzie z trzech elementów:

Sercem programu, będzie klasa LocationClass.vb, w której umieścimy główną logikę.

Spójrzmy na kod Form1, omówimy sobie jego konstrukcje:

Imports System.Threading

Public Class Form1
    'rdzeń gry
    Dim LocationClass As LocationClass
    'odpowiedzialna za ułożenie elementów
    Dim ElementsLocation As New ElementsLocation

    Public time As Integer = 0

    Private Sub startLabel_Click(sender As Object, e As EventArgs) Handles startLabel.Click
        'rzutowanie elementów gry
        LocationClass = New LocationClass(3, mainBoard, points, left, level.Text, lives)
        'przygotowanie elementów
        points.Text = "0"

        mainBoard.Controls.Clear()
        mainBoard.Enabled = True
        mainBoard.BackColor = Color.FromArgb(240, 240, 240)

        time = 0
        'czas start
        Timer1.Start()
        'ustawiamy lokacje planszy na podstawie levelu gracza
        setMainBoardLocation(level.Text)
        'zaczynamy gre od stworzenia kwadratów
        LocationClass.createNewGame()

        'pasek w zegarze
        Panel2.Location = New Point(0, 0)
    End Sub

    Public Sub setMainBoardLocation(ByVal level As Integer)
        ElementsLocation.setLocation(mainBoard, timeControlPanel, gameControlPanel, level, Me.Height, Me.Width)
    End Sub

#Region "pomocnicze"

    Private Sub Label3_Click(sender As Object, e As EventArgs) Handles Label3.Click
        level.Text += 1
    End Sub

    Private Sub Label7_Click(sender As Object, e As EventArgs) Handles Label7.Click
        If Not level.Text - 1 <= 0 Then
            level.Text -= 1
        End If
    End Sub

    Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
        If Not (LocationClass Is Nothing) Then
            setMainBoardLocation(LocationClass.getLevel)
        End If

    End Sub
#End Region

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Dim _point As New Point
        _point = Panel2.Location
        _point.X -= 2
        Panel2.Location = _point
        If _point.X <= -120 Then
            '
            LocationClass.hideSquares()
            Panel2.Location = New Point(0, 0)
            Timer1.Stop()
        End If
    End Sub

End Class

Najważniejszym elementem tej formy jest oczywiście zdarzenie kliknięcia na przycisk „Start” który odwołuje się do „Handles startLabel.Click”  tam zawarte są odwołania do klasy głównej, w której przygotowywana i obsługiwana jest gra. Dodano tutaj również dodatkową klasę „ElementsLocation” która jest odpowiedzialna za położenie głównej planszy gry na swoim miejscu. Gdy zacząłem tworzyć tę prostą grę bardzo nie podobała mi się sytuacja, w której podczas zmiany rozmiaru okna, główna plansza gry zostawała na swoim miejscu :/ , postanowiłem to troszkę usprawnić, by gra wyglądała troszke ładniej.

Po zastosowaniu metody, nasza plansza płynnie zmienia położenie. Umożliwia to przechwycenie zdarzenia zmiany rozmiaru optymalnie:

    Public Sub setMainBoardLocation(ByVal level As Integer)
        ElementsLocation.setLocation(mainBoard, timeControlPanel, gameControlPanel, level, Me.Height, Me.Width)
    End Sub

#Region "pomocnicze"

(...)

    Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
        If Not (LocationClass Is Nothing) Then
            setMainBoardLocation(LocationClass.getLevel)
        End If
    End Sub
#End Region

„level: potrzebny jest, do określenia jak duża ma być plansza, nie chcemy, aby nasze kwadraty były bardzo duże, gdy plansza jest mała, ale gdy level jest wysoki i kwadratów będzie bardzo dużo, chcielibyśmy wykorzystać cały obszar gry jak najlepiej:

Kod, który to umożliwia:

Public Class ElementsLocation

    Public Sub setLocation(ByVal gameBoard As Panel,
                           ByVal bottomPanel As Panel,
                           ByVal topPanel As Panel,
                           ByVal level As Integer,
                           ByVal formHeight As Integer,
                           ByVal formWidth As Integer)

        Dim height As Integer = formHeight - topPanel.Location.Y - topPanel.Height - (formHeight - bottomPanel.Location.Y)
        Dim width As Integer = formWidth

        If Not (width < 360 + 120 * (level - 1) Or height < 360 + 120 * (level - 1)) Then
            gameBoard.Width = 360 + 120 * (level - 1)
            gameBoard.Height = 360 + 120 * (level - 1)
        Else
            If width > height Then
                gameBoard.Width = height - 20
                gameBoard.Height = height - 20
            Else
                gameBoard.Width = width - 20
                gameBoard.Height = width - 20
            End If
        End If
        gameBoard.Location = New Point((formWidth - gameBoard.Width) / 2,
                                       (bottomPanel.Location.Y - topPanel.Height - gameBoard.Height) / 2 + topPanel.Height + 7)
    End Sub

End Class

Dzięki temu, że nasza plansza utworzona jest z obiektu „TableLayoutPanel” i określoną procentową wielkością, możemy sobie z łatwością manipulować rozmiarem planszy, nie musząc się martwić o wielkości obiektów wewnątrz.

Przejdźmy teraz do naszej metody głównej, rozpoczynającej grę:

 Private Sub startLabel_Click(sender As Object, e As EventArgs) Handles startLabel.Click
        'rzutowanie elementów gry
        LocationClass = New LocationClass(3, mainBoard, points, left, level.Text, lives)
        'przygotowanie elementów
        points.Text = "0"

        mainBoard.Controls.Clear()
        mainBoard.Enabled = True
        mainBoard.BackColor = Color.FromArgb(240, 240, 240)

        time = 0
        'czas start
        Timer1.Start()
        'ustawiamy lokacje planszy na podstawie levelu gracza
        setMainBoardLocation(level.Text)
        'zaczynamy gre od stworzenia kwadratów
        LocationClass.createNewGame()

        'pasek w zegarze
        Panel2.Location = New Point(0, 0)
    End Sub

Mamy tutaj trzy ważne elementy, pierwszy tworzy klasę LocationClass i przekazuje elementy formy, drugi uruchamia timer, trzeci tworzy grę. Powód, dlaczego przekazujemy elementy formy, a nie tworzymy wszystko w jednym miejscu, jest prosty, naszą klasę LocationClass możemy użyć w innej aplikacji lub formie, obiekt będzie niezależny.

Pełen kod klasy LocationClass

Imports System.Threading

Public Class LocationClass
    Dim RandomNum As New Random
    Dim ElementsLocation As New ElementsLocation
    Dim mainBoard As New TableLayoutPanel
    Dim gameBoard As Panel
    Dim pointsLabel As Label
    Dim clickCountsLabel As Label
    Dim livesLabel As Label

    Public lives As Integer
    Dim clickCounts As Integer
    Dim points As Double = 0
    Dim negativePoints As Integer
    Dim level As Integer
    Dim gameCount As Integer = 4
    Dim matrix As New List(Of List(Of Boolean))

    Public ReadOnly Property getLevel As Integer
        Get
            Return level
        End Get
    End Property

    Public Sub New(lives As Integer, gameBoard As Panel, pointsLabel As Label,
                   clickCountsLabel As Label, level As Integer, livesLabel As Label)
        Me.lives = lives
        Me.gameBoard = gameBoard
        Me.pointsLabel = pointsLabel
        Me.clickCountsLabel = clickCountsLabel
        Me.level = level
        Me.livesLabel = livesLabel
    End Sub

    '1. tworzymy kwadraty, inicjujemy gre
    Public Sub createNewGame()

        livesLabel.Text = lives
        negativePoints = 0
        gameBoard.Controls.Clear()
        clickCounts = 0

        gameBoard.Visible = False
        mainBoard.Controls.Clear()
        matrix.Clear()
        'inicjujemy wielkość planszy
        mainBoard.ColumnCount = 3 + level
        mainBoard.RowCount = 3 + level

        mainBoard.Margin = New Padding(3, 0, 0, 0)
        mainBoard.Dock = DockStyle.Fill

        'ponieważ nasza gra bazuje na obiekcie TableLayoutPanel, musimy go sensownie przygotować i podzielić
        For i As Integer = 0 To mainBoard.ColumnCount - 1
            mainBoard.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 50))
        Next
        For i As Integer = 0 To mainBoard.RowCount - 1
            mainBoard.RowStyles.Add(New ColumnStyle(SizeType.Percent, 50))
        Next
        'dodajemy TableLayoutPanel do naszego Panelu gry
        gameBoard.Controls.Add(mainBoard)

        Dim amountOfElements As Integer
        For i As Integer = 0 To mainBoard.RowCount - 1
            'losujemy ile w danym wierszu ma być losowych elementów do zapamiętania od 0 do 3 + lewel
            amountOfElements = RandomNum.Next(0, 3 + level)
            'określamy liste elementów boolen w której zaznaczymy nasze elementy do zapamiętania
            Dim line As New List(Of Boolean)
            For k As Integer = 0 To mainBoard.ColumnCount - 1
                'wszystkie pola chwilowo robimy na false
                line.Add(False)
            Next
            'teraz trik który zaznaczy nam pola, 
            'dla wylosowanych pól, losujemy miejsca
            For l As Integer = 0 To amountOfElements
                line(RandomNum.Next(0, mainBoard.ColumnCount)) = True
            Next
            'dodajemy linie do zestawu
            matrix.Add(line)
            'tworzymy obiekty w TableLayoutPanel, w każdym polu tworzymy
            'mały panel odpowiedniego koloru
            For j As Integer = 0 To mainBoard.ColumnCount - 1
                Dim _PictureBox As New PictureBox
                With _PictureBox
                    If line(j) = True Then
                        .BackColor = Color.Red
                        .Enabled = False
                        'dodajemy im zdarzenie kliknięcia
                        AddHandler _PictureBox.Click, AddressOf PB_red
                    Else
                        .BackColor = Color.Gray
                        .Enabled = False
                        AddHandler _PictureBox.Click, AddressOf PB_grey
                    End If
                    .Dock = DockStyle.Fill
                End With
                mainBoard.Controls.Add(_PictureBox, j, i)
            Next
        Next
        'określamy ile jest czerwonych obiektów na planczy, tych do zapamiętania
        For i As Integer = 0 To mainBoard.RowCount - 1
            For j As Integer = 0 To mainBoard.ColumnCount - 1
                If matrix(i).Item(j) = True Then
                    clickCounts += 1
                End If
            Next
        Next

        clickCountsLabel.Text = clickCounts
        mainBoard.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single
        'odsłaniamy naszą plansze
        gameBoard.Visible = True
    End Sub

    '2. ukryj kwadraty
    Public Sub hideSquares()
        For Each _pb As PictureBox In mainBoard.Controls
            _pb.BackColor = Color.DarkGray
            _pb.Cursor = Cursors.Hand
            _pb.Enabled = True
        Next
    End Sub

    '3. mimo tego, że zmienimy kolory naszych elementów ich adresy pozostaną bez zian
    ''' dlatego gdy klikniemy na szry kwadrat który kiedyś był czerwony jego adres się nie zmieni
    ''' 
    Public Sub PB_red(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'użytkownik trafił na właściwy element
        ''zmniejszamy ilość szukanych elementów
        clickCounts -= 1
        ''blokuj element
        DirectCast(sender, PictureBox).Enabled = False
        clickCountsLabel.Text = clickCounts 'wyświetl pozostałe elementy
        'jeśli zostały jakieś elementy wtedy
        If Not clickCounts < 1 Then
            'ustaw odpowiedni kolor
            DirectCast(sender, PictureBox).BackColor = Color.Red
            'dodaj punkty
            points += level / (clickCounts + 1)
            pointsLabel.Text = Math.Round(points).ToString 'wyświetl punkty
        Else
            'nie ma więcej elementów
            DirectCast(sender, PictureBox).BackColor = Color.Red
            pointsLabel.Text = Math.Round(points).ToString
            'koniec gry, zwiększ poziom i przejdź do następnej gry
            checker(0)
        End If
    End Sub
    ''' 
    Public Sub PB_grey(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'użytkownik trafił na szary element
        ''zmieniamy kolor
        DirectCast(sender, PictureBox).BackColor = Color.Gray
        'dodajemy punkty negatywne, trzy punkty i koniec etapu
        negativePoints += 1
        If negativePoints = 3 Then
            If lives = 1 Then
                'koniec gry
                checker(1)
            Else
                lives -= 1
                checker(2)
            End If
        End If
    End Sub
    ''' 
    'ten element sprawdza czy pzostały jeszcze elementy do odnalezienia
    Private Sub checker(ByVal wybor As Integer)
        If wybor = 0 Then
            'gra udana
            gameBoard.BackColor = Color.LightGreen
            nextGame()
        ElseIf wybor = 1 Then
            gameBoard.BackColor = Color.Red
            gameBoard.Enabled = False
            livesLabel.Text = "0"
        ElseIf wybor = 2 Then
            gameBoard.BackColor = Color.Red
            nextGame()
        End If
    End Sub

    Public Sub nextGame()
        'unieruchamiamy naszą plansze na pół sekundy
        gameBoard.Enabled = False
        Application.DoEvents()
        Thread.Sleep(500)
        Application.DoEvents()
        gameBoard.Visible = False

        livesLabel.Text = lives.ToString

        gameBoard.BackColor = Color.FromArgb(240, 240, 240)
        gameBoard.Enabled = True

        'każda seria składa się z 4 gier
        'poziom zwiększany ejst co cztery gry

        gameCount -= 1

        If Not gameCount = 0 Then
            'uruchom następną gre
            Form1.time = 0
            Form1.Timer1.Start()
            createNewGame()
        Else
            'to już ostatnia gra, zwiększ poziom
            'aby następna plansza była większa
            Form1.time = 0
            Form1.Timer1.Start()
            createNewGame()
            gameCount = 4
            level += 1
        End If

        gameBoard.Visible = True
        Form1.setMainBoardLocation(level)
    End Sub
End Class

Omówimy teraz najważniejsze elementy metody „createNewGame()”.

Element, który ustawia wielkość gry na podstawie ustawionego lewelu:

        mainBoard.ColumnCount = 3 + level
        mainBoard.RowCount = 3 + level

każda gra zaczyna się od trzech kwadratów i zwiększa się w zależności od wartości lewelu.

Ten element przygotowuje naszą plansze, a konkretnie określa, że każdy wiersz i kolumna w naszym TableLayoutPanel będzie miała wielkość procentową:

        For i As Integer = 0 To mainBoard.ColumnCount - 1
            mainBoard.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 50))
        Next
        For i As Integer = 0 To mainBoard.RowCount - 1
            mainBoard.RowStyles.Add(New ColumnStyle(SizeType.Percent, 50))
        Next

Daje nam to pewność, że wszystkie elemnty wiersza będą miały jednakową szerokość i każdy element kolumny będzie miał jednakową wysokość.

Te elementy są częścią przygotowania wizualnego planszy, odpowiedzialne są za przygotowanie widoku. Najważniejszym elementem jednak jest metoda, która będzie nam dodawała te czerwone kwadraciki do gry, ważne jest, aby nie było ich za dużo, ale też, aby nie było ich za mało 🙂 , jak tego dokonamy?

Otóż ilość czerwonych elementów będziemy określać dla każdej linii, dlatego naszą metodę umieścimy w pętli for:

        For i As Integer = 0 To mainBoard.RowCount - 1
            'losujemy ile w danym wierszu ma być losowych elementów do zapamiętania od 0 do 3 + lewel
            amountOfElements = RandomNum.Next(0, 3 + level)
(...)

ten element mówi nam, że „Dla każdego wiersza w TableLayoutPanel wylosuj liczbę z przedziału od 0 do 3+level. Następnie tworzymy sobie listę, którą zapełniamy wartościami false:

            'określamy liste elementów boolen w której zaznaczymy nasze elementy do zapamiętania
            Dim line As New List(Of Boolean)
            For k As Integer = 0 To mainBoard.ColumnCount - 1
                'wszystkie pola chwilowo robimy na false
                line.Add(False)
            Next

To dzięki tej liście będziemy wiedzieli na późniejszym etapie, jaki kwadrat mamy dopasować, szary czy czerwony. Po stworzeniu listy przyszedł czas na rozłożenie naszych elementów:

            'teraz trik który zaznaczy nam pola, 
            'dla wylosowanych pól, losujemy miejsca
            For l As Integer = 0 To amountOfElements
                line(RandomNum.Next(0, mainBoard.ColumnCount)) = True
            Next
            'dodajemy linie do zestawu
            matrix.Add(line)
            'tworzymy obiekty w TableLayoutPanel, w każdym polu tworzymy
            'mały panel odpowiedniego koloru

Niektórzy z was pewnie zauważą, że nie sprawdzamy tutaj, czy element w linii jest już zajęty, jest to zabieg celowy, który sprawia, że nie wszystkie ilości z amountOfElements będą rozłożone a sytuacja, gdy cała linia będzie zapełniona, jest mało prawdopodobna. Gwarantuje nam to, że sytuacja, gdy nasz kwadrat będzie cały szary lub cały czerwony, jest bardzo mało prawdopodobna. Gdy wybraliśmy już, gdzie mają znajdować się czerwone kwadraty, czas je rozłożyć:

            For j As Integer = 0 To mainBoard.ColumnCount - 1
                Dim _PictureBox As New PictureBox
                With _PictureBox
                    If line(j) = True Then
                        .BackColor = Color.Red
                        .Enabled = False
                        'dodajemy im zdarzenie kliknięcia
                        AddHandler _PictureBox.Click, AddressOf PB_red
                    Else
                        .BackColor = Color.Gray
                        .Enabled = False
                        AddHandler _PictureBox.Click, AddressOf PB_grey
                    End If
                    .Dock = DockStyle.Fill
                End With
                mainBoard.Controls.Add(_PictureBox, j, i)
            Next

Dla każdej kolumny określamy na podstawie listy „line” jaki PictureBox z jakim click eventem wstawimy. Kwadrat wstawiamy przy użyciu:

                mainBoard.Controls.Add(_PictureBox, j, i)

Gdzie „j” określa kolumne a „i” określa wiesz. Teraz nasze elementy gry będą dodane:

Omówmy sobie teraz zdarzenie kliknięcia kwadrat, każdy dodany przez nas kwadrat, nie ważne, czerwony czy szary ma dodany adres odnośnika do odpowiedniej metody:

AddHandler _PictureBox.Click, AddressOf PB_grey

Składa się ono ze zdarzenia, które chcemy wykorzystać i metody, którą chcemy do tego zdarzenia nadpisać. W naszym wypadku są to dwa zdarzenia, użytkownik trafił kwadracik lub spudłował.

    '3. mimo tego, że zmienimy kolory naszych elementów ich adresy pozostaną bez zian
    ''' dlatego gdy klikniemy na szry kwadrat który kiedyś był czerwony jego adres się nie zmieni
    ''' 
    Public Sub PB_red(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'użytkownik trafił na właściwy element
        ''zmniejszamy ilość szukanych elementów
        clickCounts -= 1
        ''blokuj element
        DirectCast(sender, PictureBox).Enabled = False
        clickCountsLabel.Text = clickCounts 'wyświetl pozostałe elementy
        'jeśli zostały jakieś elementy wtedy
        If Not clickCounts < 1 Then
            'ustaw odpowiedni kolor
            DirectCast(sender, PictureBox).BackColor = Color.Red
            'dodaj punkty
            points += level / (clickCounts + 1)
            pointsLabel.Text = Math.Round(points).ToString 'wyświetl punkty
        Else
            'nie ma więcej elementów
            DirectCast(sender, PictureBox).BackColor = Color.Red
            pointsLabel.Text = Math.Round(points).ToString
            'koniec gry, zwiększ poziom i przejdź do następnej gry
            checker(0)
        End If
    End Sub
    ''' 
    Public Sub PB_grey(ByVal sender As System.Object, ByVal e As System.EventArgs)
        'użytkownik trafił na szary element
        ''zmieniamy kolor
        DirectCast(sender, PictureBox).BackColor = Color.Gray
        'dodajemy punkty negatywne, trzy punkty i koniec etapu
        negativePoints += 1
        If negativePoints = 3 Then
            If lives = 1 Then
                'koniec gry
                checker(1)
            Else
                lives -= 1
                checker(2)
            End If
        End If
    End Sub

Dużą rolę w tych metodach grają punkty dodatnie i ujemne, jeśli gracz źle trafi trzy kwadraty, gra albo się skończy, albo rozpocznie nowa gra. Grę kończy odpalenie medoty checker(1)

    'ten element sprawdza czy pzostały jeszcze elementy do odnalezienia
    Private Sub checker(ByVal wybor As Integer)
        If wybor = 0 Then
            'gra udana
            gameBoard.BackColor = Color.LightGreen
            nextGame()
        ElseIf wybor = 1 Then
            gameBoard.BackColor = Color.Red
            gameBoard.Enabled = False
            livesLabel.Text = "0"
        ElseIf wybor = 2 Then
            gameBoard.BackColor = Color.Red
            nextGame()
        End If
    End Sub

 

Do omówienia została nam jeszcze jedna metoda, która zwiększa poziom i generuje nową planszę:

 Public Sub nextGame()
        'unieruchamiamy naszą plansze na pół sekundy
        gameBoard.Enabled = False
        Application.DoEvents()
        Thread.Sleep(500)
        Application.DoEvents()
        gameBoard.Visible = False

        livesLabel.Text = lives.ToString

        gameBoard.BackColor = Color.FromArgb(240, 240, 240)
        gameBoard.Enabled = True

        'każda seria składa się z 4 gier
        'poziom zwiększany ejst co cztery gry

        gameCount -= 1

        If Not gameCount = 0 Then
            'uruchom następną gre
            Form1.time = 0
            Form1.Timer1.Start()
            createNewGame()
        Else
            'to już ostatnia gra, zwiększ poziom
            'aby następna plansza była większa
            Form1.time = 0
            Form1.Timer1.Start()
            createNewGame()
            gameCount = 4
            level += 1
        End If

        gameBoard.Visible = True
        Form1.setMainBoardLocation(level)
    End Sub

W tej metodzie nie ma nic wyjątkowego, zwrócić uwagę może tylko warunek, który sprawdza, która to gra w danym etapie i zwiększa go po trzech grach. Jak wcześniej pisałem na każdym etapie, będziemy mieli do rozegrania trzy gry.

To by było na tyle, standardowo repozytorium dostępne na GitHubie.

Projekt dostępny tuaj: https://github.com/VisualMonsters/LocationMemorizing

Permalink do tego artykułu: https://visualmonsters.cba.pl/gra-zapamietywanie-polozenia/

Dodaj komentarz

Twój adres email nie będzie publikowany.