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:

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:

„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:

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ę:

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

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

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

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ą:

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:

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:

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:

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ć:

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

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ł.

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)

 

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

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.