Ügyességi játékok programozása Pythonnal és Pygame-mel

Ügyességi játékok programozása
Pythonnal és Pygame-mel

Chapter 4: Véletlenszerű számokat és ciklusokat használó Kitalálós játék

Az utolsó fejezet, mielőtt a grafikával kezdenénk, megtanuljuk a ciklusokat kezelni. A legtöbb játék egy ciklus. Ugyanazt a kódot ismétlik újra és újra. Például a számkitalálós játékban a ciklikusan újrapróbál minden találgatást:

Video: The for loop
Szia! Én gondoltam egy számra 1 és 100 közt.
--- Próba 1
Találd ki, mire gondolok: 50
Túl nagy. 
--- Próba 2
Találd ki, mire gondolok: 25
Túl nagy. 
--- Próba 3
Találd ki, mire gondolok: 17
Túl nagy. 
--- Próba 4
Találd ki, mire gondolok: 9
Túl kicsi. 
--- Próba 5
Találd ki, mire gondolok: 14
Túl nagy. 
--- Próba 6
Találd ki, mire gondolok: 12
Túl nagy. 
--- Próba 7
Találd ki, mire gondolok: 10
Túl kicsi. 
Ó, kifogytál a próábálkozási lehetőségekből. A szám 11 volt. 

Várjunk csak, mit számít ez grafikában és videójátékokban? Sokat. Minden, amit a játék megjelenít, az egy frame/keret, amit bizonyos időközönként megjelenít, egy ciklussal. Ismerős lehet, a keret-per-másodperc (FPS) statisztika, amit a játékok szoktak használni. Minél magasabb a szám, annál szebb játékról beszélünk. (Noha, az FPS ha 60 felett van, akkor az már magasabb, mint amit egy átlag képernyő képes update-elni.) Ábra:4.1, itt azt láthatjuk, hogy az Eve Online játék grafikai megjelenítése mennyi keretet képes másodpercenként képes megjeleníteni.

fig.fps
Figure 4.1: FPS in video games

A ciklusok ezekben a játékokban úgy működnek, mint egy folyamatábra, lásd ábra: 4.2. A modern játékok összetettségének ellenére, a ciklus magja maga elég egyszerű, és hasonló a számológépes programhoz, amit az első fejezetben csináltunk. Kérjünk bemeneti adatot a felhasználótól. Számoljunk. Adjunk kimenetet. Egy videó játékban megpróbáljuk ezt megcsinálni 60-nál is több alkalommal másodpercenként.

fig.game_loop
Figure 4.2: Game loop

Lehetnek ciklusok másik ciklusokban. Egy igazi ciklus a ciklusban eset. Vess egy pillantást a “Draw Everything” dobozra ezen az ábrán: 4.2. Ez a kódsorozat ciklikusan ismétlődik és kirajzol minden tárgyat a játékban. Ez a cikllus egy nagyobb cikluson belül van, ami minden keretet kirajzol a játékban, lásd itt: Figure 4.3.

fig.draw_everything
Figure 4.3: Draw everything loop

Két fontosabb típusú ciklus van a Pythonban, a for és a while ciklus. Ha valamit egy adott szám szerint akarsz ismételni, akkor használd a for-t. Ha addig akarsz valamit ismételni, amíg valami történik (például a felhaszbáló lenyom egy kilépés billentyűt), akkor használd a while-t.

Például, egy for ciklust használhatunk arra, hogy kiírassuk az összes adatát a diákoknak, mivel a gép tudja, mennyi diák van. Egy while ciklus jó lehet arra, hogy leellenőrízzük, hogy a játékos megnyom e egy gombot az egeren, mivel itt nem tudjuk megmondani mennyit kellene erre várni.

4.1 For ciklusok

A for ciklus például alább végrehajt ötször egy print parancsot. Ezt ugyanolyan könnyű 100 vagy 1 millió alkalommal végrehajtatn, csupán azáltal, hogy megváltoztatjuk az 5-t, a kívánt számra. Érdemes megfigyelni a for parancs felépítése mennyire hasonlít az if parancsra. Mindkettő egy kettősponttal végződik, és mindkettő használ sorbehúzást, melyek hatással vannak a programkódra.
for i in range(5):
    print ("I will not chew gum in class.")
Output:
I will not chew gum in class.
I will not chew gum in class.
I will not chew gum in class.
I will not chew gum in class.
I will not chew gum in class.

Az i az első sorban egy változó, mi nyomonköveti azt, hogy mennyiszer fut le a ciklus. Ez egy új változó, úgyhogy el kell látni érvényes változó névvel. A programozók kedvelik az i változó nevet, mivel az i egy rövidítés is lehet, az angol increment-re utal: maygarul növekményre, függvényváltozásra. Ez a változó segít minket nyomon követni, hogy mikor ér véget a ciklus.

A range függvény irányítja azt, hogy mennyiszer hajtódik végre a cikluskód. Ezesetben ötször.

A következő példa kód kiírja ötször, hogy "Kérlek" és egyszer, hogy "Elmehetek a plázába?". Az "Elmehetek a plázába" nincs sorbehúzva, szóval nem a for ciklus része, nem lesz annyiszor kiírva, nem lesz addig, amíg a ciklus le nem fut.
for i in range(5):
    print ("Please,")
print ("Can I go to the mall?")
Output:
Please,
Please,
Please,
Please,
Please,
Can I go to the mall?

A következő kód példa arra, hogy behúzzuk a hármas sort, és így ötször lesz a "Kérlek" és a "Elmehetek a plázába?" szöveg is kiírva. Mivel a parancs be van húzva, ezért az "Elmehetek a plázába?" immár a része a ciklusnak, és így ötször lesz megismételve, miképpen a "Kérlek".
for i in range(5):
    print ("Please,")
    print ("Can I go to the mall?")
Output:
Please,
Can I go to the mall?
Please,
Can I go to the mall?
Please,
Can I go to the mall?
Please,
Can I go to the mall?
Please,
Can I go to the mall?

A lenti kód 0-tól 9-ig írja ki a számokat. Megjegyzem, hogy a ciklus nullával indul, és nem foglalja magába a 10-t. Természetszerűleg a 10-t mi beleértenénk a range(10)-be, de pont azelőtt áll meg.
for i in range(10):
    print(i)
Output:
0
1
2
3
4
5
6
7
8
9

Egy program számára nem szükséges, hogy i legyen a változó neve, nevet adhatunk bármi más után. Például egy programozó használhat számsort, ha úgy akarja.

Ha egy programozó 1-től 10-ig akar számolni, és nem 0-tól 9-ig, akkor arra van elég sok lehetőség. Az első lehetőség, hogy a range függvényen változtatunk, két számot. Az első szám a kezdő érték, a második a végérték.

Ehhez kell egy kis gyakorlat, hogy hogyan használjuk a for ciklust, amikor az első számot kiíratjuk, az utolsót nem. A példában alat, a range (1,11) közt lesz, és 1-10-ig íratja ki a számokat. A kezdő szám 1, de a végső szám nem a 11.
for i in range(1,11):
    print(i)
Output:
1
2
3
4
5
6
7
8
9
10

Egy másik lehetséges mód arra, hogy kiírassuk a számokat 1-től 10-ig, ugyanígy a range(10) használata, az i változóval, ami 0-tól 9-ig számol. De, mielőtt kiírnánk az eredményt, adjunk +1-t a számhoz. Szintén 1-10-ig írja majd ki a számokat. Mindkét eljárás jól működik.

# Print the numbers 1 to 10.
for i in range(10):
    print(i + 1)

4.1.1 Számok megszámolása, melyek nem egyesek

Ha kell, egy olyan program, ami kettessével számol, vagy más számmal, akkor az is egyszerű. Mint előzőleg, itt is kétféle út áll előttünk. Az egyszerűbb, hogy megadunk egy harmadik számot a range függvénybe, ami megmondja, hogy most kettessével számolunk. A másik lehetőség, hogy egyesével számolunk, de megszorozzuk a változót kettővel. A lenti példa mindkét eljárást bemutatja:
# Two ways to print the even numbers 2 to 10
for i in range(2,12,2):
    print(i)
    
for i in range(5):
    print ((i + 1) * 2)
Output:
2
4
6
8
10
2
4
6
8
10

Lehetséges tovább, hoogy visszafelé, vagy lefelé is számoljunk, ekkor a range függvénynek negatív lépést kell megadnunk. A lenti példában, 10-zel kezdünk, és lefelé számolunk, de nem érintjük a nullát, és -1-gyel csökken a változónk. A legnehezebb rész ezekben a ciklusokban, hogy véletlenszeráen kell változtatnunk a kezdő és végző számot. Egy normál for ciklus, ami felfelé számol, az mindig a legkisebb számmal kezd a range függvényben.
for i in range(10, 0, -1):
    print(i)
Output:
10
9
8
7
6
5
4
3
2
1

Ha a számok, amikre a programnak szüksége van, nem alkotnak könnyá mintát, akkor lehetőség van számokat kivenni a listából. (Teljes leírás lesz a listákról majd a hetedik fejezetben. Ez csak egy kis ízelítő, hogy mit is csinálhatsz velük.)

for i in [2,6,4,2,4,6,7,4]:
    print(i)

This prints:

2
6
4
2
4
6
7
4

4.1.2 Egymásba ágyazott ciklusok

Próbáld megjósolni, hogy a lenti kód mit írhat ki. Azután meg a kódot és lásd, hogy jól gondolkodtál-e.

# What does this print? Why?
for i in range(3):
    print ("a")
for j in range(3):
	print ("b")
Video: Nesting for loops

A következő kódsor majdnem hasonló a fentihez. A második for ciklus beljebb van húzva egy tabulátorral, így beágyazott ciklusnak nevezzük. Ez jelentős különbséget jelent a program futásában, próbáld ki és tapasztald meg.

# What does this print? Why?
for i in range(3):
    print("a")
    for j in range(3):
        print("b")

print("Done")

Nem fogom megmondani, hogy ez a kód mit csinál, menj a géphez, és nézd meg magad.

Video: for loop animation

4.1.3 Keeping a Running Total

Megszokott művelet a ciklusokkal való munka során az összeg (total) megadása. Ez a "running total" (folyamatos összeg/összesítés) kódminta sokat lesz használva ebben a könyben. Ezt használjuk pontszámok megadásához, egy személy teljes számla tranzakcióját, a totált használjuk, hogy megtaláljuk az átlagot, stb. Lehet, kell majd könyvjelzőznöd ezt a kódlistát, mivel erre fogunk majd visszautalni elég sokszor. A lenti kódnál, a felhasználó 5 számot visz be, és a kód kiszámolja a total/összeg értéket.

total = 0
for i in range(5):
    newNumber = int(input("Enter a number: " ))
    total += newNumber
print("The total is: ",total)
Video: Using a loop to keep a running total

Megjegyzés, az első sorban hozzuk létre a total változót, és egyből fel is töltjük nulla értékkel. Elég könnyű elfelejteni, hogy kezdetben definiálni kell a változót, és nulla értéket rendelni hozzá. Enélkül, a gép panaszkodni kezdene a negyedik sorban. Ugyanis nem tudná, hogyan adhatna newNumber-t a total-hoz, mivel a total-nak még nem volt értéke eddig.

Gyakori hiba, hogy i-t szokták használni a total-hoz, a newNumber helyett. Jegyezzük meg, hogy mi folyamatosan az összeget akarjuk megkapni, a felhasználó által megadott számok alapján, és nem az éppen aktuális összegét a ciklus számlálónak.

Kicsit beszéljünk akkor a ciklus számlálóról, a ciklusszámlálót matematikai feladatok megoldásánál használhatjuk. Például:

$s=\sum\limits_{n=1}^{100}n$

Ha nem ismerős ez a forumla, akkor van egy másik tetszetős megoldás is:

$s=1+2+3+4+5 \ldots 98+99+100$

A lenti kód összeadja a számokat 1-től 100-ig. Egy gyakori módszerre jó példa, amikor az aktuális összeg a a cikluson belül van. Használ még egy külön változót is a sum-t, amivel a total-t követi nyomon.

# What is the value of sum?
sum = 0
for i in range(1,101):
    sum = sum + i
print(sum)  	

Itt van még egy másik variáció. Ez öt számot kér be a felhasználótól, és megszámolja azt, hogy mennyiszer ütött be a felhasználó nullát.

total = 0
for i in range(5):
    newNumber = int(input( "Enter a number: "))
    if newNumber == 0:
        total += 1
print("You entered a total of",total,"zeros")

Az a programozó, aki már megértette az egymásba ágyazott for ciklusok jelentőségét, és a folyamatos összegét, képes arra, hogy megjósolja az eredményét a lenti kódnak.

# What is the value of a?
a = 0
for i in range(10):
    a=a+1
print(a)

# What is the value of a?
a = 0
for i in range(10):
    a = a + 1
for j in range(10):
    a = a + 1
print(a)

# What is the value of a?
a = 0
for i in range(10):
    a = a + 1
    for j in range(10):
        a = a + 1
print(a)     

Ne rohanj át ezen a részen. Adj egy esélyt magadnak és jósold meg a kód kimenetét. Aztán másold be a kódot a Python programodba, és futtasd le, hogy meglásd, igazad van-e. Ha nem, akkor keresd meg miért. Don't go over this section too fast. Give it a try and predict the output of the code above. Then copy it into a Python program and run it to see if you are right. If you aren't, figure out why.

4.2 Example for Loops

Ez a példa szokványos for ciklusokat mutat be működés közben. .

# Sample Python/Pygame Programs
# Simpson College Computer Science
# http://programarcadegames.com/
# http://simpson.edu/computer-science/

# Print 'Hi' 10 times
for i in range(10):
    print("Hi")

# Print 'Hello' 5 times and 'There' once
for i in range(5):
    print("Hello")
print("There")

# Print 'Hello' 'There' 5 times
for i in range(5):
    print("Hello")
    print("There")

# Print the numbers 0 to 9
for i in range(10):
    print(i)

# Two ways to print the numbers 1 to 10
for i in range(1, 11):
    print(i)

for i in range(10):
    print(i + 1)

# Two ways to print the even numbers 2 to 10
for i in range(2, 12, 2):
    print(i)

for i in range(5):
    print((i + 1) * 2)

# Count down from 10 down to 1 (not zero)
for i in range(10, 0, -1):
    print(i)

# Print numbers out of a list
for i in [2, 6, 4, 2, 4, 6, 7, 4]:
    print(i)

# What does this print? Why?
for i in range(3):
    print("a")
    for j in range(3):
        print("b")

# What is the value of a?
a = 0
for i in range(10):
    a = a + 1
print(a)

# What is the value of a?
a = 0
for i in range(10):
    a = a + 1
for j in range(10):
    a = a + 1
print(a)

# What is the value of a?
a = 0
for i in range(10):
    a = a + 1
    for j in range(10):
        a = a + 1
print(a)

# What is the value of sum?
sum = 0
for i in range(1, 101):
    sum = sum + i

4.3 While ciklusok

Video: The while loop

A for ciklust akkor használjuk, amikor a program tudja, hogy mennyiszer kell ismételni egy adott kódsorozatot. A while ciklust akkor használjuk, amikor a programnak egy megadott állapot bekövetkeztére van szüksége.

A while ciklus bárhol használható, ahol for ciklust használnánk. Lehet használni arra, hogy ismétlődjön, amíg egy megadott változó el nem ér egy adott értéket. Miért van akkor for ciklusunk, ha a while ciklusunk megcsinálhat mindent? A for-t könnyebb használni kódolás során. Egy for ciklus, ami így néz ki:

for i in range(10):
    print(i)

...helyettesíthető while ciklussal, ami így néz ki:

i = 0
while i < 10:
    print(i)
    i = i + 1

Az első sor a while ciklusban értéket ad egy "megfigyelő" változónak, amit arra használunk, hogy megszámolja, hányszor hajtódott végre a ciklus. Ez automatikusan megtörténik egy for ciklusban, egy sor kóddal. A második sor tartalmazza az aktuális while ciklust. A while ciklus formája nagyon hasonló az if parancséhoz. Ha az állapot nem változik, akkor a kód lefog futni. A negyedik sorban megtörténik az érték változása. Egy for ciklusban ez automatikus, megincsak eggyel több sor. És ha valaki ránéz a kódra, azt veheti észre, hogy a for ciklus összetettebb, mint a while ciklus, és könnyebb olvasni. Másfelől a programunk bármit megcsinálhat egy while ciklussal.

Gyakori hoba, hogy a for ciklust összekeverik a while ciklussal. A lenti kód arra példa, amikor a programozó nem tud fejben különbséget tenni a for és a while ciklusok közt.

while range(10):	
    print(i)
Ne használd a range parancsot a while ciklussal!

A range függvény csak akkor működik, for ciklussal használod. Ne használd a while ciklussal!

4.3.1 Növekvő operátor használata

Növekvő operátorokat gyakran használunk while ciklusokban. Lehetőség van lerövidíteni a kódot:

i = i + 1

A következővel:

i += 1

A while ciklusban így kéne kinéznie:

i = 0
while i < 10:
    print(i)
    i += 1

Használható kivonással és szorzással is. Például:

i *= 2

Ez ugyanaz:

i = i * 2

Nézd meg ezt, és képzeld el, mi lehet a kimenet:

i = 1
while i <= 2 ** 32:
    print(i)
    i *= 2  

4.3.2 Ciklikus ismétlődés amíg a felhasználó ki nem szeretne lépni

Az egyik leggyakoribb működtetése egy ciklusnak, hogy addig fut, amíg a felhasználó ne szól, hogy ki szeretne lépni:

quit = "n"
while quit == "n":
    quit = input ("Do you want to quit? ")

Sokféle módja van egy ciklus megszakításának. Használhatunk Boolean változót is, hogy megkapjuk azt az eseményt, ami ezt előidézi. Itt egy példa rá:

done = False
while not done:
    quit = input ("Do you want to quit? ")
    if quit == "y" :
        done = True;
        
    attack = input ("Does your elf attack the dragon? ")
    if attack == "y":
        print ("Bad choice, you died.")
        done = True;

Ez persze nem tökéletes, mivel ha a játékos ki akar lépni, akkor is megkérdezi a kód, meg akarja-e támadni még a sárkányt. Hogyan tudnánk kijavítani ezt?

Itt egy példa while ciklus használatára, ahol a kód addig ismétlődik, amíg a kód elég közel nem kerül nullához. (elírás, amíg elég közel nem kerül nullától egyhez - a ford.)

value = 0
increment = 0.5
while value < 0.999:
    value += increment
    increment *= 0.5
    print(value)

4.3.3 Gyakori problémák a while ciklusokkal

A programozó 10-től lefelé akar számolni. Mi a rossz és hogyan lehet kijavítani?

i = 10
while i == 0:
    print (i)
    i -= 1

Mi a hiba ebben a ciklusban, ami 10-ig akar számolni? Mi fog történni, amikor lefut? Hogyan lehet kijavítani?

i = 1
while i < 10:
    print (i)

4.4 Példa while ciklusokra

Itt egy program, amiben szemléltetve vannak a különböző felhasználási módjai a while ciklusnak, amikről korábban beszéltünk.

# Sample Python/Pygame Programs
# Simpson College Computer Science
# http://programarcadegames.com/
# http://simpson.edu/computer-science/

# A while loop can be used anywhere a for loop is used:
i = 0
while i < 10:
    print(i)
    i = i + 1

# This is the same as:
for i in range(10):
    print(i)

# It is possible to short hand the code:
# i = i + 1
# With the following:
# i += 1
# This can be done with subtraction, and multiplication as well.
i = 0
while i < 10:
    print(i)
    i += 1

# What would this print?
i = 1
while i <= 2**32:
    print(i)
    i *= 2

# A very common operation is to loop until the user performs
# a request to quit
quit = "n"
while quit == "n":
    quit = input("Do you want to quit? ")

# There may be several ways for a loop to quit. Using a boolean
# to trigger the event is a way of handling that.
done = False
while not done:
    quit = input("Do you want to quit? ")
    if quit == "y":
        done = True

    attack = input("Does your elf attach the dragon? ")
    if attack == "y":
        print("Bad choice, you died.")
        done = True

value = 0
increment = 0.5
while value < 0.999:
    value += increment
    increment *= 0.5
    print(value)

# -- Common problems with while loops --

# The programmer wants to count down from 10
# What is wrong and how to fix it?
i = 10
while i == 0:
    print(i)
    i -= 1

# What is wrong with this loop that tries
# to count to 10? What will happen when it is run?
i = 1
while i < 10:
    print(i)

4.5 Véletlen számok

A véletlen számokat elég sűrűn használják a számítástechnikában, főleg a játék szimulációban.

4.5.1 A randrange függvény

Video: Random Numbers

Alapbeállítás szerint, a Python nem tudja hogyan használjon véletlen számokat. Szükséges, hogy importáljuk a kódkönyvtárát ahhoz, hogy véletlenszerű számot állíthassunk elő. Nos, a véletlenszámok használata, az első dolog, ami miatt meg kell tanulnunk az import parancs használatát:

import random

Miképpen a pygame-ben is, fontos, hogy ne készítsünk olyan fájlt, aminek az a neve, amit importáltunk. Ha olyan fájlt csinálunk, amit aztán random.py-nak nevezünk el, azt fogja okozni, hogy a Python ezt a fájlt fogja beolvasni a rendszer könyvtárában lévő helyett.

Ezekután, a véletlenszerű számokat már elő is állíthatjuk a randrange függvény. Például, ez a kód egy véletlenszerű számot fog készíteni 0 és 49 köszt. Az alapértelmezett legkisebb a 0.

my_number = random.randrange(50)

A következő példakód egy véletlenszerű számot állít elő 100 és 200 közt. Figyeld meg a range függvényt. A második paraméter a felső határt jelöli. Továbbá, ha 200-ig akarsz számolni, akkor 201-t kell ide írnod.

my_number = random.randrange(100,201)

Mi van akkor, ha nem számot, hanem egy véletlenszerű elemet akarsz? Ahhoz már lista kell. Nem foglalkozunk a listákkal a, majd csak a 7-dik fejezetben, de egy kis ízelítő legyen itt, hogyan is néz ki egy véletlenszerűen kiválasztott elem, lássuk:

my_list = ["rock", "paper", "scissors"]
random_index = random.randrange(3)
print(my_list[random_index])

4.5.2 A random függvény

Minden megadott kód integer (egész) számot generál. Ha egy floating (tört) számot szeretnénk, akkor is használhatjuk a véletlenszám generáló random függvényt.

A lenti kód egy véletlenszerű számot állít elő, 0 és 1 közt, mint amilyen a 0.4355991106620656.

my_number = random.random()

Egy kis matekkal, ezt a számot is változtathatjuk. Például a lenti kód egy véletlenszerű törtszámot állít elő 10 és 15 közt:

my_number = random.random() * 5 + 10

4.6 Review

4.6.1 Multiple Choice Quiz

Click here for a multiple-choice quiz.

4.6.2 Short Answer Worksheet

Click here for the chapter worksheet.

4.6.3 Lab

Click here for the chapter lab.


You are not logged in. Log in here and track your progress.