Игра „Икс-окс”¶
Игра икс-окс игра се тако што на нацртаној табли са 3 реда и 3 колоне играчи наизменично цртају знакове X и O на слободна поља док неко од њих не скупи три иста знака за редом, као у примеру:
X |
O |
|
X |
X |
O |
O |
X |
Желимо да направимо програм који ће моћи да користе два играча да играју ову игру на једном рачунару!
Нацртану таблу можемо у нашем програму представити матрицом са три реда и три колоне. На пример, таблу из претходног примера бележимо матрицом:
tabla = [["X", "O", " "], ["X", "X", "O"], ["O", " ", "X"]]
За испис матрице користимо функцију коју смо писали у прошлом поглављу:
Размислимо сада шта све треба да ради наш програм:
направи матрицу у којој се чува стање табле;
пита играча који је на потезу за ред и колону поља у које жели да стави свој знак;
уколико је могуће, на унето поље уписује одговарајући знак;
исписује ново стање табле;
испитује да ли је тренутни играч победио;
кораке 2-5 понавља док неко не победи или се не попуне сва пољаако нико није победио, исписује да је игра завршена нерешено.
Слично као за игру погађања речи, прво правимо костур кода. Како има 9 слободних поља, кораци 2-5 понављаће се највише 9 пута па зато можемо да користимо for петљу:
#1 napravi matricu koja čuva stanje prazne table
for i in range(9):
#2 pitaj igraca za red i kolonu
#3 u tabli upisi odgovarajuci znak na tu poziciju
#4 ispisi novo stanje table
#5 ako je igrač pobedio čestitaj mu i prekini igru
#6 ako nije bilo pobednika reci da je nerešeno
Чување табле¶
На почетку игре сва поља табле су празна. Ради лепшег исписа, рећи ћемо да се у празним пољима налази један размак. Матрицу од 3 реда и 3 колоне која има сва поља иста правимо на следећи начин:
tabla = [[" " for i in range(3)] for j in range(3)]
слично као у примеру цртања квадрата испуњеног звездицама из прошлог поглавља.
Уписивање новог потеза¶
Рекли смо да програм треба за ред и колону да пита играча који је на потезу, па се поставља питање како да он зна ко је на потезу? Постоји пуно начина на које се то може осигурати, пробај да смислиш неки од њих.
Један начин је да приметимо да је први на потезу Икс, други Окс, трећи опет Икс и тако редом до 9. осим ако неко заврши раније. Видимо да су сви непарни потези Икс, а сви парни Окс, односно да играча можемо одредити на основу парности бројача for петље.
Ако имамо листу играча, igraci = ['X', 'O'], у \(i\)-том потезу на реду ће бити igrac = igraci[i%2].
Сада можемо направити програм који наизменично пита играче за позицију на коју желе да ставе свој знак и исписује све уписане знакове:
Провера исправности унете позиције¶
Шта се деси када играч жели да стави свој знак на место које је већ заузето или које излази из оквира ове табле? По правилима игре то није дозвољено, али је на нама да одлучимо како ћемо то да спречимо и како ће се програм даље одвијати након што региструје да се то догодило.
Једно решење је да прекинемо даљу игру када један играч унесе неисправан потез:
Могли смо такође изабрати да играчу који је унео неисправан потез дамо још једну шансу, две или три. Уколико бисмо желели да једног играча изнова питамо да унесе нову позицију док он коначно не унесе исправну, потребна би нам била while петља.
While петља
Када желимо да се неки блок кода понавља више пута али не за сваки елемент неке колекције, него докле год је испуњен неки услов, користимо while петљу.
Провера победника¶
Играч је победио ако је сакупио три своја знака у једном реду, колони или дијагонали.
Једноставан начин да напишемо функцију која одређује да ли је играч победио је следећи:
def igrac_je_pobedio(igrac, tabla):
if tabla[0][0] == igrac and tabla[1][1] == igrac and tabla[2][2] == igrac:
return True
if tabla[0][2] == igrac and tabla[1][1] == igrac and tabla[2][0] == igrac:
return True
for i in range(3):
if tabla[i][0] == igrac and tabla[i][1] == igrac and tabla[i][2] == igrac:
return True
if tabla[0][i] == igrac and tabla[1][i] == igrac and tabla[2][i] == igrac:
return True
return False
Размисли како на лепши начин можеш ово да запишеш.
Користећи ову функцију добијамо следећи код:
Крај игре¶
Уколико после 9 потеза и даље нема победника, игра је готова и резултат је нерешен, па крај програма треба да изгледа овако:
if nema_pobednika:
print("Igra je zavšena nerešeno.")
Како да по завршетку рада петље знамо да ли је било победника? Као и за сва остала питања у овој лекцији, одговор је да има пуно различитих решења, сада ћемо показати само једно од њих а ти пробај да смислиш још неко 🙂. То решење је да имамо логичку променљиву nema_pobednika којој је почетна вредност True, јер у том тренутку и даље нисмо наишли на победника, и постављамо је на False када наиђемо на победника:
Овим смо завршили још једну нашу игрицу! 🥳
Промена знакова играча¶
Игру коју смо направили можемо лако изменити да уместо знакова X и O буду неки други знакови, на пример почетна слова имена играча, тако што ћемо променити елементе листе igraci. Уколико играч означава своје поље са више од једног слова приметићеш да табла више не изгледа добро и могуће је да треба да промениш дужину празног поља да би све било лепо поравнато. Слично се деси ако поставимо igraci = ['❌', '⭕'].
У некој од наредних лекција показаћемо како се користећи библиотеку rich могу избећи овакви проблеми и правити игрице које лепше изгледају, а до тада пробај да искористиш овај код како би направио неку сличну, али што занимљивију игрицу. Ово су неки примери измена:
Пробај да измениш ову игрицу тако да пре почетка игре пита играче за њихове иницијале и њих уписује на таблу уместо знакова X и O.
Пробај да измениш ову игрицу тако да играчи играју на три добијене, односно док један играч не победи 3 пута.
Пробај да измениш ову игрицу тако да се игра на табли са 4 реда и 4 колоне, а победник је онај који има 4 иста знака у низу.
Пробај да измениш ову игрицу тако да корисник на почетку уноси димензије табле на којој жели да игра.
Пробај да измениш ову игрицу тако да је могу играти 3 играча на табли унете димензије, победник је онај који први скупи 3 у низу.
Даљим изменама овог кода можеш направити игрицу која одговара правилима које ти измислиш и играти је на рачунару са другарима! 💫