Advertisement
B-Matt

Balkan Coders: Iks oks

Nov 14th, 2015
443
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.75 KB | None | 0 0
  1. Dobar dan Vam želi Balkan Coders ekipa. Prije svega se ispričavam što nisam mogao ranije napisati ovaj tutorijal, ali obaveze su me okupirale te sam morao prvo njih riješiti pa se onda tek baviti ovim hobijem. Danas Vam donosimo tutorijal iz programskog jezika C koji je zapravo baza većini programskih jezika kao što su C++, C# i PHP, ali i skripterskog jezika Pawn. U ovome tutorijalu ćemo programirati najpoznatiju igru koju ste sigurno svi igrali, a to je iksoks (XO). Stoga zasučimo rukave i bacimo se na kodiranje.
  2.  
  3. U ovome tutorijalu ću koristiti (programi i biblioteke):
  4. - Visual Studio Community (posve besplatan) - https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx (ukoliko Vi želite nešto jednostavnije preporučavam Dev C++ ili bilo koji drugi IDE),
  5. - Samo dvije standardne biblioteke stdio.h i stdlib.h koje se nalaze unutar svih kompajlera.
  6.  
  7. Također ćemo koristiti sljedeće funkcije:
  8. - DrawGameTable() - Funkcija koju smo sami napisali, a ispisuje polje za igru na konzolu,
  9. - CheckForWin() - Funkcija koju smo sami napisali, a provjerava dali je igrač unio dovoljno znakova na odabrana polja i proglašava pobjednika.
  10.  
  11. Ovdje ćete naučiti:
  12. - Što su to pretprocesorske naredbe,
  13. - Što su to polja (arrays),
  14. - Petlje (do-while, for, while),
  15. - Više o tenarnom operatoru,
  16. - Što je to goto naredba
  17.  
  18. -------------------------------
  19.  
  20. Ovo je zapravo multiplayer igra jer, kao i u stvarnosti, je predviđena za igranje dvoje igrača. Kao i svaki program moramo početi od samoga kostura, a to je uvoz potrebnih biblioteka i pisanja glavne funkcije.
  21.  
  22. -------------------------------
  23. /*
  24.     Ime: Iks Oks (eng. Tic Tac Toe)
  25.     Autor: Matej Arlović (B-Matt)
  26.     Datum: 5.11.2015. | (c) 2015.
  27.  
  28.     Program iks oks igrice u kojoj igraju dva igrača. Nakon što se završi igrica 'd' je za pokretanje nove igre i 'n' za završetak programa. M ♥
  29. */
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33.  
  34. int main()
  35. {
  36.     system("pause");
  37.     return 0;
  38. }
  39. -------------------------------
  40.  
  41. Na prvih sedam linija koda je postavljen standardni komentar za sve programe gdje piše ime programa, autor, datum kodiranja i opis programa odnosno što on radi. Ukoliko želite imati više linija koda koje želite komentirati tada koristite ovaj tip komentara: /**/, a ukoliko želite komentirati samo jednu liniju koda onda koristite //. Kada komentirate određen dio koda on se ne prevodi već ga kompajler (prevoditelj) izbjegava kao miš mačku.
  42. Nakon toga idu pretprocesorske naredbe odnosno naredbe koje se izvode u trenutku kompajliranja (prevođenja programa u strojni jezik) za razliku od ostalih naredbi i funkcija koje se izvode prilikom izvršavanja programa. Također pretprocesorske naredbe se prve prevode pa tek onda ide ostatak koda. Mi koristimo pretprocesorsku naredbu '#include' koja uvozi funkcije iz biblioteka stdio.h i stdlib.h da ih možemo koristiti u svome programu.
  43. Nakon toga svega ide glavna funkcija odnosno int main() koju MORA imati svaki program jer se unutar nje sve izvodi. Kao što vidite ona STALNO vraća nulu (0), a iznad funkcije 'return' smo stavili funkciju 'system();' i njezinu naredbu "pause" da zaustavi program kada se otvori i izvrši sve, te traži "Press any key to continue..." za izlazak iz programa. Ukoliko toga nema onda program izvrši svoj kod i sam se ugasi. Funkcija 'system();' se nalazi u biblioteci stdlib.h i radi toga smo je uvezli na početku programa!
  44.  
  45. HINT: Više o pretprocesorskim naredbama pročitajte ovdje: http://www.tutorialspoint.com/cprogramming/c_preprocessors.htm
  46.  
  47. -------------------------------
  48. // Globalna varijabla
  49. char playingTable[9];
  50.  
  51. /*
  52.     Naziv funkcije: DrawGameTable
  53.     Tip funkcije: void
  54.     Argumenti:
  55.     Opis: Ispisuje tablicu za igru
  56.     Return: 0
  57. */
  58. void DrawGameTable()
  59. {
  60.     printf("%c|%c|%c\n", playingTable[0], playingTable[1], playingTable[2]);
  61.     printf("-+-+-\n");
  62.     printf("%c|%c|%c\n", playingTable[3], playingTable[4], playingTable[5]);
  63.     printf("-+-+-\n");
  64.     printf("%c|%c|%c\n", playingTable[6], playingTable[7], playingTable[8]);
  65. }
  66.  
  67. /*
  68.     Naziv funkcije: CheckForWin
  69.     Tip funkcije: int
  70.     Argumenti:
  71.     Opis: Ispisuje tablicu za igru
  72.     Return: 1 ako je pobjeda, inače 0
  73. */
  74. int CheckForWin(int player) {
  75.     char playerSign = (player == 1 ? ('X') : ('O'));
  76.  
  77.     if (playingTable[0] == playerSign && playingTable[1] == playerSign && playingTable[2] == playerSign) return 1; // 123
  78.     else if (playingTable[3] == playerSign && playingTable[4] == playerSign && playingTable[5] == playerSign) return 1; // 456
  79.     else if (playingTable[6] == playerSign && playingTable[7] == playerSign && playingTable[8] == playerSign) return 1; // 789
  80.     else if (playingTable[0] == playerSign && playingTable[3] == playerSign && playingTable[6] == playerSign) return 1; // 147
  81.     else if (playingTable[1] == playerSign && playingTable[4] == playerSign && playingTable[7] == playerSign) return 1; // 258
  82.     else if (playingTable[2] == playerSign && playingTable[5] == playerSign && playingTable[8] == playerSign) return 1; // 369
  83.     else if (playingTable[0] == playerSign && playingTable[4] == playerSign && playingTable[8] == playerSign) return 1; // 159
  84.     else if (playingTable[2] == playerSign && playingTable[4] == playerSign && playingTable[6] == playerSign) return 1; // 357
  85.     return 0;
  86. }
  87. -------------------------------
  88.  
  89. Iznad glavne funkcije smo deklarirali glavno polje (array) 'playingTable[9]' koje je tipa znaka (char) i ima 10 polja. Deklariranje polja se vrši tako da unesete količinu polja unosi unutar uglatih zagrada tj. []. Pa zašto onda ovo polje ima 10 polja, a unutra piše 9? Pa količina polja se unosi uvijek po "formuli" n-1 jer se polja numeriraju od nule do n-tog zato glavno polje ima 10 polja.
  90. Nakon toga smo deklarirali i definirali dvije funkcije. Funkcije se UVIJEK deklariraju iznad glavne funkcije. Pod deklariranjem mislim na "void DrawGameTable();", a onda ispod glavne funkcije definiramo funkciju odnosno pišemo ovo što piše iznad. Da bismo to izbjegli zato sam deklarirao i definirao funkcije iznad glavne funkcije. Tip podatka int ste već upoznali i on označava cijelobrojni podatak, ali ovdje imamo i tip podatka void. On označava prazan tip podatka no u ovome slučaju označava funkciju koja ne vraća ništa tj. nema ključnu riječ 'return' unutar sebe.
  91.  
  92. -------------------------------
  93. int main()
  94. {
  95.     GAME_START:
  96.     // Lokalne varijable
  97.     bool gameOn = true;
  98.     int playerTurn = 1,
  99.         playerInput;
  100. -------------------------------
  101.  
  102. Ovaj kod ulazi unutar 'int main()' i to pri vrhu. Ovdje smo stavili jump oznaku koju ćemo kasnije koristiti za početak nove igre, te smo deklarirali tri lokalne varijable. Prva varijabla 'gameOn' je bool tipa što označava da ima vrijednost true (istina ili 1) ili false (laž ili 0) koja je u stanju istine dokle god igra traje zbog do-while petlje. Druge dvije varijable su cijelobrojnoga tipa: 'playerTurn' označava koji je igrač na redu (1 ako je prvi ili 2 ako je drugi igrač na redu), 'playerInput' označava broj polja koje je igrač odabrao.
  103.  
  104. -------------------------------
  105. do {
  106.     system("CLS");
  107. UNOS:
  108.     DrawGameTable();
  109.     printf("Na redu je igrac %d. Unesite svoje polje (1-9): ", playerTurn);
  110.     scanf_s("%d", &playerInput);
  111. -------------------------------
  112.  
  113. Ovdje smo započeli našu do-while petlju u kojoj će se odvijati igra i u kojoj ide veći dio našeg koda. Do-while petlja započinje s ključnom riječi 'do' pa tek na kraju koda imamo 'while()' s uvjetom. Odmah na početku petlje imamo naredbu 'system("CLS")' koju smo uvezli iz biblioteke 'stdlib.h', a koja briše sav tekst ispisan u konzoli (CLS označava "CLear Screen"). Nakon te funkcije imamo jump oznaku 'UNOS:' koja nam treba prilikom provjere dali je igrač unio dobar broj polja ili dali je uneseno polje već ispunjeno. Nakon toga koristimo našu funkciju 'DrawGameTable()' koja crta polja za igru.
  114. Nakon ispisivanja polja red je da igrač unese svoj unos. Funkcijom 'printf();' ispisujemo poruku kojom dajemo do znanja koji je igrač na redu i koje polje da unese. Više o funkciji printf pročitajte ovdje: http://www.tutorialspoint.com/c_standard_library/c_function_printf.htm
  115. Funkcija za unos podatka u varijablu je scanf no Microsoftov kompajler forsira sigurnu verziju te funkcije i MORATE staviti 'scanf_s' inače će vam izbacivati pogrešku. Unutra morate unijeti format podatka s operatorom '%' i oznakom za tip podatka (više pogledajte link iznad o printf funkciji jer su isti formati) u ovome slučaju koristimo 'd' što označava decimal ili vam ga dekadski tip podatka (cijeli broj). Nakon zareza označujemo adresu varijable u koju želimo spremiti korisnikov unos. Adresu neke varijable dobijate tako da stavite '&' odnosno referentni operator uz ime varijable od koje želite dobiti adresu. Kod mene adresa varijable 'playerInput' je 4127212 što sigurno neće biti slučaj kod vas jer je adresa memorije različita kod svakog računala.
  116.  
  117. HINT: Ukoliko želite provjeriti adresu varijable 'playerInput' koristite ovaj kod: "printf("%d\n", &playerInput);" i u komentaru javite koji ste broj dobili! :)
  118.  
  119. -------------------------------
  120. if (playerInput < 1 || playerInput > 9) {
  121.     system("CLS");
  122.     printf("GRESKA: Smijete unijeti broj od 1 do 9!\n");
  123.     goto UNOS;
  124. }
  125.  
  126. if (playingTable[playerInput - 1] != 0) {
  127.     system("CLS");
  128.     printf("GRESKA: Polje %d je vec ispunjeno!\n", playerInput);
  129.     goto UNOS;
  130. }
  131. -------------------------------
  132.  
  133. Ove dvije if naredbe su zapravo provjere o kojima sam pričao gore. Prva provjera provjerava dali je korisnik unio brojeve manje od 1 ili veće od 9 (jer imamo 9 polja) te onda ispisujemo poruku da mora unijeti broj u rasponu od 1 do 9. Ukoliko unese dobar broj polja onda prelazimo na novu provjeru, ako ne unese onda vraća program skroz gore do jump oznake "UNOS:" i opet kreće ispočetka s unosom podatka u varijablu 'playerInput'.
  134. Druga provjera provjerava dali je već uneseno polje ispunjeno. Kao uvjet pregledavamo dali je polje s IDom 'unos - 1' ispunjeno ili ne. Polja (arrays) su skup varijabli u jednoj i njihovo brojanje kreće od 0 do unesenog maksimuma. Znači ukoliko želite imati 5 polja onda brojite 0, 1, 2, 3, 4 i kada prebrojite koliko brojeva imate tu dobijete broj 5 što označava vašu željenu veličinu polja.
  135.  
  136. -------------------------------
  137. playingTable[playerInput - 1] = ( playerTurn == 1 ? ('X') : ('O') );
  138. if (CheckForWin(playerTurn)) {
  139.     int winner = playerTurn;
  140.     system("CLS");
  141.  
  142.     CONTINUE_PICK:
  143.     int gamePick;
  144.     printf("Igrac %d je pobjednik!\nUnesite '1' za ponovnu igru ili '2' za izlazak: ", winner);
  145.     scanf_s("%d", &gamePick);
  146.  
  147.     gameOn = false;
  148.     playerTurn = 1;
  149.     playerInput = 0;
  150.  
  151.     switch (gamePick) {
  152.         case 1: {
  153.             // Čistimo varijable
  154.             for (int i = 0; i < 9; i++)
  155.                 playingTable[i] = 0;
  156.             goto GAME_START;
  157.             break;
  158.         }
  159.         case 2: {
  160.             printf("Odabrali ste odlazak iz igre. Dovidjenja!\n");
  161.             break;
  162.         }
  163.         default: {
  164.             system("CLS");
  165.             printf("GRESKA: Niste dobro unijeli odabir, d ili n!\n");
  166.             goto CONTINUE_PICK;
  167.             break;
  168.         }
  169.     }
  170.     break;
  171. }
  172. playerTurn = (playerTurn == 1 ? 2 : 1);
  173. -------------------------------
  174.  
  175. Ukoliko prođemo sve provjere onda nam ostaje samo unos igračeva znaka u polje, ispis cijele tablice i provjere jeli taj igrač unio pobjedonosni znak. Prva linija koda se odnosi na upisivanje znakića u polje. Opet umanjujemo ID od polja za jedno i koristeći se tenarnim operatorom upisujemo znak. Tenarni operator je naime kraćena verzija if izraza za kratke verzije koda. Kada unesete uvjet koji želite provjeriti onda morate staviti znakić '?' koji označava da je lijevo uvjet, a desno ispunjavanje uvjeta.
  176. Ukoliko je 'playerTurn', odnosno red igrača, jednak 1 onda će upisati 'X' u protivnome upisuje 'O' jer je onda sigurno 'playerTurn' jednak 2 odnosno različit od 1. Primjećujete ':'? To označava zapravo razliku između ispunjenja uvjeta, ako nije istinit onda napravi desno od ':' u protivnome napravi ono što je lijevo od ':'.
  177. I sada provjeravamo dali je trenutni igrač pobjednik. Gore smo napisali funkciju koja radi svu provjeru za nas i ukoliko je unio pobjedonosni znakić onda vraća 1 i odmah se ispunjuje uvjet postavljen gore u protivnome je nula i nastavlja se kod ispod uvjeta.
  178. Ako je uvjet točan i imamo pobjednika onda je valjda red da obavijestimo igrača zar ne? Ja sam deklarirao cijelobrojnu varijablu 'winner' jer je bio nekakav bug oko prikaza pobjednika za koji nisam imao vremena da ga riješim pa sam napravio "prečac".
  179. Brišemo polje i ostale poruke sa ekrana, čistimo varijable trenutne igre, te ispisujemo da je trenutni igrač pobjedio i da unese 1 za ponovnu igru ili 2 za prekid igre. U switch-case provjeri provjeravamo unose te završavamo igru ili započinjemo novu po naredbi korisnika ili u protivnome ispisujemo da je unio krivi broj i da mora ponovno unijeti broj (za to služi ključna riječ 'default'). Primjećujete ključnu riječ break nakon svakog case-a? Eh to je da nam uvjet ne ispuni na druge uvjete sve dok ne detektira ključnu riječ break. Znači ukoliko nema break-a onda će se ispuniti svi uvjeti dok program ne nađe tu ključnu naredbu. Također ispod provjera stavljamo ključnu riječ 'break;' koja označava da trebamo prekinuti do-while petlju jer imamo pobjednika, a nismo cijeli program vratili na početak.
  180. Te na kraju ukoliko nemamo pobjednika onda prebacujemo na sljedećeg igrača.
  181.  
  182. HINT: Pokušajte napraviti program koji zahtjeva jednostavan unos cijeloga broja i onda u switch-case provjeri stavite da nema jednoga break-a i vidite što će se dogoditi.  
  183.  
  184. -------------------------------
  185.     } while (gameOn);
  186.     system("pause");
  187.     return 0;
  188. }
  189. -------------------------------
  190.  
  191. I ostao nam je kraj samoga programa. Kao što sam gore rekao kod do-while petlje prvo ide ključna riječ 'do' i cijeli program unutar bloka naredbi i onda pri kraju bloka naredbi ide ključna riječ 'while' sa uvjetom. Zašto smo koristili do-while? Prvo što je moja djevojka to željela (žene su jedna divna bića (lažem)) zbog koje i radim ovaj program, a drugo što do-while petlja se izvodi barem jednom. Znači i da nije uvjet istinit onda će on odraditi sav kod unutar petlje i onda prekinuti. Dok while petlja ne počinje svoje iteracije sve dok uvjet bude istinit. Ovdje smo mi automatski stavili uvjet na istinu pa onda možemo koristiti do-while petlju.
  192. Nakon toga nam ostaje još 'system("pause");' naredba kojom pauziramo program da korisnik mora unijeti neki unos za izlazak iz konzole u protivnome program sve odradi i onda ugasi konzolu na brzinu (gore je objašnjeno detaljno što ta funkcija radi). I na kraju ključna riječ 'return 0;' kojom vraćamo nulu jer glavna funkcija UVIJEK vraća nulu!
  193.  
  194. I to bi bilo to. Znam da ima puno teksta, ali se nadam da ćete ga pročitati i naučiti nešto novo. Ukoliko vam nešto nije jasno slobodno postavite pitanje u inbox stranice ili u komentare. Zapamtite to da samo znatiželjom i pitanjima nešto naučiti!
  195.  
  196. Vaš,
  197. Balkan Coders tim ili vam ga Matej.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement