Zavod sv. Stanislava - arnes.sissljskg2s/2015_16/Poklukar_Gregor/osebna_spletna... · Zavod sv....
Transcript of Zavod sv. Stanislava - arnes.sissljskg2s/2015_16/Poklukar_Gregor/osebna_spletna... · Zavod sv....
Zavod sv. Stanislava
Škofijska klasična gimnazija
Python za začetnike
Programiranje preproste igre
Maturitetna seminarska naloga iz Informatike
Kandidat: Gregor Poklukar
Mentorica: Helena Medvešek
Ljubljana Šentvid, januar 2016
Python za začetnike
2
Povzetek
Čeprav »Python za začetnike« morda ni ravno obetaven naslov projektne naloge, me
je kot absolutnega začetnika v programiranju pritegnil. Za cilj sem si zadal napisati
kodo za znano igro Štiri v vrsto in program pretvoriti v izvršljivo datoteko. Potem ko
sem namestil program Python skupaj z zbirko modulov Pygame, ki je namenjena
ustvarjanju videoiger, sem se lotil pisanja programa. Algoritma za t. i. »one player«
nisem vključil, torej sta za igranje igre potrebna dva igralca. Ko uporabnik klikne
izvršljivo datoteko, se mu odpre okno z menujem, kjer lahko klikne »začni« za začetek
igre.
Abstract
Although »Python for beginners« is possibly not a very promising title of a project
work, it has attracted me, perhaps because at programming I am an absolute beginner.
I set my sights on writing code for the famous game Four in a line and then converting
it into an executable file. After I have installed program Python together with Pygame
– this is a set of Python modules designed for writing video games – I started writing
the program. I did not included algorithm for so-called »one player«, so for playing
this game two players are needed. When a user clicks an executable file, a window
with a menu opens, where they can click »začni« for starting the game.
Ključne besede
Python, Pygame, Štiri v vrsto, programiranje, Notepad++, cx_Freeze
Python za začetnike
3
Kazalo
1. UVOD ........................................................................................................................................ 4
2. TEORETIČNI DEL ......................................................................................................................... 6
2.1 DELITEV IN PREVAJANJE PROGRAMSKIH JEZIKOV ..................................................................................... 6
2.2 PYTHON, PYGAME IN IGRA ŠTIRI V VRSTO ............................................................................................. 7
2.3 TEORETIČNA REŠITEV NALOGE ............................................................................................................ 7
3. PRAKTIČNI DEL .......................................................................................................................... 9
3.1 NAMESTITEV PROGRAMA PYTHON IN ZBIRKE MODULOV PYGAME .............................................................. 9
3.2 REŠITEV V PYTHONU ...................................................................................................................... 10
3.3 PRETVORBA PROGRAMA V IZVRŠLJIVO DATOTEKO S KONČNICO .EXE ......................................................... 23
4. SKLEP ....................................................................................................................................... 24
5. VIRI IN LITERATURA ................................................................................................................. 26
6. PRILOGE .................................................................................................................................. 27
Stvarno kazalo
cx_Freeze, 24 deklarativni programski jeziki, 7 Guido van Rossum, 8 modularni ali objektni programski jeziki, 7 nestrukturirani programski jeziki, 7 nizkonivojski programski jeziki, 7 postopkovni programski jeziki, 7, 8 proceduralni programski jeziki, 7 programski jeziki, 3, 7, 27 Pygame, 8 strojni jezik, 7, 8 strukturirani programski jeziki, 7, 8 Štiri v vrsto, 8 ukazno kazalko, 10, 24 visokonivojski programski jeziki, 7 zbirka modulov, 8, 11 zbirni jezik, 7
Python za začetnike
4
1. Uvod
Področje računalništva in z njim povezanega programiranja me že od nekdaj
zanima. S slednjim se nisem še nikoli zares ukvarjal, zato se mi je zdela maturitetna
seminarska naloga odlična priložnost. Ker smo se pri pouku naučili že nekaj osnov
programskega jezika Python, sem si za naslov naloge izbral že predlaganega »Python
za začetnike«. Zanimalo me je pisanje iger, zato sem se, kot že podnaslov
Programiranje preproste igre nakaže, odločil, da bom napisal igro Štiri v vrsto.
Glede projektne naloge sem si zadal dva cilja:
1. da bom v omenjenem programu s pomočjo zbirko modulov Pygame napisal
igro Štiri v vrsto za dva igralca (ne bo možnosti, da bi bil igralčev nasprotnik
računalnik), ter
2. da bom napisani program pretvoril v datoteko s končnico .exe.
Programirati po SSKJ med drugim pomeni »narediti, da naprava dela po
določenem programu«. Bistven pri celotni projektni nalogi je ta postopek, ki sem ga
torej moral določiti. Ko je bilo delovanje programa določeno s programsko kodo, je le-
ta deloval le, če sem ga zagnal s pomočjo programa Python. Če slednjega ne bi imel,
programa računalnik ne bi znal brati. Zato ga bom pretvoril v izvršljivo datoteko s
končnico .exe, ki jo zna brati več operacijskih sistemov, med drugim tudi Microsoft
Windows.
Kot zelenec na področju programiranja sem se seveda najprej moral naučiti
osnovnih terminov, s katerimi sem se kar naprej srečeval in jih uporabljal. Nekaj jih
bom razložil tudi v nadaljevanju. Začeli smo že pri pouku, v šoli, kjer smo spoznali
nekaj osnov programerskega dela. Nadalje pa sem se učil iz raznih spletnih strani, ki
ponujajo izobraževanje na področju Pythona in zbirke modulov Pygame.
Python za začetnike
5
Tabela 1: Strojna oprema, ki sem jo uporabljal pri izdelavi:
Izdaja sistema Windows Windows 7 Ultimate
Procesor Pentium(R) Dual-Core CPU E6500 2,94 GHz
Nameščeni pomnilnik (RAM) 3,00 GB
Vrsta sistema 64-bitni operacijski sistem
Ločljivost zaslona 1920 x 1080 px
Tabela 2: Programska oprema, ki sem jo uporabljal pri izdelavi:
Program, v katerem sem pisal igro Python 3.4.4
Zbirka modulov Pygame-1.9.1
Program za pretvorbo v izvršljivo datoteko cx_Freeze-4.3.4
Urejevalnik programske kode Notepad++ 6.8.8
Spletni brskalnik Google Chrome 49.0.2623.110 m
Urejevalnik besedil Word 2013
Program za urejanje tabel Excel 2013
Program za prenos podatkov na splet FileZilla 3.14.1
Python za začetnike
6
2. Teoretični del
2.1 Delitev in prevajanje programskih jezikov
Naloga programskih jezikov je, da omogočijo opis problema in opis postopka
za njegovo rešitev. Navadno jih delimo na nižje (ali nizkonivojske) in višje (ali
visokonivojske) programske jezike.
V 50. letih prejšnjega stoletja se je pojavil strojni jezik, ki je tudi dandanes edini
jezik, razumljiv računalniku. Skupaj z zbirnim jezikom (angl. assembler), ki so ga
razvili okrog leta 1955, ga uvrščamo med nižje programske jezike. Strojni jezik
sestavljajo nizi ničel in enic. Ker je pri uporabi potrebno natanko poznati pomen
posameznih nizov teh dveh števk, je ta jezik človeku zelo nerazumljiv. Tako strojni kot
zbirni jezik sta strogo odvisna od procesorja. Slednjega so razvili okrog leta 1955, in
sicer tako, da so vsakemu strojnemu ukazu priredili besedni ukaz. Čeprav je bolj
razumljiv kakor strojni jezik, je za človeka še vedno precej zapleten. Ukaze v zbirnem
jeziku so nekoliko kasneje združili v skupino, grupo, ki so jo poimenovali makro, tako
je nastal makro zbirni jezik.
To kopičenje ukazov zbirnega jezika pa je privedlo tudi do razcveta višjih
programskih jezikov, ki človeku omogočajo razumljivejši zapis ukazov, poleg tega pa
se programerjem ni več potrebno ukvarjati s specifičnimi lastnostmi strojnega jezika
(zmanjševanje semantičnega prepada). Tudi pri višjih programskih jezikih poznamo
delitve na več skupin glede na njihove lastnosti. Omenimo le najpomembnejše:
Glede na strukturo prevedenega programa v primerjavi s strukturo izvornega
programa jih delimo na strukturirane in nestrukturirane programske jezike (za
prve je značilno, da pri prevajanju v strojni jezik struktura programa ostane
nespremenjena; primeri: Python, C, Java …, med druge pa navadno uvrščamo
programe, ki podpirajo brezpogojne skoke v kodi, primer je Basic).
Glede na to, kaj pri »kodiranju« programiramo jih delimo na postopkovne in
deklarativne. Postopkovni so tisti, pri kodiranju katerih opisujemo pot, po kateri
bomo prišli do rešitve. Primeri teh so Basic, C, Pascal. Deklarativni pa so tisti, pri
katerih programiranju le-to sloni na definiciji podatkov in povezav med njimi. Ne
programiramo poti do rešitve, temveč zastavljamo vprašanja glede na definicije in
prepustimo jeziku samemu, da poišče pot do rešitve. Primeri: Prolog, List, SQL …
Glede na to, kaj je osnovni element programa, jih delimo na proceduralne in
modularne ali objektne. Pri proceduralnih je osnovni element programa procedura
– postopek; zaporedje oz. nabor funkcionalnosti, ki nima omejitve pri dostopi do
podatkov ali do drugih delov procedur. Primeri so Pascal, Basic, C … Za
modularne ali objektne pa je značilno, da je osnovni element modul s svojo
funkcionalnostjo in svojimi lastnostmi, ki so vgrajene vanj. Primera sta Eifel in Java.
Programske jezike lahko delimo tudi glede na namen njihove uporabe. Dandanes
so zelo pomembni tudi jeziki umetne inteligence, ki se, kot se da sklepati iz imena,
Python za začetnike
7
uporabljajo pri tehnologijah umetne inteligence. Ena izmed njihovih posebnosti je,
da dovoljujejo slovnične napake.
Kot sem že omenil, računalnik razume le strojni jezik, zato mora imeti za namen,
da zna brati tudi zbirni in visoke programske jezike, prevajalnik oz. tolmač.
Prevajalnik (angl. compiler) naenkrat izdela prevod celotnega programa v strojni jezik,
tolmač (angl. interpreter) pa ob vsakem zagonu programa tega prevaja ukaz za
ukazom.
2.2 Python, Pygame in igra Štiri v vrsto
Python spada med strukturirane postopkovne objektne programske jezike.
Poleg strukturiranega in objektnega postopka pri programiranju podpira tudi
zadnjega, dogodkovnega. Podpira veliko različnih podatkovnih tipov (v
računalništvu je to oznaka za množico mogočih vrednosti, ki jih lahko zavzame
podatek). Program Python je Nemec Guido van Rossum napisal v 80. letih prejšnjega
stoletja.
V Python lahko uvozimo veliko različnih modulov. Nekaj se jih prenese ob
namestitvi programa samega, veliko pa jih lahko prenesemo iz interneta. Nekaj izmed
slednjih jih vsebuje zbirka modulov Pygame, ki je namenjena ustvarjanju
računalniških video igric. Ko jo uvozimo v Python, ta dobi množico dodatnih ukazov,
ki jih programer lahko uporabi pri delu. Pygame je prvič izšel leta 2000.
Igra Štiri v vrsto pa se je začela širiti po letu 1974. Za igro samo potrebujemo
igralno tablico (običajno je ta velikosti 7 krat 6 polj) ter žetone dveh različnih barv.
Igralca izmenično mečeta žetone v tablico in tisti, ki štiri svoje žetone uspe vreči v
tablico tako, da stojijo skupaj v vrstici, stolpcu ali pa v kateri izmed obeh diagonal, je
zmagovalec. Je igra z ničelno vsoto, kar pomeni, da je zmaga enega igralca hkrati poraz
njegovega nasprotnika. Kakor vsaka druga igra, je tudi ta zanimiva iz matematičnega
vidika. Če bi tekmovala dva idealna igralca, bi tisti, ki bi igro začel, zagotovo zmagal,
če bi svoj prvi žeton vrgel v srednji stolpec. Tisti, ki bi bil prvi na vrsti, in bi svoj prvi
žeton vrgel v 1. ali 2. oz. v 6. ali 7. stolpec, bi zagotovo izgubil. Neodločeno bi pa bilo,
če bi tisti, ki bi igro začel, svoj prvi žeton vrgel v enega izmed stolpcev, ki sta sosednja
srednjemu.
2.3 Teoretična rešitev naloge
Najprej sem na svoj računalnik namestil program Python in zbirko modulov
Pygame, ki sem jo namestil s pomočjo ukazne kazalke (angl. »command prompt«).
Zatem sem se pričel učiti programiranja v Pythonu na splošno s pomočjo spletne strani
www.codecademy.com, kmalu zatem pa sem se osredotočil na učenje ukazov iz
omenjene zbirke modulov, in sicer s pomočjo spletne strani
thepythongamebook.com/en:start. Ko sem vsaj okvirno predelal poglavja v tej spletni
knjigi, sem se lotil pisanja programa. Ko se mi je kje zataknilo, sem šel iskat rešitev na
katerega izmed forumov, največkrat na naslov stackoverflow.com.
Python za začetnike
8
Spodnja slika predstavlja zasnovo programa, s pomočjo katere sem kasneje
napisal kodo v Pythonu. Psevdo koda:
Python za začetnike
9
3. Praktični del
3.1 Namestitev programa Python in zbirke modulov Pygame
Program Python sem prenesel s spletne strani
https://www.python.org/download/releases/3.4.0/, Pygame pa s spletne strani
http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame. Python sem namestil brez
večjih težav, saj je bilo potrebno zgolj slediti poti, ki jo je kazal računalnik sam. Na
kratko bom opisal nameščanje omenjene zbirke modulov, za katero pa sem porabil več
časa. Verzijo zbirke, ki je ustrezala verziji programa Python sem prenesel s spleta v
datoteki s formatom Zip in jo kopiral v mapo Scripts, ki se nahaja znotraj samodejno
ustvarjene mape Python 34. Nato sem v mapi Scripts, medtem ko sem držal tipko Shift,
kliknil desni miškin gumb, ter nato ukaz Odpri ukazno okno tukaj. Nato sem v to
ukazno okno, torej v ukazno kazalko (angl. command prompt) vpisal naslednje:
pip3 install pygame-1.9.2a0-cp34-none-win32.whl
To je ukaz, s katerim je računalnik namestil Pygame.
Slika 1: Mapa Scripts in ukaz Odpri ukazno okno tukaj (obkrožen).
Python za začetnike
10
3.2 Rešitev v Pythonu
Potem ko sem se naučil osnovnih ukazov, ki jih ponuja uvožena zbirka
modulov, sem pričel s pisanjem igre same. Koda, ki je napisna v Pythonu s pomočjo
modulov Pygame ima v mojem primeru tako ogrodje:
# s prvim ukazom uvozimo zbirko modulov Pygame import pygame # z naslednjim ukazom zaženemo vse module Pygame pygame.init() # določimo velikost zaslona igre (obvezno v dvojnih oklepajih) screen = pygame.display.set_mode((x,y)) # določimo ozadje (velikost); to je t.i. podlaga ("surface") background = pygame.Surface((screen.get_size())) # določimo barvo ozadja background.fill((red,green,blue)) # podlago ozadje nalepimo na zaslon screen.blit(background, (x,y)) # glavna zanka naj teče mainloop = True # zajema naj: while mainloop: # osvežuje celoten zaslon igre pygame.display.flip()
Če nadomestimo neznanke s konkretnimi številkami, se nam po zagonu
naslednje kode prikaže okno na sliki. Na vrhu okna je viden napis "Se ne odziva".
Napis se pojavi, ker je v glavni zanki zgolj ukaz za osveževanja okna, v katerem igra
poteka, in nič drugega.
Slika 2: Zaslon in na vrhu napis »Se ne odziva«.
Python za začetnike
11
Sledi koda, ki predstavlja temelj končnega izdelka te projektne naloge, dodanih
pa je nekaj komentarjev. Še opomba: vrstice, ki se prelomijo, se v programu samem ne
(sicer le-ta ne bi deloval).
Prva vrstica celotnega programa uvozi v program zbirko modulov, ki, kot sem
že omenil, omogočajo določene dodatne ukaze.
import pygame
Program je sestavljen iz dveh definicij. Prva na osnovni zaslon prikaže »menu«,
na katerem igralec lahko klikne »Začni«.
def menu(): pygame.init() screen = pygame.display.set_mode((681,502)) background = pygame.Surface((screen.get_size())) background.fill((216,127,89)) # ustvari novo kopijo ozadja s spremenjeno obliko slikovnih pik, da se # bo potem hitreje narisal na zaslon: background = background.convert() # iz sistemskega fonta ustvari predmet iz črk, SysFont(ime fonta, velikost, odebeljeno = False, ležeče = False) font = pygame.font.SysFont("calibri.tff", 50) # nariše besedilo na novo podlago (zacni) zacni = font.render("Začni", 1, (139,62,29)) zacni.convert() # nariši eno podlago na drugo, pomen posameznih besed: # na ozadje.nalepi(podlaga, ki jo bo nalepil, kam(koordinati)) background.blit(zacni,(100,150)) # zacni1 je sedaj pravokotnik s koordinatami, ki jih ima podlaga zacni # (v oklepajih sem definiral središče podlage zacni) zacni1 = zacni.get_rect(center = (144.5,167.5)) background = background.convert() # nastavi ime zaslona, ki je odprt: pygame.display.set_caption("Štiri v vrsto") # glavna zanka teče, dokler je ne spremenimo v False mainloop = True while mainloop: # dobimo koordinati miškinega kazalca polozaj = pygame.mouse.get_pos() # kaj naredi, če se zgodi določen dogodek (event) for event in pygame.event.get(): # če igralec pritisne križec v desnem zgornjem kotu okna if event.type == pygame.QUIT: # glavna zanka se preneha izvajati mainloop = False # prekliči vse Pygame module pygame.quit() # preveri, če so trenutne koordinate miškinega kazalca znotraj # pravokotnika zacni1; # če so in če uporabnik izpusti katerikoli gumb na miški, naj
Python za začetnike
12
# se zgodi naslednje: if zacni1.collidepoint(polozaj) and event.type == pygame.MOUSEBUTTONUP: # zaženi funkcijo stiri_v_vrsto() stiri_v_vrsto() screen.blit(background,(0,0)) # posodobi celotno podlago na oknu, kjer se vse predvaja pygame.display.flip()
Če zaženemo prvo definicijo, se nam odpre zgornje okno. Na zaslonu lahko kliknemo »začni«
za začetek igre.
Druga definicija z imenom »stiri_v_vrsto«, katere klic vsebuje prva, pa določa
delovanje igre.
def stiri_v_vrsto():
Sledi določitev nekaj osnovnih spremenljivk ter določanje velikosti okna (screen),
ozadja (background) in napisa na vrhu zaslona.
pygame.init() screen = pygame.display.set_mode((681,502)) background = pygame.Surface((screen.get_size())) background.fill((255,255,255)) background = background.convert() # to je 2d seznam; vsaka ničla predstavlja po eno polje v tabeli za igro # poševnica se uporablja za prelom vrstice zunaj oklepajev tabela = \ [ [0,0,0,0,0,0,0],
Slika 3: Menu igre.
Python za začetnike
13
[0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], [0,0,0,0,0,0,0], ] # spremenljivke, ki jih bomo kasneje potrebovali vrstice = 6 stolpci = 7 kvadx = 83 kvady = 67 # naslednja vrstica nastavi napis na vrhu zaslona, ki je odprt: pygame.display.set_caption("Štiri v vrsto")
Če zgornji kodi dodamo še naslednji dva vrstici, ob zagonu dobimo sliko spodaj.
while mainloop: pygame.display.flip()
Slika 4: Okno in napis "Nova igra".
Python za začetnike
14
Naslednjih pet vrstic na podlago ozadje (background) napiše napis "Nova igra".
font = pygame.font.SysFont("calibri.tff", 30) nova_igra = font.render("Nova igra", 1, (138,92,46)) nova_igra.convert() background.blit(nova_igra,((681-115)/2,502-35)) nova_igra1 = nova_igra.get_rect(center = ((681-115)/2+(150-35)/2,(502- 35)+(100-89)/2))
Ta funkcija se, kot vse naslednje, nahaja znotraj funkcije »stiri_v_vrsto()«. Ustvari
podlago z imenom kvadrat in nanjo nalepi bel krog.
# v oklepaju so parametri funkcije def krog_na_kvadratu(kvadx, kvady): # Surface obvezno z veliko začetnico kvadrat = pygame.Surface((kvadx, kvady)) kvadrat.fill((138,92,46)) # nariše krog, ki mu damo ime "krog" (pygame.draw.circle(kam: podlage, barva, # koordinate: kam na podlago, polmer, širina=0 (če želimo kolobar))) krog = pygame.draw.circle(kvadrat, (255,255,255), (42,34), 24) kvadrat = kvadrat.convert() return kvadrat # definiramo spremenljivko kvadrat kot tisto, kar funkcija krog_na_kvadratu(kvadx, kvady) vrne kvadrat = krog_na_kvadratu(kvadx, kvady)
Funkcija narisi_tabelo s parametroma tabela in kvadrat nariše tabelo za igro.
def narisi_tabelo(tabela,kvadrat): seznam_kvadratov = [] for j in range (stolpci): for i in range (vrstice): background.blit(kvadrat,((50+kvadx*j),(50+kvady*i))) seznam_kvadratov.append(background.blit (kvadrat,((50+kvadx*j),(50+kvady*i)))) screen.blit(background, (0,0)) return vrstice, stolpci, kvadx, kvady, background, seznam_kvadratov,j,i vrstice, stolpci, kvadx, kvady, background, seznam_kvadratov, j, i = narisi_tabelo(tabela,kvadrat)
Python za začetnike
15
Ko kodo zaženemo v Python Shell-u, zaenkrat izgleda, kot kaže slika. Zaslon, ki se
pojavi ob zagonu, še ne omogoča nobenih interakcij med igralcem in računikom.
Nadaljnjih sedem funkcij preveri, če se miškin kazalec nahaja na katerem izmed
sedmih stolpcev igralne tabele. Če se nahaja na npr. prvem stolpcu, funkcija stolpec0
vrne True (če se kazalec sploh ne nahaja na tabeli, vse funkcije vrnejo vrednost False).
def stolpec0(polozaj): kazalec = False for i in range (0,6): if seznam_kvadratov[i].collidepoint(polozaj): kazalec = True return kazalec def stolpec1(polozaj): kazalec = False for i in range (6,12): if seznam_kvadratov[i].collidepoint(polozaj): kazalec = True return kazalec def stolpec2(polozaj): kazalec = False for i in range (12,18): if seznam_kvadratov[i].collidepoint(polozaj): kazalec = True return kazalec def stolpec3(polozaj):
Slika 5: Zaslon, ki se pojavi ob zagonu.
Python za začetnike
16
kazalec = False for i in range (18,24): if seznam_kvadratov[i].collidepoint(polozaj): azalec = True return kazalec def stolpec4(polozaj): kazalec = False for i in range (24,30): if seznam_kvadratov[i].collidepoint(polozaj): kazalec = True return kazalec def stolpec5(polozaj): kazalec = False for i in range (30,36): if seznam_kvadratov[i].collidepoint(polozaj): kazalec = True return kazalec def stolpec6(polozaj): kazalec = False for i in range (36,42): if seznam_kvadratov[i].collidepoint(polozaj): kazalec = True return kazalec
Te štiri funkcije tekom igre preverjajo, če so slučajno kje štirje krogi iste barve (bela je
izključena) skupaj v isti vrstici, v istem stolpcu, v isti od katerih izmed dveh diagonal.
# ta funkcija preverja, če so slučajno kje štirje krogi iste barve drug zraven drugega v isti vrstici: def stiri_vrs(): vrs = False x = 0 for i in range (6): for j in range (4): if tabela[i][j] != 0 and tabela[i][j] == tabela[i][j+1] == tabela[i][j+2] == tabela[i][j+3]: vrs = True x = tabela[i][j] return vrs, i, j, x return vrs, i, j, x # to preverja, če so slučajno kje štirje krogi iste barve drug zraven drugega v istem stolpcu: def stiri_stolp(): stolp = False y = 0 for k in range (3): for t in range (6): if tabela[k][t] != 0 and tabela[k][t] == tabela[k+1][t] == tabela[k+2][t] == tabela[k+3][t]: stolp = True y = tabela[k][t] return stolp, k, t, y return stolp, k, t, y
Python za začetnike
17
# to preverja, če so slučajno kje skupaj štirje krogi iste barve po diagonali 1: def stiri_d1(): d1 = False z = 0 for m in range (3): for n in range (4): if tabela[m][n] != 0 and tabela[m][n] == tabela[m+1][n+1] == tabela[m+2][n+2] == tabela[m+3][n+3]: d1 = True z = tabela[m][n] return d1, m, n, z return d1, m, n, z # to preverja, če so slučajno kje skupaj štirje krogi iste barve po diagonali 2: def stiri_d2(): d2 = False l = 0 for o in range (3): for p in range (4): if tabela[o][p+3] != 0 and tabela[o][p+3] == tabela[o+1][p+3-1] == tabela[o+2][p+3-2] == tabela[o+3][p+3-3]: d2 = True l = tabela[o][p+3] return d2, o, p, l return d2, o, p, l
Klic funkcije in določitev vrednosti nekaterih spremenljivk:
narisi_tabelo(tabela, kvadrat) # klic funkcije # definiramo vrednosti logičnih spremenljivk # glavna zanka deluje mainloop = True igralec1 = True igralec2 = False # definiramo nekaj spremenljivk, ki jih bomo kasneje potrebovali za ugotavljanje naslednjega # prostega mesta v posameznem stolpcu, kjer se bo, če bodo izpolnjeni določeni pogoji, narisal krog r0 = 0 r1 = 0 r2 = 0 r3 = 0 r4 = 0 r5 = 0 r6 = 0
Sledi glavna zanka funkcije stiri_v_vrsto():
Python za začetnike
18
while mainloop: # vrne miškini koordinati polozaj = pygame.mouse.get_pos() for event in pygame.event.get(): if event.type == pygame.QUIT: mainloop = False pygame.quit() # če igralec klikne napis "Nova igra" if nova_igra1.collidepoint(polozaj) and event.type == pygame.MOUSEBUTTONUP: # funkcija se na novo zažene stiri_v_vrsto() # če je na vrsti igralec1 in če je miškin gumb izpuščen if igralec1 == True and event.type == pygame.MOUSEBUTTONUP: # preko naslednjih pogojev preveri, na katerem od stolpcev je miškin kazalec, če sploh # je na tabeli, in na novo nariše kvadrat s krogom na najnižjem mestu v stolpcu, ki je še prazno if 5-r0 >= 0: if stolpec0(polozaj): pygame.draw.circle(kvadrat,(34,34,64),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[5- r0][0],seznam_kvadratov[5-r0][1])) tabela[5-r0][0] = 1 r0 += 1 igralec1, igralec2 = igralec2, igralec1 if 5-r1 >= 0: if stolpec1(polozaj): pygame.draw.circle(kvadrat,(34,34,64),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[11- r1][0],seznam_kvadratov[11-r1][1])) tabela[5-r1][1] = 1 r1 += 1 igralec1, igralec2 = igralec2, igralec1 if 5-r2 >= 0: if stolpec2(polozaj): pygame.draw.circle(kvadrat,(34,34,64),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[17- r2][0],seznam_kvadratov[17-r2][1])) tabela[5-r2][2] = 1 r2 += 1 igralec1, igralec2 = igralec2, igralec1 if 5-r3 >= 0: if stolpec3(polozaj): pygame.draw.circle(kvadrat,(34,34,64),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[23- r3][0],seznam_kvadratov[23-r3][1])) tabela[5-r3][3] = 1 r3 += 1 igralec1, igralec2 = igralec2, igralec1 if 5-r4 >= 0: if stolpec4(polozaj): pygame.draw.circle(kvadrat,(34,34,64),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[29- r4][0],seznam_kvadratov[29-r4][1])) tabela[5-r4][4] = 1
Python za začetnike
19
r4 += 1 igralec1, igralec2 = igralec2, igralec1 if 5-r5 >= 0: if stolpec5(polozaj): pygame.draw.circle(kvadrat,(34,34,64),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[35- r5][0],seznam_kvadratov[35-r5][1])) tabela[5-r5][5] = 1 r5 += 1 igralec1, igralec2 = igralec2, igralec1 if 5-r6 >= 0: if stolpec6(polozaj): pygame.draw.circle(kvadrat,(34,34,64),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[41- r6][0],seznam_kvadratov[41-r6][1])) tabela[5-r6][6] = 1 r6 += 1 igralec1, igralec2 = igralec2, igralec1 # če je na vrsti igralec2 (če je njegova vrednost "True"): elif igralec2 == True and event.type == pygame.MOUSEBUTTONUP: if 5-r0 >= 0: if stolpec0(polozaj): pygame.draw.circle(kvadrat,(240,137,33),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[5- r0][0],seznam_kvadratov[5-r0][1])) tabela[5-r0][0] = 2 r0 += 1 igralec2, igralec1 = igralec1, igralec2 if 5-r1 >= 0: if stolpec1(polozaj): pygame.draw.circle(kvadrat,(240,137,33),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[11- r1][0],seznam_kvadratov[11-r1][1])) tabela[5-r1][1] = 2 r1 += 1 igralec2, igralec1 = igralec1, igralec2 if 5-r2 >= 0: if stolpec2(polozaj): pygame.draw.circle(kvadrat,(240,137,33),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[17- r2][0],seznam_kvadratov[17-r2][1])) tabela[5-r2][2] = 2 r2 += 1 igralec2, igralec1 = igralec1, igralec2 if 5-r3 >= 0: if stolpec3(polozaj): pygame.draw.circle(kvadrat,(240,137,33),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[23- r3][0],seznam_kvadratov[23-r3][1])) tabela[5-r3][3] = 2 r3 += 1 igralec2, igralec1 = igralec1, igralec2 if 5-r4 >= 0: if stolpec4(polozaj): pygame.draw.circle(kvadrat,(240,137,33),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[29- r4][0],seznam_kvadratov[29-r4][1])) tabela[5-r4][4] = 2
Python za začetnike
20
r4 += 1 igralec2, igralec1 = igralec1, igralec2 if 5-r5 >= 0: if stolpec5(polozaj): pygame.draw.circle(kvadrat,(240,137,33),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[35- r5][0],seznam_kvadratov[35-r5][1])) tabela[5-r5][5] = 2 r5 += 1 igralec2, igralec1 = igralec1, igralec2 if 5-r6 >= 0: if stolpec6(polozaj): pygame.draw.circle(kvadrat,(240,137,33),(42,34), 24) background.blit(kvadrat,(seznam_kvadratov[41- r6][0],seznam_kvadratov[41-r6][1])) tabela[5-r6][6] = 2 r6 += 1 igralec2, igralec1 = igralec1, igralec2 # kličemo funkcije, ki preverjajo, če so kjerkoli v tabeli štirje krogci iste barve # v isti vrsti ali istem stolpcu ali v isti diagonali vrs, i, j, x = stiri_vrs() stolp, k, t, y = stiri_stolp() d1, m, n, z = stiri_d1() d2, o, p, l = stiri_d2() # če katera izmed zgornjih funkcij dejansko vrne True in če je kroge, ki so narisani # drug zraven drugega, narisal ali igralec1 ali igralec2, na njihova mesta nariši nove # kvadrate s krogi nekoliko svetlejših odtenkov iste barve if x == 1: pygame.draw.circle(kvadrat,(47,47,137),(42,34), 24) background.blit(kvadrat,(j*83+50, i*67+50)) background.blit(kvadrat,((j+1)*83+50, (i)*67+50)) background.blit(kvadrat,((j+2)*83+50, (i)*67+50)) background.blit(kvadrat,((j+3)*83+50, (i)*67+50)) if x == 2: pygame.draw.circle(kvadrat,(242,195,0),(42,34), 24) background.blit(kvadrat,(j*83+50, i*67+50)) background.blit(kvadrat,((j+1)*83+50, (i)*67+50)) background.blit(kvadrat,((j+2)*83+50, (i)*67+50)) background.blit(kvadrat,((j+3)*83+50, (i)*67+50)) if y == 1: pygame.draw.circle(kvadrat,(47,47,137),(42,34), 24) background.blit(kvadrat,(t*83+50, k*67+50)) background.blit(kvadrat,((t)*83+50, (k+1)*67+50)) background.blit(kvadrat,((t)*83+50, (k+2)*67+50)) background.blit(kvadrat,((t)*83+50, (k+3)*67+50)) if y == 2: pygame.draw.circle(kvadrat,(242,195,0),(42,34), 24) background.blit(kvadrat,(t*83+50, k*67+50)) background.blit(kvadrat,((t)*83+50, (k+1)*67+50)) background.blit(kvadrat,((t)*83+50, (k+2)*67+50)) background.blit(kvadrat,((t)*83+50, (k+3)*67+50)) if z == 1: pygame.draw.circle(kvadrat,(47,47,137),(42,34), 24) background.blit(kvadrat,(n*83+50, m*67+50))
Python za začetnike
21
background.blit(kvadrat,((n+1)*83+50, (m+1)*67+50)) background.blit(kvadrat,((n+2)*83+50, (m+2)*67+50)) background.blit(kvadrat,((n+3)*83+50, (m+3)*67+50)) if z == 2: pygame.draw.circle(kvadrat,(242,195,0),(42,34), 24) background.blit(kvadrat,(n*83+50, n*67+50)) background.blit(kvadrat,((n+1)*83+50, (m+1)*67+50)) background.blit(kvadrat,((n+2)*83+50, (m+2)*67+50)) background.blit(kvadrat,((n+3)*83+50, (m+3)*67+50)) if l == 1: pygame.draw.circle(kvadrat,(47,47,137),(42,34), 24) background.blit(kvadrat,((p+3)*83+50, o*67+50)) background.blit(kvadrat,((p+3-1)*83+50, (o+1)*67+50)) background.blit(kvadrat,((p+3-2)*83+50, (o+2)*67+50)) background.blit(kvadrat,((p+3-3)*83+50, (o+3)*67+50)) if l == 2: pygame.draw.circle(kvadrat,(242,195,0),(42,34), 24) background.blit(kvadrat,((p+3)*83+50, o*67+50)) background.blit(kvadrat,((p+3-1)*83+50, (o+1)*67+50)) background.blit(kvadrat,((p+3-2)*83+50, (o+2)*67+50)) background.blit(kvadrat,((p+3-3)*83+50, (o+3)*67+50)) # prilepi ozadje na zaslon screen.blit(background, (0,0)) # vsakokrat posodobi, osveži celotno okno pygame.display.flip() """ Kako neposredno zaženemo napisani program? Preverimo notranjo spremenljivko __name__. V tej spremenljivki Python shrani ime ime Pythonovega modula, ki je uvozil napisani program. Če ta program zaženemo neposredno, torej iz ukaznega poziva ali iz urejevalnika Pythona, dobi omenjena spremenljivka ime __mail__. Brez teh dveh vrstic program ne dela. """ if __name__ == "__main__": menu()
To je torej programska koda. Če imamo ustrezno različico Pythona in zahtevane
zbirke modulov, se nam program zažene. Kot že omenjeno, se nam najprej pojavi
menu igre. Če kliknemo začni ter igramo igro, v primeru da zmaga igralec1, okno
izgleda takole:
Python za začetnike
22
Slika 6: Zmagal je igralec1.
Slika 7: Zmagal je igralec2.
Python za začetnike
23
3.3 Pretvorba programa v izvršljivo datoteko s končnico .exe
Najprej sem z interneta prenesel program cx_Freeze. Pretvorbi je sicer, če
sklepamo zgolj iz imena, namenjen program py2exe, vendar v osnovi deluje le za
programe Python verzije 2.x. Izdane so bile tudi različice za pretvorbo verzij 3.x,
vendar jih nisem uspel prenesti na svoj računalnik. Program cx_Freeze je bil napisan z
istim namenom kot program py2.exe. Pri namestitvi sem spet zgolj sledil računalniku,
pretvorba sama pa je bila zame kot računalniškega začetnika nekoliko zahtevnejša.
V isti mapi, v kateri sem imel shranjeno Python datoteko s programsko kodo in
sam program Python, sem ustvaril datoteko z imenom setup.py, v kateri sem napisal
naslednje (sledil sem navodilom iz vira, ne vem točno, kaj posamezen ukaz naredi):
Prav tako v tej mapi sem nato medtem ko sem držal tipko Shift kliknil desni
miškin gumb ter nato ukaz »Odpri ukazno okno tukaj«. V ukazno kazalko sem nato
vpisal naslednje besede: python setup.py build. Med izvrševanjem tega ukaza se je v
omenjeni mapi ustvarila nova mapa z imenom build. Vsebovala je polno datotek, med
drugim tudi eno izvršljivo datoteko z imenom stiri_v_vrsto.exe. Vendar pa slednja
samostojno, brez preostalih, ne deluje.
Slika 8: Koda v datoteki z imenom setup.py .
Python za začetnike
24
4. Sklep
Projektna naloga je dokončana. Vsaj v grobem sta dosežena oba cilja: igra Štiri
v vrsto je napisana in pretvorjena v izvršljivo datoteko s končnico .exe. V
dokumentacijo sem vključil kodo programa v Pythonu ter razlaga njenih posameznih
delov. Za zaključek bom napisal še dva seznama: enega, ki bo vseboval težave, ki so
se mi med delom pojavljale, in ki sem jih bolj ali manj uspešno premostil, ter drugega,
seznam izboljšav, ki jih je sicer neskončno, vendar bi jih nekaj posebno rad omenil.
Težave, ki so se mi pojavljale med delom, in rešitve le-teh:
Kodo sem želel skrajšati, saj je na treh mestih napisana zelo na široko, za vsak
stolpec posebej, vendar mi to zaradi for zanke, katere delovanje nisem vnaprej
predvidel, ni uspelo. Po dobri uri poskušanja sem to idejo opustil, izziv ostaja še
nerešen.
Težave sem imel čisto na začetku tudi s tem, kako narisati samo tabelo za igro.
Sedaj bi mi bil to najbrž mačji kašelj, vendar pa sem takrat poskušal najprej s
pomočjo dvodimenzionalnega seznama. To je sicer uspelo, vendar pa je nastal
problem, ko je bilo potrebno napisati, kako naj program preverja, če so kje štirje
žetoni »v vrsti«. Tu sem si pomagal z internetom, kjer sem na forumu
Stackoverflow našel izvirno rešitev: preko spreminjanja vrednosti v
dvodimenzionalnem seznamu. Ko igralec 1 oz. igralec 2 klikne na določen stolpec
in se v njem nariše krogec, se hkrati na istem mestu v seznamu ničla spremeni v
enico oz. dvojko. Nato je bilo potrebno napisati le še algoritem za preverjanje, če so
kje štiri enake številke (razen ničel) »v vrsti«.
Izboljšave, ki se mi zdijo precej pomembne, če bi igro želel objaviti na spletu:
Najprej naj omenim dve stvari: Prvič, kodo bi bilo potrebno napisati tako, da bi se
igra, ko bi eden od igralcev dosegel štiri v vrsto, prekinila. Zaenkrat se da žetone
še naprej metati v stolpce. Drugič, odstraniti hrošča - če ima igralec 2 štiri svoje
žetone skupaj po diagonali f tako, da je žeton, ki je izmed teh štirih najnižji hkrati
5. žeton v spodnji vrstici, se ta (in če se ne motim, je to dejansko edina) četverica
nepravilno obarva.
Python za začetnike
25
Na že omenjenih treh mestih bi se dalo kodo precej skrajšati. Za hitrejše delovanje
programa in sam izgled kode bi bilo to zelo koristno. Morda bi bilo za ta namen
potrebno sploh popolnoma spremeniti koncept delovanja programa.
Dobro bi bilo lepše oblikovati menu igre, dodati še kakšno možnost (zaenkrat
igralec lahko klikne le »začni«), v igri sami malo spremeniti barve, dodati ozadje
…
Posebno dobro bi bilo v menu dodati možnost, da bi igralec igral proti računalniku.
To bi seveda zahtevalo še precej časa, posebno če bi želeli napisat res izpiljen
algoritem za strategijo, ki bi se jo posluževal računalnik.
Slika 9: Hrošč v programu.
Python za začetnike
Učenje Pisanje programa
Pretvorba v izvršljivo datoteko Pisanje dokumentaicije
Graf 1: Čas (v odstotkih), ki sem ga porabil za posamezen del projektne naloge.
Python za začetnike
26
Še nekaj besed o uporabnosti rešitve. Kot omenjeno, je program v določenih
pogledih dokaj okoren, vendar je v njem možno izvajati tisto, za kar je bil napisan.
Pred morebitno objavo na spletu pa bi ga vseeno nadgradil vsaj kar se tiče omenjenih
pomanjkljivosti. Če pogledam nazaj, sem s svojim delo precej zadovoljen. Vzelo mi je
sicer res kar nekaj nepotrebnih ur več, kot bi mi jih lahko, če bi bil že nekoliko bolj
izkušen. Razočaran sem edino nad prvima dvema stvarema, ki sem ju napisal na
seznam stvari, ki bi jih lahko izboljšali. Programiranje mi je bilo v veselje, sedaj grem
nekoliko bolj izkušen novim izzivom naproti.
5. Viri in literatura
Avtor neznan: Delitev programskih jezikov (online). [Uporabljeno 3.3.2016]
Dostopno na
http://colos.fri.unilj.si/eri/RACUNALNISTVO/PROG_JEZIKI_ORODJA/02Del
itevProgJezikov/02_delitevProgramskihJezikov.html
Skellykiernan: Python + PyGame Install (online). [Uporabljeno 1.2.2016] Dostopno
na https://skellykiernan.wordpress.com/2015/01/04/python-pygame-install/
Jens, H.: The Python Game Book (online). [Uporabljeno 19.2.2016] Dostopno na
http://thepythongamebook.com/en:start
Johnson, K.: [Tutor] Accesing »column« of a 2D list. (online) [Uporabljeno
20.2.2016] Dostopno na https://mail.python.org/pipermail/tutor/2007-
August/056549.html
Sentdex: Converting tkinter to exe tutorial with cx_Freeze - Python 3.4 part 29
(online). [Uporabljeno 19.3.2016] Dostopno na
https://www.youtube.com/watch?v=HosXxXE24hA
Harrison: Converting PyGame to an executable (online). [Uporabljeno 19.3.2015]
Dostopno na https://pythonprogramming.net/converting-pygame-executable-
cx_freeze/
Več avtorjev: Four in a row logic (online). [Uporabljeno 23.3.2016] Dostopno na
http://stackoverflow.com/questions/15457796/four-in-a-row-logic
Codecademy: Python (online). [Uporabljeno 1.2.2016] Dostopno na
https://www.codecademy.com/learn/python
Avtor neznan: Connect four (online). [Uporabljeno 26.3.2016] Dostopno na
https://en.wikipedia.org/wiki/Connect_Four
Python za začetnike
27
6. Priloge
-Kratek opis
-Osnutek
-Spletna stran
-Koda v programskem jeziku Python
-Izvršljiva datoteka Štiri v vrsto