Gra w kropki jest kolejną znaną ze szkoły grą, którą sobie stworzymy. W grze chodzi o to, aby okrążyć kropki przeciwnika. Sam grałem w liceum w kropki dość często, głównie na religii :P. Mam duży sentyment do tej gry więc kiedy nauczyłem się programować, bardzo chciałem taką grę zrobić. Po kilku nieudanych próbach trochę się poddałem, ale powróciłem do projektu i dokończyłem go. Forma, którą zademonstruje tutaj w tutorialu, jest dosyć prosta:
Rodzaj elementu | Nazwa elementu | Ustawienia |
---|---|---|
Form | Form1 | Name: Form1 Text: Kropko mania Size: 840; 663 |
Panel | Panel_glowny | Name: Panel_glowny Size: 800; 600 Location: 12;12 BackColor: White Anchor: Top, Bottom, Left, Right |
Istnieje także program do pobrania mojego autorstwa, w którym można pograć ze znajomym poprzez sieć LAN, jak ktoś potrafi przekierować porty to również przez internet, przed monitorem z kolegą lub samemu z komputerem:
Do pobrania tutaj: KropkoMania 1.4
W tym tutorialu gra zacznie się w momencie uruchomienia programu, nie ma co kombinować i budować niepotrzebnych przycisków i elementów upiększających, które tylko przysłonią i zamglą główny silnik gry. Nasza gra będzie wyglądać tak jak na gifie poniżej:
Każdy, kto zrozumie, na czym polega sposób okrążania kropek, będzie umiał dodać sobie dodatkowe elementy. Tworzymy Form_Load:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
Public Class Form1 'wielkość planszy do gry Dim wysokosc As Integer = 15 Dim szerokosc As Integer = 20 Dim listaLokalizacji As New List(Of List(Of Panel)) 'lista wszystkich paneli na planszy Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load For i As Integer = -2 To szerokosc +1 Dim listapaneli As New List(Of Panel) For j As Integer = -2 To wysokosc +1 Dim panelPodstawowy As New Panel With panelPodstawowy .Location = New Point(i * 40 + 30, j * 40 + 30) .Size = New Size(20, 20) .BackColor = Color.Transparent .Name = "panL_" + i.ToString + "^" + j.ToString + "^" .Cursor = Cursors.Hand 'AddHandler .Click, AddressOf pan_Click 'Obrzeże kartki, wyjaśnie na blogu If i = -2 Or i = -1 Or j = -1 Or j = -2 Or i = szerokosc Or j = wysokosc Or i = szerokosc _ + 1 Or j = wysokosc + 1 Then .Enabled = False End If End With Panel_glowny.Controls.Add(panelPodstawowy) ' dodaje element do panelu listapaneli.Add(panelPodstawowy) Next 'zmienna przechowuje wszystkie panele kartki listaLokalizacji.Add(listapaneli) Next 'Generuje kratkę kartki Dim bit As Bitmap = New Bitmap(Panel_glowny.Width, Panel_glowny.Height) Dim g As Graphics = Graphics.FromImage(bit) Dim myPen As Pen = New Pen(Color.FromArgb(191, 218, 229), 1) For i As Integer = 40 To Panel_glowny.Height Step 40 g.DrawLine(myPen, 0, i, Panel_glowny.Width, i) Next For i As Integer = 40 To Panel_glowny.Width Step 40 g.DrawLine(myPen, i, 0, i, Panel_glowny.Height) Next Panel_glowny.BackgroundImage = bit End Sub End Class |
Po uruchomieniu programu naszym oczom powinna pokazać się, gotowa do kropkowania strona, można się pokusić o taką jej zmianę, aby bardziej przypominała stronę z zeszytu. Ważnym elementem, na który powinniśmy zwrócić uwagę, jest wystawanie naszych paneli poza obszar kartki. Ponieważ podczas działania programu elementy będą rozpatrywane w pewien logiczny sposób, proces ten będzie wymagał sprawdzania elementów powyżej, poniżej, z lewej i z prawej strony kropki dodanie dodatkowych paneli, do których użytkownik nie będzie miał dostępu na początku, będzie wygodniejsze niż wprowadzanie ograniczeń. Jeśli pokolorujemy te obszary, będą one wyglądały tak jak na zdjęciu:
Obszary te będą traktowane jako obszary puste, a ich zablokowanie upewni nas, że takie pozostaną. Jeśli czytaliście tutorial o grze w piłkarzyki, dodanie kropek nie powinno dla was stanowić problemu. Odblokowujemy:
1 |
AddHandler .Click, AddressOf pan_Click |
Dodajemy kod:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
'aktualny gracz Dim gracz As Boolean = True 'listy kropek Dim listaKropekGracz1 As New List(Of Panel) Dim listaKropekGracz2 As New List(Of Panel) Dim bit As Bitmap Dim g As Graphics 'kolory Dim zielony As New System.Drawing.SolidBrush(System.Drawing.Color.Green) Dim czerwony As New System.Drawing.SolidBrush(Color.Red) Public Sub pan_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) If gracz Then 'zielony bit = New Bitmap(20, 20) g = Graphics.FromImage(bit) 'dodaje zajęty panel do listy listaKropekGracz1.Add(DirectCast(sender, Panel)) g.FillEllipse(zielony, New Rectangle(5, 5, 10, 10)) DirectCast(sender, Panel).BackgroundImage = bit DirectCast(sender, Panel).Enabled = False '''''''''testOkrazenia() Else ' czerwony bit = New Bitmap(20, 20) g = Graphics.FromImage(bit) 'dodaje zajęty panel do listy listaKropekGracz2.Add(DirectCast(sender, Panel)) g.FillEllipse(czerwony, New Rectangle(5, 5, 10, 10)) DirectCast(sender, Panel).BackgroundImage = bit DirectCast(sender, Panel).Enabled = False '''''''''testOkrazenia() End If End Sub |
Są już kropki. Jeden kolor, bo gracz nie zmienia statusu na false, ale będzie to robił w innej pętli. Ponieważ wymagają tego zasady gry. Kiedy gracz okrąży przeciwnika, może położyć dodatkową kropkę.
Jeśli chodzi o łatwe rzeczy, to właśnie się skończyły. Teraz musicie ogarnąć, co mam na myśli, tłumacząc sposób działania kilku elementów. Najtrudniejszym elementem gry jest stwierdzenie, czy kropki są okrążone. Kiedy kropka jest jedna, to sytuacja jest oczywista. Należy sprawdzić na naszej liście czy ze wszystkich czterech stron nasza kropka jest otoczona przez kropki przeciwnika. Niestety jest to jedna z wielu sytuacji, które musimy rozpatrywać. Będę starał się tłumaczyć co i jak, jeśli ktoś nie zrozumie, to może napisać mi maila lub zostawi komentarz. Odblokowujemy:
1 |
testOkrazenia() |
Kod tego elementu razem z pierwszą funkcją wygląda następująco:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
Private Sub testOkrazenia() Dim listabrzegowa As New List(Of Panel) 'Dodaje elementy sąsiadujące z kropkami do listy If Not listaKropekGracz1.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz1)) End If If Not listaKropekGracz2.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz2)) End If End Sub 'Funkcja zwraca elementy sąsiadujące z kropkami Private Function brzegi(ByRef listagracza As List(Of Panel)) As List(Of Panel) Dim listanabrzezna As New List(Of Panel) 'przechowuje elementy sąsiadujące For k As Integer = 0 To listagracza.Count - 1 Dim pozycjax As Integer = 0 Dim pozycjay As Integer = 0 'pobiera aktualną pozycję panelu For i As Integer = 0 To listaLokalizacji.Count - 1 For j As Integer = 0 To listaLokalizacji(i).Count - 1 If listaLokalizacji(i)(j).Name = listagracza(k).Name Then pozycjax = i pozycjay = j End If Next Next 'sprawdza czy z lewej, prawej, góry i dołu znajdują się jakieś puste elementy If Not listanabrzezna.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) And _ Not listaKropekGracz1.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) And _ Not listaKropekGracz2.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) Then listanabrzezna.Add(listaLokalizacji(pozycjax - 1)(pozycjay)) End If If Not listanabrzezna.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) And _ Not listaKropekGracz1.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) And _ Not listaKropekGracz2.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) Then listanabrzezna.Add(listaLokalizacji(pozycjax + 1)(pozycjay)) End If If Not listanabrzezna.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) And _ Not listaKropekGracz1.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) And _ Not listaKropekGracz2.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) Then listanabrzezna.Add(listaLokalizacji(pozycjax)(pozycjay + 1)) End If If Not listanabrzezna.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) And _ Not listaKropekGracz1.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) And _ Not listaKropekGracz2.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) Then listanabrzezna.Add(listaLokalizacji(pozycjax)(pozycjay - 1)) End If Next Return listanabrzezna End Function |
Metody zawarte w funkcji powyżej zwracają nam listę elementów sąsiadujących z kropkami.
Na zdjęciach widzimy pokolorowane elementy sąsiadujące. Kolejnym etapem jest stworzenie pewnej szczególnej listy elementów. Ja nazywam tę listę „listą wolności”. Każde zderzenie się elementu lub grupy podczas sprawdzania okrążenia z tą listą będzie oznaczało, że kropka/ki nie są okrążone.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
Private Sub testOkrazenia() Dim listabrzegowa As New List(Of Panel) 'Dodaje elementy sąsiadujące z kropkami do listy If Not listaKropekGracz1.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz1)) End If If Not listaKropekGracz2.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz2)) End If Dim listaWolnosci As New List(Of List(Of Panel)) listaWolnosci = freedomPoints(listabrzegowa) End Sub 'Punkty wolności Private Function freedomPoints(ByRef Sasiadujace As List(Of Panel)) As List(Of List(Of Panel)) Dim listapaneli As New List(Of List(Of Panel)) Dim dlugoscListy As Integer = listaLokalizacji(0).Count Dim wielkoscListy As Integer = listaLokalizacji.Count 'dodawanie elementów z dołu For i As Integer = wielkoscListy - 1 To 0 Step -1 Dim lista As New List(Of Panel) For j As Integer = dlugoscListy - 1 To 0 Step -1 If Not Sasiadujace.Contains(listaLokalizacji(i)(j)) Then lista.Add(listaLokalizacji(i)(j)) Else Exit For End If Next listapaneli.Add(lista) Next 'dodawanie elementów z góry For i As Integer = 0 To wielkoscListy - 1 Dim lista As New List(Of Panel) For j As Integer = 0 To dlugoscListy - 1 If Not Sasiadujace.Contains(listaLokalizacji(i)(j)) Then lista.Add(listaLokalizacji(i)(j)) Else Exit For End If Next listapaneli.Add(lista) Next 'dodawanie elementów z prawej strony For i As Integer = dlugoscListy - 1 To 0 Step -1 Dim lista As New List(Of Panel) For j As Integer = wielkoscListy - 1 To 0 Step -1 If Not Sasiadujace.Contains(listaLokalizacji(j)(i)) Then lista.Add(listaLokalizacji(j)(i)) Else Exit For End If Next listapaneli.Add(lista) If i = wielkoscListy Then Exit For End If Next 'dodawanie elementów z lewej strony For i As Integer = 0 To dlugoscListy - 1 Dim lista As New List(Of Panel) For j As Integer = 0 To wielkoscListy - 1 If Not Sasiadujace.Contains(listaLokalizacji(j)(i)) Then lista.Add(listaLokalizacji(j)(i)) Else Exit For End If Next listapaneli.Add(lista) If i = wielkoscListy Then Exit For End If Next Return listapaneli End Function |
Funkcja ta zwraca nam listę która zawiera elementy:
Jak widać na obrazku, do naszej listy niedodawane są elementy graniczące z kropką, ponieważ są one przechowywane w innej liście. Jak funkcja ta działa, gdy mamy więcej elementów? Otóż tak jak na obrazku poniżej:
Fioletowe i niebieskie elementy to efekt funkcji „freedomPoints”, a czerwone to efekt funkcji „brzegi”. Spójrzcie na elementy w środku, okrążone przez zielone kropki. Nie mają żadnego koloru. Są one bardzo ważne, ponieważ będą naszą drogą do wolności lub okrążenia. Zaczniemy teraz bardzo ważny rozdział, w którym pogrupujemy sobie nasze kropki. Ważnym elementem będzie tutaj odgrywał gracz, musimy wiedzieć który gracz właśnie postawił kropkę. Taką wiedzę daje nam zmienna „gracz”. W momencie, gdy stawiana jest kropka zielona, nie rozpatrujemy, tak jak by nam się mogło zdawać kropek zielonych a kropki czerwone. Ponieważ wszystkie kropki gracza czerwonego grupujemy i każdą grupę po kolei rozpatrujemy czy dąży do naszej „ListyWolności”, jeśli nie, oznacza to, że jest okrążona.
Wstępne grupowanie jest dosyć proste. Tworzymy grupy elementów sąsiadujących, dodajemy je do listy, a następnie te listy, które zawierają te same elementy, łączymy ze sobą:
Zobaczmy jak wygląda kod metody:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
Private Sub testOkrazenia() Dim listabrzegowa As New List(Of Panel) 'Dodaje elementy sąsiadujące z kropkami do listy If Not listaKropekGracz1.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz1)) End If If Not listaKropekGracz2.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz2)) End If Dim listaWolnosci As New List(Of List(Of Panel)) listaWolnosci = freedomPoints(listabrzegowa) Dim listagrup As New List(Of List(Of Panel)) If gracz Then 'zielony listagrup = grupuj(listaKropekGracz2) Else 'czerwony listagrup = grupuj(listaKropekGracz1) End If End Sub 'funkcja tworzy wstępne grupy kropek Private Function grupuj(ByRef listagracza As List(Of Panel)) As List(Of List(Of Panel)) Dim grupy As New List(Of List(Of Panel)) 'wylicza wszystkie kropki przeciwnika For k As Integer = 0 To listagracza.Count - 1 Dim kontynuacja As Boolean = True 'blokada, nie dodaje kropek jeśli już się znajdują w jakiejś grupie For i As Integer = 0 To grupy.Count - 1 If grupy(i).Contains(listagracza(k)) Then kontynuacja = False Exit For End If Next If kontynuacja = True Then Dim listaPunktowa As New List(Of Panel) listaPunktowa.Add(listagracza(k)) 'pobiera pozycję kropki Dim pozycjax As Integer = 0 Dim pozycjay As Integer = 0 For i As Integer = 0 To listaLokalizacji.Count - 1 For j As Integer = 0 To listaLokalizacji(i).Count - 1 If listaLokalizacji(i)(j).Name = listagracza(k).Name Then pozycjax = i pozycjay = j End If Next Next 'łączy sąsiedne punkty w grupy If Not listaPunktowa.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) And _ listagracza.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) Then listaPunktowa.Add(listaLokalizacji(pozycjax - 1)(pozycjay)) End If If Not listaPunktowa.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) And _ listagracza.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) Then listaPunktowa.Add(listaLokalizacji(pozycjax + 1)(pozycjay)) End If If Not listaPunktowa.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) And _ listagracza.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) Then listaPunktowa.Add(listaLokalizacji(pozycjax)(pozycjay + 1)) End If If Not listaPunktowa.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) And _ listagracza.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) Then listaPunktowa.Add(listaLokalizacji(pozycjax)(pozycjay - 1)) End If 'dodaje do listy nasze punkty grupy.Add(listaPunktowa) End If Next For i As Integer = 0 To grupy.Count - 1 For j As Integer = 0 To grupy(i).Count - 1 Dim panelzgrupa As Panel = grupy(i)(j) For r As Integer = 0 To grupy.Count - 1 If Not r = i And grupy(r).Contains(panelzgrupa) Then 'łączy listy grupy(i).AddRange(grupy(r)) grupy(r).Clear() End If Next Next Next 'usuwa puste listy For i As Integer = grupy.Count - 1 To 0 Step -1 If grupy(i).Count = 0 Then grupy.RemoveAt(i) End If Next Return grupy End Function |
Najprościej pokazuje to przykład czterech kropek:
W takich listach nie musimy chwilowo przejmować się powtarzającymi się elementami. Taka segregacja, jak dodamy kolory, wygląda to następująco:
Jak widzimy, grupa B nie zalicza chwilowo pustych pól do swojej grupy, dlatego też nie wiemy, czy nasza grupa B jest na pewno okrążona, czy też nie. Ostatni etap ma na celu dodanie pustych lub brzegowych pól do naszych grup i usunięcie z listy tych grup, które łączą się z naszą listą wolności.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
Private Sub testOkrazenia() Dim listabrzegowa As New List(Of Panel) 'Dodaje elementy sąsiadujące z kropkami do listy If Not listaKropekGracz1.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz1)) End If If Not listaKropekGracz2.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz2)) End If Dim listaWolnosci As New List(Of List(Of Panel)) listaWolnosci = freedomPoints(listabrzegowa) Dim listagrup As New List(Of List(Of Panel)) If gracz Then 'zielony listagrup = grupuj(listaKropekGracz2) listagrup = Edycjagrup(listaKropekGracz1, listagrup, listabrzegowa, listaWolnosci) Else 'czerwony listagrup = grupuj(listaKropekGracz1) listagrup = Edycjagrup(listaKropekGracz2, listagrup, listabrzegowa, listaWolnosci) End If End Sub Private Function Edycjagrup( ByRef listaprzeciwnika As List(Of Panel), ByRef grupy As List(Of List(Of Panel))_ , ByRef listaBrzegowa As List(Of Panel), ByRef Listastrefowa As List(Of List(Of Panel))) As List(Of List(Of Panel)) Dim listanabrzezna As New List(Of Panel) 'pętla sprawdza każdy element na piechotę i dodaje elementy do grup Do Dim dzialajpetlo As Boolean = False For k As Integer = grupy.Count - 1 To 0 Step -1 For l As Integer = 0 To grupy(k).Count - 1 Dim pozycjax As Integer = 0 Dim pozycjay As Integer = 0 'pobiera aktualną pozycję naszego panelu For i As Integer = 0 To listaLokalizacji.Count - 1 For j As Integer = 0 To listaLokalizacji(i).Count - 1 If listaLokalizacji(i)(j).Name = grupy(k)(l).Name Then pozycjax = i pozycjay = j End If Next Next Dim kontynuuj As Boolean = True For i As Integer = 0 To Listastrefowa.Count - 1 'Element grupy dotkną elementu listy wolności, co świadczy o tym, że nie jest okrążony If Listastrefowa(i).Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) Or _ Listastrefowa(i).Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) Or _ Listastrefowa(i).Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) Or _ Listastrefowa(i).Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) Then kontynuuj = False 'usuwa listę z grupy grupy.RemoveAt(k) Exit For End If Next If kontynuuj = True Then 'dodaje listy brzegowe If listaBrzegowa.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) And Not _ grupy(k).Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) Then grupy(k).Add(listaLokalizacji(pozycjax - 1)(pozycjay)) dzialajpetlo = True 'dodaje własne elementy i nie dodaje elementów przeciwnika ElseIf Not listaprzeciwnika.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) And _ Not grupy(k).Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) Then grupy(k).Add(listaLokalizacji(pozycjax - 1)(pozycjay)) dzialajpetlo = True End If If listaBrzegowa.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) And Not _ grupy(k).Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) Then grupy(k).Add(listaLokalizacji(pozycjax + 1)(pozycjay)) dzialajpetlo = True ElseIf Not listaprzeciwnika.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) And _ Not grupy(k).Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) Then grupy(k).Add(listaLokalizacji(pozycjax + 1)(pozycjay)) dzialajpetlo = True End If If listaBrzegowa.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) And Not _ grupy(k).Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) Then grupy(k).Add(listaLokalizacji(pozycjax)(pozycjay + 1)) dzialajpetlo = True ElseIf Not listaprzeciwnika.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) And Not _ grupy(k).Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) Then grupy(k).Add(listaLokalizacji(pozycjax)(pozycjay + 1)) dzialajpetlo = True End If If listaBrzegowa.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) And Not _ grupy(k).Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) Then grupy(k).Add(listaLokalizacji(pozycjax)(pozycjay - 1)) dzialajpetlo = True ElseIf Not listaprzeciwnika.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) And Not _ grupy(k).Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) Then grupy(k).Add(listaLokalizacji(pozycjax)(pozycjay - 1)) dzialajpetlo = True End If Else Exit For End If Next Next 'pętla działa dopóki wszystkie elementy nie będą sprawdzone lub nie będzie już elementów w grupie If grupy.Count = 0 Then Exit Do ElseIf dzialajpetlo = False Then Exit Do End If Loop Return grupy End Function |
Ta funkcja pozwoli nam na wyeliminowanie grup otwartych a zachowanie grup zamkniętych, lub opróżnienie grup jeśli wszystkie są otwarte.
Kiedy wiemy która grupa jest okrążona, należy ją okrążyć i wyeliminować z gry, aby przeciwnik nie mógł już ich użyć. Tę ostatnią rzecz możemy bardzo łatwo osiągnąć poprzez dodanie okrążonych elementów do „listaKropekGracz1” lub „listaKropekGracz2” wtedy dla jednego gracza kropki będą wyeliminowane a dla drugiego i tak są bezużyteczne, skoro są już okrążone. Na podstawie tych list możemy również później stwierdzić, który z graczy wygrał, jeśli będziemy mówić o wygranej w kontekście zajętego terenu. Przejdźmy do elementu rysowania linii, widząc obrazek powyżej, łatwo domyślić się jak to zrobimy. Sprawdzimy każdy okrążony element czy jest obok niego kropka przeciwnika i stworzymy sobie listę tych kropek. Następnie z listy takiej usuniemy powtarzające się elementy tak, aby zostały pojedyncze, sprawdzimy jakie elementy z nimi graniczą i stworzymy listę Tupli, która będzie przechowywać współrzędne linii.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
Dim listazlapaneGracz1 As New List(Of Panel) Dim listazlapaneGracz2 As New List(Of Panel) Private Sub testOkrazenia() Dim listabrzegowa As New List(Of Panel) 'Dodaje elementy sąsiadujące z kropkami do listy If Not listaKropekGracz1.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz1)) End If If Not listaKropekGracz2.Count = 0 Then listabrzegowa.AddRange(brzegi(listaKropekGracz2)) End If Dim listaWolnosci As New List(Of List(Of Panel)) listaWolnosci = freedomPoints(listabrzegowa) Dim listagrup As New List(Of List(Of Panel)) If gracz Then 'zielony listagrup = grupuj(listaKropekGracz2) listagrup = Edycjagrup(listaKropekGracz1, listagrup, listabrzegowa, listaWolnosci) 'listuje wszystkie elementy w grupach które pozostały For i As Integer = 0 To listagrup.Count - 1 'rysuje linie i tworzy listę tupli rysujLinie(listagrup(i), listaKropekGracz1, listazlapaneGracz1) For j As Integer = 0 To listagrup(i).Count - 1 'elementy mogą się powtarzać, więc pętla sprawdza czy przypadkiem nie znajduą się już na liście If Not listazlapaneGracz1.Contains(listagrup(i)(j)) Then listazlapaneGracz1.Add(listagrup(i)(j)) 'dodaje element listagrup(i)(j).Enabled = False 'warunek usuwa element z listy przeciwnika aby nie mógł go już używać If Not listaKropekGracz2.IndexOf(listagrup(i)(j)) = -1 Then listaKropekGracz2.RemoveAt(listaKropekGracz2.IndexOf(listagrup(i)(j))) listaKropekGracz1.Add(listagrup(i)(j)) 'dodaje do listy aktualnego gracza End If End If Next Next 'zmienia gracza jeśli nic nie zostało okrążone If Not listagrup.Count > 0 Then gracz = False End If Else 'czerwony listagrup = grupuj(listaKropekGracz1) listagrup = Edycjagrup(listaKropekGracz2, listagrup, listabrzegowa, listaWolnosci) 'listuje wszystkie elementy w grupach które pozostały For i As Integer = 0 To listagrup.Count - 1 'rysuje linie i tworzy listę tupli rysujLinie(listagrup(i), listaKropekGracz2, listazlapaneGracz2) For j As Integer = 0 To listagrup(i).Count - 1 'elementy mogą się powtarzać, więc pętla sprawdza czy przypadkiem nie znajduą się już na liście If Not listazlapaneGracz2.Contains(listagrup(i)(j)) Then listazlapaneGracz2.Add(listagrup(i)(j)) 'dodaje element listagrup(i)(j).Enabled = False 'warunek usuwa element z listy przeciwnika aby nie mógł go już używać If Not listaKropekGracz1.IndexOf(listagrup(i)(j)) = -1 Then listaKropekGracz1.RemoveAt(listaKropekGracz1.IndexOf(listagrup(i)(j))) 'usuwa listaKropekGracz2.Add(listagrup(i)(j)) 'dodaje do listy aktualnego gracza End If End If Next Next 'zmienia gracza jeśli nic nie zostało okrążone If Not listagrup.Count > 0 Then gracz = True End If End If End Sub |
Tak zmodyfikowany test okrążenia sprawdzi, co trzeba, dodaj go do swojego kodu. Teraz dodamy sobie ostatni element „rysujLinie”, która okrąży nasze punkty. wygląda ona tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
Dim listaLiniwszystkich As New List(Of Tuple(Of Panel, Panel)) Private Sub rysujLinie(ByRef pane As List(Of Panel), ByRef listagracza As List(Of Panel), ByRef listazlapanych As List(Of Panel)) Dim d As Graphics d = Panel_glowny.CreateGraphics() Dim listaUporzadkowanychpanelow As New List(Of Panel) 'tworzy listę wszystkich paneli grupy bez powtórzeń For i As Integer = 0 To pane.Count - 1 If Not listaUporzadkowanychpanelow.Contains(pane(i)) Then listaUporzadkowanychpanelow.Add(pane(i)) End If Next Dim listaliniowych As New List(Of Panel) 'lista sąsiadujących paneli For k As Integer = 0 To listaUporzadkowanychpanelow.Count - 1 Dim pozycjax As Integer = 0 Dim pozycjay As Integer = 0 For i As Integer = 0 To listaLokalizacji.Count - 1 For j As Integer = 0 To listaLokalizacji(i).Count - 1 If listaLokalizacji(i)(j).Name = listaUporzadkowanychpanelow(k).Name Then pozycjax = i pozycjay = j End If Next Next If listagracza.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) Then listaliniowych.Add(listaLokalizacji(pozycjax - 1)(pozycjay)) End If If listagracza.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) Then listaliniowych.Add(listaLokalizacji(pozycjax + 1)(pozycjay)) End If If listagracza.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) Then listaliniowych.Add(listaLokalizacji(pozycjax)(pozycjay + 1)) End If If listagracza.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) Then listaliniowych.Add(listaLokalizacji(pozycjax)(pozycjay - 1)) End If Next For k As Integer = 0 To listaliniowych.Count - 1 If Not listazlapanych.Contains(listaliniowych(k)) Then Dim pozycjax As Integer = 0 Dim pozycjay As Integer = 0 For i As Integer = 0 To listaLokalizacji.Count - 1 For j As Integer = 0 To listaLokalizacji(i).Count - 1 If listaLokalizacji(i)(j).Name = listaliniowych(k).Name Then pozycjax = i pozycjay = j End If Next Next If listaliniowych.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) And Not _ listazlapanych.Contains(listaLokalizacji(pozycjax - 1)(pozycjay)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax - 1)(pozycjay))) End If If listaliniowych.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) And Not _ listazlapanych.Contains(listaLokalizacji(pozycjax + 1)(pozycjay)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax + 1)(pozycjay))) End If If listaliniowych.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) And Not _ listazlapanych.Contains(listaLokalizacji(pozycjax)(pozycjay + 1)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax)(pozycjay + 1))) End If If listaliniowych.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) And Not _ listazlapanych.Contains(listaLokalizacji(pozycjax)(pozycjay - 1)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax)(pozycjay - 1))) End If If listaliniowych.Contains(listaLokalizacji(pozycjax - 1)(pozycjay - 1)) And _ Not listazlapanych.Contains(listaLokalizacji(pozycjax - 1)(pozycjay - 1)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax - 1)(pozycjay - 1))) End If If listaliniowych.Contains(listaLokalizacji(pozycjax + 1)(pozycjay + 1)) And _ Not listazlapanych.Contains(listaLokalizacji(pozycjax + 1)(pozycjay + 1)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax + 1)(pozycjay + 1))) End If If listaliniowych.Contains(listaLokalizacji(pozycjax - 1)(pozycjay + 1)) And _ Not listazlapanych.Contains(listaLokalizacji(pozycjax - 1)(pozycjay + 1)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax - 1)(pozycjay + 1))) End If If listaliniowych.Contains(listaLokalizacji(pozycjax + 1)(pozycjay - 1)) And _ Not listazlapanych.Contains(listaLokalizacji(pozycjax + 1)(pozycjay - 1)) Then listaLiniwszystkich.Add(Tuple.Create(listaliniowych(k), listaLokalizacji(pozycjax + 1)(pozycjay - 1))) End If End If Next 'rysujemy kółeczka i linie For i As Integer = 0 To listaLiniwszystkich.Count - 1 listaLiniwszystkich(i).Item1.Visible = False listaLiniwszystkich(i).Item2.Visible = False Application.DoEvents() If gracz Then Dim myPen As Pen = New Pen(zielony, 2) d.DrawLine(myPen, listaLiniwszystkich(i).Item1.Location.X + 10, _ listaLiniwszystkich(i).Item1.Location.Y + 10, listaLiniwszystkich(i).Item2.Location.X + 10, _ listaLiniwszystkich(i).Item2.Location.Y + 10) d.FillEllipse(zielony, New Rectangle(listaLiniwszystkich(i).Item1.Location.X + 5, _ listaLiniwszystkich(i).Item1.Location.Y + 5, 10, 10)) d.FillEllipse(zielony, New Rectangle(listaLiniwszystkich(i).Item2.Location.X + 5, _ listaLiniwszystkich(i).Item2.Location.Y + 5, 10, 10)) Else Dim myPen As Pen = New Pen(czerwony, 2) d.DrawLine(myPen, listaLiniwszystkich(i).Item1.Location.X + 10, _ listaLiniwszystkich(i).Item1.Location.Y + 10, listaLiniwszystkich(i).Item2.Location.X + 10, _ listaLiniwszystkich(i).Item2.Location.Y + 10) d.FillEllipse(czerwony, New Rectangle(listaLiniwszystkich(i).Item1.Location.X + 5, _ listaLiniwszystkich(i).Item1.Location.Y + 5, 10, 10)) d.FillEllipse(czerwony, New Rectangle(listaLiniwszystkich(i).Item2.Location.X + 5, _ listaLiniwszystkich(i).Item2.Location.Y + 5, 10, 10)) End If Next End Sub |
Pętla ta wymaga trochę jeszcze pracy ale jej założenia są chyba jasne.
Gotowy projekt dostępny pod adresem: GraWkropki_visualmonsters.cba.pl
Sam kod programu do pobrania: Kropki visualmonsters.cba.pl