Skocz do zawartości

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

nyac55

Problem z napisaniem prostej gry w C#?

Polecane posty

Witam. Obecnie muszę napisać prostą grę w C#. Jednak nie wiem jak się za to zabrać, bo nigdy czegoś takiego nie robiłem itd. Przykładową grą może być np. kółko-krzyżyk. Proszę o pomoc w tej sprawie, jak miałbym to zrobić?

Link do komentarza
Udostępnij na innych stronach

Ma być oparta o WindowsForms - tak mi się wydaje, bo to programowanie obiektowe. Także myślę, że o WindowsForms.

_+_+_

Zastanawiałem się już nad tym. Myślę, że można stworzyć pictureBox, narysować kontury planszy do gry w kółko i krzyżyk. Kliknięcie w dane pole powoduje naprzemienne wprowadzanie, albo kółka, albo krzyżyka. Pozostaje jeszcze sprawdzanie, odnośnie skreślania 3 takich samych obiektów w linii.

Nie bardzo się orientuję jak powinienem to stworzyć?

Link do komentarza
Udostępnij na innych stronach

Proponowałbym utworzenie osobnej klasy (poza klasą okna), która przechowywałaby aktualny stan gry.

Wewnątrz powinna zawierać np. tablicę int[3][3], reprezentującą planszę. Wartość 0 oznaczałaby puste pole, 1 - kółko, 2 - krzyżyk.

Musi też posiadać metodę, która wstawi jeden z obiektów na planszę i może od razu zwrócić wartość bool, czy ruch był zwycięski (mam nadzieję, że ze sprawdzeniem istnienia takich samych i niezerowych wartości w jednej z 8 linii nie będziesz miał większego problemu).

Dzięki temu, że będzie to osobna klasa, będzie można ją łatwo przetestować, wywołując wspomnianą metodę z kolejnymi pozycjami i sprawdzając zwracany wynik.

PS w konsoli jak najbardziej też da się pisać obiektowo, w końcu C# z góry narzuca ten paradygmat

Link do komentarza
Udostępnij na innych stronach

Odnośnie tych 9 przycisków, czy mogę zrobić tak, że naprzemienne klikanie na odpowiedni button dodaje do nazwy albo O albo X? (Nie bardzo wiem jak mógłbym to zrobić), następnie w tle utworzyć tablicę 2 wymiarową o wymiarach 3x3. Kliknięcie odpowiedniego button'u będzie powodowało dodanie do talbicy, albo O albo X. Następnie jakoś sprawdzać zawartość tablicy np. if'em - jeśli jest zwycięstwo wypisywać do tekstbox'a zwycięstwo, itd. Czy ma to jakiś sens, czy można to zrobić prościej?

Link do komentarza
Udostępnij na innych stronach

Nie bardzo wiem jak mógłbym to zrobić

Użyj zmiennej informującej, którego gracza jest kolej.

Następnie jakoś sprawdzać zawartość tablicy np. if'em

Sprawdzanie ifem jest moim zdaniem niepoważne - będziesz pisał warunki dla 8 możliwych rozwiązań. Użyj pętli. Gdybyś miał planszę 10x10 też byś ifa użył?

Link do komentarza
Udostępnij na innych stronach

Mógłbyś podać mi jakiś przykład jak mogę to zrobić w pętli, bo np. myślę, że powinienem użyć podwójnego fora w forze wewnętrznym sprawdzać if'em, tak? Tylko, że buttonów jest kilka i nie wiem jak obsłużyć je wszystkie na raz, bo mają różne nazwy np. Button1, Button2 itd. oraz if musiałby sprawdzać raz dla X i raz dla O.

Link do komentarza
Udostępnij na innych stronach

Ten kod jest na pewno skompilowany ? Bo jak dla mnie, to kod:


public partial class Form1 : Form
{
Form1 pole = new Form1();
...

nie powinien działać.

Obiekt klasy z logiką (game) powinien się znajdować w Form1, natomiast sama klasa w OSOBNYM PLIKU.

Link do komentarza
Udostępnij na innych stronach

Powyższy kod, akurat się kompiluje - wyrzuca 2 błędy w button'ie 1: na tab i gra - ale to pewnie błędny zapis.

Obecnie mam coś takiego:

https://www.dropbox..../Game v.1.1.rar

Obiekt jest w Form1 i odwołuje się do klasy game. Co powinienem zrobić dalej?

Nie bardzo orientuję się jak mógłbym w for sprawdzać wystąpienia znaków, bez użycia jak najmniejszej ilości if'ów? Czy np. mogę dodawać wartości liczbowe do tablicy w ten sposób:


private void button1_Click(object sender, EventArgs e)
{
if (_game.player == 1)
{
button1.Text = "X";
tab[0, 0] = 1;
//_game.pole(); <- w takim wypadku metoda game musiałby sprawdzać
//wystąpienia znaków i informować o zwycięstwie.
}
else
{
button1.Text = "O";
tab[0, 0] = 2;
//_game.pole();
}
}

Link do komentarza
Udostępnij na innych stronach

Po pierwsze dobrze by było, gdyby każdy button edytował swój własny Text. Metoda pole (o ile dobrze rozumiem, ma ona wykonać ruch) powinna:

- przyjmować jako parametr współrzędne przycisku

- wstawiać wartość player w odpowiednią komórkę tab

- sprawdzić, czy gracz wykonujący ruch nie wygrał

- zmienić wartość player

- zwrócić informację o ewentualnej wygranej

Zauważ, że jedynie gracz, który wykonuje ruch może wygrać, dlatego wystarczy, że sprawdzisz, czy w tab istnieje linia z aktualnymi wartościami player.

Po pierwsze zdefiniowałbym funkcję, która sprawdza, czy na podanej linii rzeczywiście znajdują się tylko wartości player, powinna przyjmować jako parametry dwie współrzędne początkowe i współrzędne określające przesunięcie do następnego punktu (czyli dla pierwszego wiersza miałaby parametry (0, 0, 1, 0), dla trzeciej kolumny (0, 2, 0, 1), a dla jednej z przekątnych (0, 2, 1, -1)). Wewnątrz powinna mieć pętlę przelatującą po trzech elementach i sprawdzającą wartości - jeżeli na trafi na różną od player, zwraca false, za pętlą zwraca true.

Teraz taką funkcję należy wywołać dla trzech wierszy (pętla), trzech kolumn (kolejna pętla) i dwóch przekątnych (albo pętla albo dwa osobne wywołania).

Link do komentarza
Udostępnij na innych stronach

Czy ja naprawdę wyrażam się tak niezrozumiale?

Metoda pole:

- przyjmować jako parametr współrzędne przycisku, np. (int x, int y)

- wstawiać wartość player w odpowiednią komórkę tab

- sprawdzić, czy gracz wykonujący ruch nie wygrał (wywołania metody check)

- zmienić wartość player

- zwrócić informację o ewentualnej wygranej

Metoda check:

- sprawdza, czy na podanej linii rzeczywiście znajdują się tylko wartości player

- jako parametry dwie współrzędne początkowe i współrzędne określające przesunięcie do następnego punktu, np. (int x1, int x2, int move1, int move2)

- wewnątrz powinna mieć pętlę przelatującą po trzech elementach i sprawdzającą wartości - jeżeli na trafi na różną od player, zwraca false, za pętlą zwraca true.

Link do komentarza
Udostępnij na innych stronach

Jeżeli masz czas do końca tygodnia, to jeszcze kupa czasu, a kodu za Ciebie pisać nie będę, bo w końcu masz go napisać, żeby się czegoś nauczyć.

Co do obecnych uwag, to w klasie Form1:

- usuń zmianę wartości w tablicy tab

- wywołanie pole wywal poza if'a

co powinno dać kod w stylu


if (game.player == 1)
button1.Text = "X";
else
button1.Text = "O";
if (game.pole(0, 0))
{
// jakiś kod obsługujący zwycięstwo jednego z graczy
}

W klasie game też musi zajść parę zmian:

- metoda pole powinna zwracać wartość bool

- to przypisywanie wartości do tab w pętli ma jakieś zastosowanie ?

- metoda check może (więc i powinna) być prywatna, podobnie jak tab

- pole player również mogłoby być ukryte (zamiast tego możesz utworzyć dwie metody: getCurrentPlayer() i getLastPlayer()

- przemianowałbym metodę player0 na getPlayerName

- metoda check powinna zwracać bool (bo co byś zrobił ze stringiem ?)

- poza istniejącą metodą check dodałbym drugą, bezargumentową (która byłaby wywoływana w metodzie pole), w stylu:


private bool check()
{
// dla każdego wiersza
if (check(0, nr_wiersza, 1, 0))
return true;
// dla każdej kolumny
if (check(nr_kolumny, 0, 0, 1))
return true;
// jeszcze dwa if'y dla kolumn

return false;
}

Link do komentarza
Udostępnij na innych stronach

Mam wielką prośbę, gdybyś mógł dopisać za mnie resztę programu, gdyż kończy mi się czas i muszę go dosłać do końca tygodnia.

Forum służy do pomocy w rozwiązywaniu problemów, a nie do odwalania roboty za studenta. Jeśli jeszcze raz o coś takiego poprosisz, to zamknę Ci temat.

Link do komentarza
Udostępnij na innych stronach

Poniżej przedstawiam to co udało mi się napisać:

https://www.dropbox.com/s/da8rphcyonmgzdn/Game%20v.1.6.rar

Mam jeszcze kilka pytań:

W zapisach metod, najpierw chyba powininien być wiersz, a nie kolumna? np (int nr_wiersza, int nr_kolumny)?

Metoda getPlayerName ma tylko zwracać nazwę użytkownika do text Boxa?

Nie wiem co powinienem zrobić z polem player, obecnie występuje do niego odwołanie, ale pole jest zakomentowane? Czy powinienem użyć nowych metod getCurrentPlayer i getLast Player?

W metodzie check() (bezargumentowej) ^ wcześniej napisałeś mi jak program ma sprawdzać wiersze i kolumny ja miałem zrobić dla przekątnych, nie wiem czy jest to dobrze, gdyż uważam, że tutaj dla 1 przypadku zmienia się i nr. kolumny i wiersza i przesunięcie jest 1 w lewo 2 w dół? // oraz czy najpierw nie powinny być wiersze, a później kolumny

_+_+_

W metodzie check() (4 argumentowej) -> argumenty move1 -> przesuwa po osi x np. w lewo; natomiast argument move2 -> przesuwa po osi y np. w dół??

Link do komentarza
Udostępnij na innych stronach

W zapisach metod, najpierw chyba powininien być wiersz, a nie kolumna? np (int nr_wiersza, int nr_kolumny)?

Tak właściwie to to i tak nie ma znaczenia, ważne jest tylko to, żebyś odpowiednio do pierwszych argumentów dopasował dwa pozostałe (żeby rzeczywiście sprawdzać istniejące linie).

Metoda getPlayerName ma tylko zwracać nazwę użytkownika do text Boxa?

Powinna zwracać nazwę konkretnego użytkownika (i w klasie Form1 wywoływałbym ją z wartością game.getCurrentPlayer() lub game.getLastPlayer()) i na pewno nie do TextBox'a, tylko jako string, a co dalej z tym zrobisz, to już inna sprawa, ale na pewno metody to nie interesuje.

Nie wiem co powinienem zrobić z polem player, obecnie występuje do niego odwołanie, ale pole jest zakomentowane?

W klasie game zdecydowanie nie powinno być zakomentowane, bo klasa odpowiedzialna za logikę powinna wiedzieć, kto powinien wykonać ruch w danym momencie. Natomiast to samo pole w klasie Form1 wydaje mi się mocno bezsensowne.

Czy powinienem użyć nowych metod getCurrentPlayer i getLast Player?

W klasie Form1 używanie tych metod wydaje mi się jak najbardziej wskazane (pierwsza powinna być używana przed wywołaniem metody pole, druga po, np.:


if (_game.pole(nr_kolumny, nr_wiersza))
{
textBox1.Text = _game.getPlayerName(_game.getLastPlayer()) + " zwyciężył";
}

W metodzie check() (bezargumentowej) ^ wcześniej napisałeś mi jak program ma sprawdzać wiersze i kolumny ja miałem zrobić dla przekątnych, nie wiem czy jest to dobrze, gdyż uważam, że tutaj dla 1 przypadku zmienia się i nr. kolumny i wiersza i przesunięcie jest 1 w lewo 2 w dół?

Po pierwsze zamiast


//dla każdego wiersza
//dla każdej kolumny

powinny się pojawić pętle, które by rzeczywiście sprawdzały wszystkie wiersze/linie.

Po drugie przekątne można sprawdzać bez żadnych pętli, więc zamiast zmiennych można im przekazywać same wartości (czyli jedna z przekątnych może być sprawdzona wartościami (0, 0, 1, 1), bo zaczynasz od narożnika (0, 0) i przesuwasz się po polach po przekątnej (czyli 1 pole w prawo + 1 w dół)).

Co do obecnego kodu:

- mam nadzieję, że kod podobny do tego z button1_Click pojawi się przy pozostałych przyciskach

- po co metoda pole ma nadal jakieś pętle i czemu nie robi tego, co powinna ?

- rozumiesz, co ma robić czteroparametrowa metoda check ?

- czemu w metodach getCurrentPlayer i getLastPlayer pojawia się wywołanie getPlayerName ?

Link do komentarza
Udostępnij na innych stronach



  • Kto przegląda   0 użytkowników

    • Brak zalogowanych użytkowników przeglądających tę stronę.
×
×
  • Utwórz nowe...