Edukira joan

PYTHON liburua/Aplikazioak II: argazkien tratamendua eta jokoak

Wikibookstik

11. Aplikazioa II: argazkien tratamenduak eta jokoak

[aldatu]

Kapitulu honetan programa luzeago batzuk landuko ditugu, gure ustez oso motibagarriak diren bi gaitan: jokoak eta irudien tratamendua. Kapitulu honetarako oso baliagarria gertatu zaigu webgune hau eta bertan agertzen diren liburuak: https://inventwithpython.com/.

Ariketa hauetan gauza ahaltsu samarrak lortu nahi dira, eta hori lortzeko aurreprogramatutako moduluak erabiliko dira. Modulu horiek instalatzea izango da lanaren parte bat. Bestalde, ezin gara sartu modulu horien zehaztasunak esplikatzen, bestela liburua izugarri luzatuko litzateke eta. Hori egin ordez, erabilera-adibideen bitartez ikasteko estrategiari helduko diogu.

11.1. ARGAZKIEN TRATAMENDUA

[aldatu]

Argazkiei tratamendu bereziak egitea ohikoa da. Zerbait puntuala denean edo ukitu artistikoa bada banan-banan egin behar da GIMP bezalako programa bat erabiliz. Baina askotan lan errepikakorra egiten dugu, adibidez argazkien bereizmena eta tamaina jaisteko, formatua aldatzeko edo bereizgarriren bat txertatzeko.

Atal honetan lan errepikakor horiek automatizatzeko programazioa landuko dugu eta horretarako Pillow modulua erabiliko dugu. Modulu hori oso interesgarria da argazkien eta irudien tratamendua egiteko. Mota guztietako manipulazioak egin daitezke, argazki-zati bat lortzea, argazki bat kopiatzea, tamainaz edo formatuz aldatzea, biratzea, geruza desberdinak gainjartzea, filtroak aplikatzea...

Pillow modulu horren metodoak oso metodo sinpleak dira, erraz-erraz ulertzen direnak. Informazio zehatzagoa hemen kontsulta daiteke:

Pillow modulu horren metodoak oso metodo sinpleak dira, erraz-erraz ulertzen direnak. Informazio zehatzagoa hemen kontsulta daiteke: http://pillow.readthedocs.org/en/3.1.x/handbook/tutorial.html.

11.1.1. Instalazioa

[aldatu]

Linux barruan modulua instalatu ahal izateko hurrengo urratsak egingo ditugu:

  • Pillow paketearekin dauden mendekotasunak ebaztea. Guk erabilitako Ubuntu sisteman honela egiten da:
 sudo apt-get install python3-dev python3-setuptools
 sudo apt-get install libtiff4-dev libjpeg8-dev zli1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev
  • Pillow bera instalatzea:
 sudo pip3 install Pillow

11.1.2. Ariketa: Argazkiei logo bat itsatsi nahian

[aldatu]

Ariketa honetan png edota jpg formatuan dauden hainbat argazki ditugu karpeta baten barruan (azpikarpetetan ere egon daitezke) eta argazki horietan guztietan, tamaina batetik gorakoak baldin badira, logo bat itsatsi nahi dugu eta sortutako argazki berriak karpeta berri batean utziko ditugu. Logoa handi samarra denez, azalera txikiagoarekin itsatsiko dugu. Programak, beraz, hiru parametro izango ditu: argazkiak dauzkan karpeta, logoa duen fitxategia eta emaitzak uzteko karpeta (aurretik sortua). Ariketa honen inspirazioa hemen aurki daiteke: <https://automatetheboringstuff.com/ chapter17/>

11.1. programan kode osoa dago oharrez lagunduta. Mesedez, prestatu datuak (argazki batzuk karpeta batean, fitxategi bat logo batekin edo QR kode batekin, eta emaitza uzteko karpeta huts bat), gero probatu programa eta, azkenik, kodea irakurri eta ulertzen saiatu.

Argazkien tamaina minimoa eta logoa txertatzeko tokia konstanteen bidez adierazi dira. Logoaren tamaina erdira jaisten da zabaleraz zein altueraz.

# argazkiak fitxategi-sisteman zehar bilatu, logoa jarri eta gorde
# oinarria: https://automatetheboringstuff.com/chapter17/

# 3 parametro: bilatzeko karpeta, logoa duen fitx. eta emaitzak uzteko karpeta
# exekutatzeko: python3 p12_6_irudi_manip.py IRUDI logo.png EMAITZA

import sys
import os
import shutil		# shel utils - os-ko batzuk errazago
from PIL import Image

erroa = "argazkiak0"		# argazkien bilaketarako katalogoa
logof = "logo.png"		# logoaren fitxategia
helb = "argazkiak1"		# emaitzak uzteko katalogoa

ZABMIN = ALTMIN = 150	# Zabalera eta altuera minimoa
TXERKOORD = (0,0)  	# logoa txertatzeko koordenadak

# programa nagusia
ArgazkiKop = 0
IaArgazkiKop = 0
EzArgazkiKop = 0

# logoa-ren fitxategia ireki eta dimentsioak
logoa = Image.open(sst_home + logof)
zab, alt = logoa.size
logotxikia = logoa.resize((int(zab/2),int(alt/2)))
print("Karpeta honetako argazkiak landu:\n", sst_home + erroa)

for karp, azpik, fitxategiak in os.walk(sst_home + erroa):
    for fitx in fitxategiak:
        fitxabs = os.path.join(karp, fitx)
        # egiaztatu luzapena .png or .jpg.
        fitxoin, luzap = os.path.splitext(fitx)
        if luzap != ".png" and luzap != ".jpg":
            # ez da argazkia
            EzArgazkiKop += 1
            continue    # hurrengo fitxategira (else ez jartzeko)

        # irudia ireki eta dimentsioak lortu
        irudia = Image.open(fitxabs)
        zab, alt = irudia.size
        # dimentsioak gainditzen direla ziurtatu
        if zab>ZABMIN and alt>ALTMIN:
            # nahikoa handia, argazkia
            ArgazkiKop += 1
            print("ARG", fitxabs, fitx)
            # fitxategia kopiatu
            irudia.paste(logotxikia, TXERKOORD)
            irudia.save(sst_home + helb + '/' + 'logo_' + fitx)   # helburuko katalogoan: 'logo_'izen
        else:
            # txikiegia da
            IaArgazkiKop += 1
            print("IA", fitxabs, fitx)

print("KOPURUAK - Argazkiak:", ArgazkiKop, "Ia-argazkiak:", IaArgazkiKop,
         "Ez-argazkiak:", EzArgazkiKop)
  • Exekuzioaren emaitza hau da:
Karpeta honetako argazkiak landu:
 drive/My Drive/Colab Notebooks/Python_UEU_20/kodea_izen_luzeak/kap11_argazkiak_jokoak/argazkiak0
ARG drive/My Drive/Colab Notebooks/Python_UEU_20/kodea_izen_luzeak/kap11_argazkiak_jokoak/argazkiak0/Arrosa_bihotza.png Arrosa_bihotza.png
ARG drive/My Drive/Colab Notebooks/Python_UEU_20/kodea_izen_luzeak/kap11_argazkiak_jokoak/argazkiak0/AlzheimerUEU_LizasoAizpurua.png AlzheimerUEU_LizasoAizpurua.png
KOPURUAK - Argazkiak: 2 Ia-argazkiak: 0 Ez-argazkiak: 0
from IPython.display import Image

Eta gainera argazkiak0 karpetan zeuden argazkiekin beste horrenbeste argazki sortu dira argazkiak1 karpetan goian ezkerrean logo txiki bat gehituta. alt text Image('drive/My Drive/Colab Notebooks/Python_UEU_20/kodea_izen_luzeak/kap11_argazkiak_jokoak/argazkiak0/Arrosa_bihotza.png')

from IPython.display import Image
Image('ARG drive/My Drive/Colab Notebooks/Python_UEU_20/kodea_izen_luzeak/kap11_argazkiak_jokoak/argazkiak0/Arrosa_bihotza.png Arrosa_bihotza.png')

Kodean ikusten denez Image objektua erabiltzen da argazkia eta logoa lantzeko. Image objektuko open metodoarekin irekitzen dira fitxategi horiek. Metodo horrek itzultzen duen objektua gero beste hainbat metodorekin aplikatu ahal izango dugu: size tamaina lortzeko, resize tamaina aldatzeko, paste beste argazki edo irudi bat itsasteko eta save kopia bat gordetzeko.

Karpetaren barruko fitxategietara iristeko os.walk metodoa erabili da (kontuz! hirukoteak itzultzen ditu: karpetak, azpikarpetak eta fitxategiak). Lortutako fitxategietan izen osoak lortzen dira join metodoaren bitartez, baina baita luzapena eta oina splitext metodoaren bidez ere.

11.1.3. Proposatutako hobekuntzak

[aldatu]

1) 11.1. programan honako hobekuntza hauek egin behar dira: tamaina minimo eta maximoa parametro gisa jaso behar ditu eta logoa goi-ezkerrean jarri beharrean behe-eskuinean jarri behar da.

2) Logoa gehitu beharrean, testu bat gehitu nahi da. Beste aukera da ur-marka (watermark) bat jartzea. Webguneen URLak konstante moduan definituta daude zerrenda batean, baina hitza parametro gisa sartuko dugu.

11.2. JOKOAK

[aldatu]

Jokoak algoritmika ikasteko zein lantzeko oso interesgarriak dira, baina konplexutasun handiegia izan ohi dute honelako liburu baterako, interfazea oso garrantzitsua delako, grafiko edo animazioen bidez eraiki behar izaten delako. Horrez gain, jokoak programatzeko modua ere askotan desberdina izaten da, gertaerei orientatutako metodologia erabili behar delako. Horrelakoetan programa nagusian bertan zailtasun handirik ez da egoten, une oro esna egongo diren hainbat funtzio/metodo martxan jarri baizik ez da egiten, gehienak gertaerei orientatuak direnak. Tekla bat sakatzea edo askatzea, denbora-tarte bat igarotzea... horrelakoak izaten dira ohiko gertaerak.

Bi joko landuko ditugu, bat oso interfaze sinplea duena eta bestea interfaze konplexuago batekin (liburutegi bat erabiliz).

11.2.1. Hiru lerroan jokoa (lehen hurbilpena)

[aldatu]

Joko hau oso ezaguna da eta oso sinplea. Hala ere programazioa ez da ebidentea. 3x3 taula batean bi jokalari saiatzen dira 3ko lerro bat osatzen (errenkada bat, zutabe bat edo diagonal bat). Lehen jokalariaren aukerak X sinboloarekin markatzen dira eta bigarrenarenak O sinboloarekin.

Programaren elementu nagusia partidaren egoera, taularen egoera irudikatzen duen datu-egitura izango da. 3 azpizerrenda (errenkadak) dituen zerrenda bat. Azpizerrenda bakoitzean errenkada horretako hiru osagaiak izango dira. Osagaien balioak hiru egoera islatzeko gai izan behar du: hutsik egotea, jokalari baten marka eta bestearena. Gure programan hutsik egotea -1 zenbakiarekin adieraziko da, X jokalariaren marka 1 zenbakiarekin, eta O jokalariarena 0 zenbakiarekin. Hasierako egoeran balio guztiak -1 izango dira.

Bestalde, 9 gelaxka (3x3) horiek izendatzeko modu bat behar da, gure aukera 1-9 tartea erabiltzea izan da.

Lehen hurbilpenean bi jokalari aurreikusten dira, baina biak teklatu beretik arituko dira. Nolabait jokalaria bere buruaren aurka arituko da. Programa, beraz, txandak banatuko ditu eta irabazlea erabakiko. Hau izango da jokalariari agertuko zaion lehen mezua:

Hauek dira erabili behar dituzun gelaxken zenbakiak:

1 | 2 | 3
-----------
4 | 5 | 6
-----------
7 | 8 | 9
-----------
Hasiera!
  |   | 
----------
  |   |
----------
  |   |
----------
txanda: 1
Programaren d

Programaren diseinuan funtzio nagusi hauek aurreikusi dira:

  • taularen hasierako egoera inprimatzea, gelaxken zenbakiekin: idatzi_taula_has()
  • taularen egoera irudikatzea: idatzi_taula(t)
  • jokalari bati dagokion jokaldia irakurtzea: irakurri_jok(jok). Gelaxkaren zenbakia zuzena dela (1-9) eta libre dagoela egiaztatuko du
  • baten batek irabazi duen ala ez aztertzea: irabazlea(t)

11.2. programan kode osoa dago. Mesedez, probatu, kodea irakurri eta ulertzen saiatu.

11.2. programa. Hiru lerroan, 1. bertsioa:

# "hirurak lerroan" jokuaren inplementazioa

# BI JOKALARIAK TEKLATU BERETIK
# PROGRAMA: EPAILE LANA

# jatorrizko ideiak:
#	http://code.activestate.com/recipes/578816-the-game-of-tic-tac-toe-in-python/
# 	https://inventwithpython.com/chapter10.html
#	http://www.linuxhispano.net/2013/09/03/tres-en-raya-python/

# taula idatzi gelaxka bakoitzean dagokion zenbakiarekin
def idatzi_taula_has():
	print ("Hauek dira erabili behar dituzun gelaxken zenbakiak:")
	print()
	# 3 errenkada
	for i in range(3):
		print (" ", end="")
		# 3 zutabe
		for j in range(3):
			# balioa: indizearena+1
			print (i*3+j+1, end="")
			if j != 2:
				# bereizgarria
				print (" | ", end="")
		# lerro-tartea
		print("\n------------")
	print()

# partidaren egoera idatzi.
# t- zerrenda dago egoera: -1 hutsik, 1 - X, 0 - O
def idatzi_taula(t):
	print()
	# 3 errenkada
	for i in range(3):
		print (" ", end="")
		# 3 zutabe
		for j in range(3):
			if t[i*3+j] == 1:
				print ('X', end="")
			elif t[i*3+j] == 0:
				print ('O', end="")
			else:
				print (' ', end="")
			# bereizgarria
			if j != 2:
				print (" | ", end="")
		# lerro-tartea
		print("\n------------")
	print()

def irakurri_jok(jok):
	zuzen = False
	while not zuzen:
		try:
			pos = int(input(jok + "- aukeratu gelaxka: " + "(1-9)? "))
			if pos >= 1 and pos <= 9:
				return pos-1
			else:
				print ("Aukera desegokia! Beste bat?\n")
				idatzi_taula_has()
		# badaezpada: adib. tekleatze okerra
		except Exception as e:
			print (user + " aukera desegokia! Beste bat?\n")

def irabazlea(t):
	konbin_guztiak = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]]
	for k in konbin_guztiak:
		if t[k[0]-1] == t[k[1]-1] and t[k[1]-1] == t[k[2]-1]:
			return t[k[0]-1]
	return -1

def idatzi_buk(t,m):
	idatzi_taula(t)
	print(m)
	print("\nAgur!\n")


# programa nagusia
# hasiera, jokalariak txandakatzea eta irabazlea erabakitzea

idatzi_taula_has()

taula = []
for i in range(9):
	taula.append(-1)

print ("Hasiera!")

buk = False
txanda = 0

while not buk:

	idatzi_taula(taula)
	print ("txanda: " + str(txanda+1))
	if txanda % 2 == 0:
		jokalaria = 'X'
	else:
		jokalaria = 'O'

	# sarrera irakurri
	p = irakurri_jok(jokalaria)
	while taula[p] != -1:
		print ("Aukera desegokia! Gelaxka hartuta. Beste bat?\n")
		p = irakurri_jok(jokalaria)
	if jokalaria == 'X':
		taula[p] = 1
	else:
		taula[p] = 0

	# aurreratu jokaldia eta testeatu bukaera
	txanda += 1
	if txanda > 4:
		irab_jok = irabazlea(taula)
		if irab_jok != -1:
			if irab_jok ==1:
				mezua = "Irabazlea: " + "X"
			else:
				mezua = "Irabazlea: " + "O"
			idatzi_buk(taula,mezua)
			buk=True
		elif txanda == 9:
			idatzi_buk(taula,"Irabazlerik ez!")
			buk=True
  1. Ariketa1: konbinazio irabazleak programaz (lerroak, zutabeak eta diagonalak).
  2. Ariketa2: berdinketara eramaten dituzten konbinazioak aurretik detektatzea
Adib.
#  X | O |
# ------------
#  O | O | X
# ------------
#  X | X | O
# ------------


Hauek dira erabili behar dituzun gelaxken zenbakiak:

 1 | 2 | 3
------------
 4 | 5 | 6
------------
 7 | 8 | 9
------------

Hasiera!

   |   |  
------------
   |   |  
------------
   |   |  
------------

txanda: 1
X- aukeratu gelaxka: (1-9)? 5

   |   |  
------------
   | X |  
------------
   |   |  
------------

txanda: 2
O- aukeratu gelaxka: (1-9)? 1

 O |   |  
------------
   | X |  
------------
   |   |  
------------

txanda: 3
X- aukeratu gelaxka: (1-9)? 3

 O |   | X
------------
   | X |  
------------
   |   |  
------------

txanda: 4
O- aukeratu gelaxka: (1-9)? 7

 O |   | X
------------
   | X |  
------------
 O |   |  
------------

txanda: 5
X- aukeratu gelaxka: (1-9)? 4

 O |   | X
------------
 X | X |  
------------
 O |   |  
------------

txanda: 6
O- aukeratu gelaxka: (1-9)? 6

 O |   | X
------------
 X | X | O
------------
 O |   |  
------------

txanda: 7
X- aukeratu gelaxka: (1-9)? 8

 O |   | X
------------
 X | X | O
------------
 O | X |  
------------

txanda: 8
O- aukeratu gelaxka: (1-9)? 2

 O | O | X
------------
 X | X | O
------------
 O | X |  
------------

txanda: 9
X- aukeratu gelaxka: (1-9)? 9

 O | O | X
------------
 X | X | O
------------
 O | X | X
------------

Irabazlerik ez!

Agur!

11.2.2. Hiru lerroan jokoa (bigarren hurbilpena)

[aldatu]

Kasu honetan programa bera, antolatzaile/epailea izateaz gain, jokalaria izango da. Horretarako programa nagusia aldatu da, txanda bakoitietan jokalariari bere mugimendua eskatuko dio eta bikoitietan makinak bere jokaldia asmatuko du.

11.2. programa. Hiru lerroan, 2. bertsioaren programa nagusia:

# "hirurak lerroan" jokuaren inplementazioa (B)

# BI JOKALARIAK TEKLATU BERETIK
# PROGRAMA: x JOKALARIA + EPAILE LANA

# jatorrizko ideiak:
#	http://code.activestate.com/recipes/578816-the-game-of-tic-tac-toe-in-python/
# 	https://inventwithpython.com/chapter10.html
#	http://www.linuxhispano.net/2013/09/03/tres-en-raya-python/

# taula idatzi gelaxka bakoitzean dagokion zenbakiarekin
def idatzi_taula_has():
	print ("Hauek dira erabili behar dituzun gelaxken zenbakiak:")
	print()
	# 3 errenkada
	for i in range(3):
		print (" ", end="")
		# 3 zutabe
		for j in range(3):
			# balioa: indizearena+1
			print (i*3+j+1, end="")
			# bereizgarria
			if j != 2:
				print (" | ", end="")
		# lerro-tartea
		print("\n------------")
	print()

# partidaren egoera idatzi.
# t- zerrenda dago egoera: -1 hutsik, 1 - X, 0 - O
def idatzi_taula(t):
	print()
	# 3 errenkada
	for i in range(3):
		print (" ", end="")
		# 3 zutabe
		for j in range(3):
			if t[i*3+j] == 1:
				print ('X', end="")
			elif t[i*3+j] == 0:
				print ('O', end="")
			else:
				print (' ', end="")
			# bereizgarria
			if j != 2:
				print (" | ", end="")
		# lerro-tartea
		print("\n------------")
	print()

def irakurri_jok(jok):
	zuzen = False
	while not zuzen:
		try:
			pos = int(input(jok + "- aukeratu gelaxka: " + "(1-9)? "))
			if pos >= 1 and pos <= 9:
				return pos-1
			else:
				print ("Aukera desegokia! Beste bat?\n")
				idatzi_taula_has()
		# badaezpada: adib. tekleatze okerra
		except Exception as e:
			print (user + " aukera desegokia! Beste bat?\n")

def irabazlea(t):
	konbin_guztiak = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]]
	for k in konbin_guztiak:
		if t[k[0]-1] == t[k[1]-1] and t[k[1]-1] == t[k[2]-1]:
			return t[k[0]-1]
	return -1

def idatzi_buk(t,m):
	idatzi_taula(t)
	print(m)
	print("\nAgur!\n")

# irabazlea-n oinarrituta
def galzorian(t):
	konbin_guztiak = [[1,2,3],[4,5,6],[7,8,9],[1,4,7],[2,5,8],[3,6,9],[1,5,9],[3,5,7]]
	for k in konbin_guztiak:
		arrisku=0; pos=0;
		for j in range(3):
			if t[k[j]-1] == 1:
				arrisku += 1	# zenbat hiruen artean
			elif t[k[j]-1] == -1:
				pos=k[j]	# lerro berean libre dagoena
		if arrisku == 2:	# jokalariak 2 hartuta baditu
			return pos-1	# libre dagoena
	return -1

def bilatu_pos(t,z):
	for pos in z:
		if t[pos-1]==-1:
			return pos-1
	return -1

# lehen estrategia: 1) zentroaren bila, 2) saihestu besteak irabaztea, 3) erpinetara, 4) erdigunetara
def hurrengo_jok(t):
	ZENTR=5
	ERPINAK=[1,3,7,9]
	ERDIGUNEAK=[2,4,6,8]
	if t[ZENTR-1]==-1:
		return ZENTR-1
	else:
		p=galzorian(t)
		if(p!=-1):
			return p
		p=bilatu_pos(t,ERPINAK)
		if(p!=-1):
			return p
		p=bilatu_pos(t,ERDIGUNEAK)
		return(p)


# programa nagusia
# makinaren aurka
# jokalaria (X, 1) hasten da
# makinak (O, 0) ez du galduko (baina galtzea aurreikusita dago kodean)

idatzi_taula_has()

taula = []
for i in range(9):
	taula.append(-1)

print ("Hasi zu!")

buk = False
txanda = 0

while not buk:
	idatzi_taula(taula)
	if txanda % 2 == 0:	#jokalariaren txanda
		jokalaria = 'X'
		print ("txanda: " + str(txanda+1))
		p = irakurri_jok(jokalaria)
		while taula[p] != -1:
			print ("Aukera desegokia! Gelaxka hartuta. Beste bat?\n")
			p = irakurri_jok(jokalaria)
		taula[p] = 1
	else:			#makinaren txanda
		jokalaria = 'O'
		p = hurrengo_jok(taula)
		taula[p] = 0

	# aurreratu jokaldia eta testeatu bukaera
	txanda += 1
	if txanda > 4:
		irab_jok = irabazlea(taula)
		if irab_jok != -1:
			if irab_jok == 1:
				mezua = "Irabazi duzu! Zorionak!"
			else:
				mezua = "Etxea irabazle! Hurrengoan agian?"
			idatzi_buk(taula,mezua)
			buk=True
		elif txanda == 9:
			idatzi_buk(taula,"Irabazlerik ez!")
			buk=True

Hau da programa horren exekuzio bat:

Hauek dira erabili behar dituzun gelaxken zenbakiak:

 1 | 2 | 3
------------
 4 | 5 | 6
------------
 7 | 8 | 9
------------

Hasi zu!

   |   |  
------------
   |   |  
------------
   |   |  
------------

txanda: 1
X- aukeratu gelaxka: (1-9)? 5

   |   |  
------------
   | X |  
------------
   |   |  
------------


 O |   |  
------------
   | X |  
------------
   |   |  
------------

txanda: 3
X- aukeratu gelaxka: (1-9)? 3

 O |   | X
------------
   | X |  
------------
   |   |  
------------


 O |   | X
------------
   | X |  
------------
 O |   |  
------------

txanda: 5
X- aukeratu gelaxka: (1-9)? 4

 O |   | X
------------
 X | X |  
------------
 O |   |  
------------


 O |   | X
------------
 X | X | O
------------
 O |   |  
------------

txanda: 7
X- aukeratu gelaxka: (1-9)? 8

 O |   | X
------------
 X | X | O
------------
 O | X |  
------------


 O |   | X
------------
 X | X | O
------------
 O | X | O
------------

txanda: 9
X- aukeratu gelaxka: (1-9)? 2

 O | X | X
------------
 X | X | O
------------
 O | X | O
------------

Irabazi duzu! Zorionak!

Agur!

Makinak zer jokaldi egin behar duen zehaztuko duen hurrengo_jok funtzioa definituta dagoela suposatu da programa nagusi horretan. Beheko kodean ikus daitekeenez inplementazio sinple bat egin da, lau urrats posible hauek kontuan hartzen dira:

  • Zentroa libre badago, horixe aukeratu,
  • bestela saihestu beste jokalariak irabaztea,
  • arrisku hori ez badago, erpinetako gelaxka libre bat eskuratu horrelakorik egoenz gero,
  • bestela libre dagoen beste edozeinetan jarri (kanpoko marra bateko erdigunean).

11.3. programaren hurrengo_jok() funtzioa:

def hurrengo_jok(t):
ZENTR=5
ERPINAK=[1,3,7,9]
ERDIGUNEAK=[2,4,6,8]
if t[ZENTR-1]==-1:
		 return ZENTR-1
else:
		 p=galzorian(t)
		 if(p!=-1):
			 return p
		 p=bilatu_pos(t,ERPINAK)
		 if(p!=-1):
			 return p
		 p=bilatu_pos(t,ERDIGUNEAK)
		 return(p)http://www.ueu.eus ......

11.2.3. Mahai-tenisa (ping-pong)

[aldatu]

Orain interfazea konplexuagoa izango da. Ping-pong bideo-joko klasikoan teklatutik bi jokalariak kontrolatuko ditu erabiltzaileak, ezkerrez “w” pala igotzeko eta “s” jaisteko, eta eskuinez gorako eta beherako geziei dagozkien teklak erabiliz. Programa pilotaren eta palen mugimenduaz zein hormetako erreboteez arduratuko da, baita marrazketaz eta tantoak kontatzeaz eta islatzeaz.

Kasu honetan interfaze grafiko sofistikatuago bat erabiliko dugu eta gauzak erraztearren, Internet konexioa baldin baduzu, codeskulptor.org gunearen aukerak erabiliko ditugu. Aukeren artean hauek dira azpimarragarrienak:

  • simplegui (Simple GUI) modulua erabil dezakegu interfazea programatzeko, besterik instalatzeko beharrik gabe. Oso interfaze sinplea da oso metodo ahaltsuak dituelako (luze joko luke hemen metodo guztien zehaztasunak emateak)
  • exekuzioa nabigatzailean azalduko zaigu

11.4. programan dago proposatzen dugun soluzioa (Eskerrak UPV/EHUko irakaslea den Jesus Ibañezi bere soluzioa gurekin partekatzeagatik), baita Interneteko helbide honetan ere: http://www.codeskulptor.org/#user41_vKzuepVh6F_27.py.

Gertaerei orientatuta dago programa, eta oharren bidez nahiko ondo azalduta dagoen arren, komenigarria da bukaeran dagoen kodea (programa nagusia) azaltzea. Ondoko urratsak ematen dira:

  • frame bat (irudia) sortzea simplegui-k duen metodoaren bidez:
frame = simplegui.create_frame(Pong, ZABALERA, ALTUERA)
  • eguneraketari dagokion funtzioa deklaratzea, kodearen atal nagusia dena, frame objektuari dagokion metodoarekin:
frame.set_draw_handler(draw)
  • tekla sakatzeari eta askatzeari dagozkien funtzioak deklaratzea, dagozkien metodoen bidez:
frame.set_keydown_handler(keydown) frame.set_keyup_handler(keyup)
  • botoi lagungarri bat gehitzea jokoa berriro berrabiatzeko
frame.add_button(Restart, init, 100)
  • programa martxan jartzea: aldagai globalen balioa hasieratzea (init), hasierako marrazketa eta funtzioen aktibazioa (frame.start) eta pilota mugitzen hastea (pilota_hasi).

Kodea luzea denez, lehen probatu eta gero arretaz irakurtzea gomendatzen da. Horretarako onena da codeskulptor.org gunean fitxategi huts batetik abiatzea, kodea kopiatzea (11.4. programa) eta probatzea.

11.4. programa. Mahai-tenisa simplegui bidez:

# Jesus Ibañezen bertsiotik eratorria

import simplegui
import random

# Hasieraketa

ZABALERA = 600		#pantailaren dimentsioa
ALTUERA = 400
ERRADIOA = 10		# pilotaren erradioa

PALA_ZAB = 8		# palaren dimentsioak
PALA_ALT = 80
PALA_ZAB_ERDIA = PALA_ZAB / 2
PALA_ALT_ERDIA = PALA_ALT / 2
pala_has_abiadura = 7		# pala mugitzeko hasierako abiadura

# Partida irabazteko tanto kopurua
tanto_kop = 5

# pilota azaltzeko funtzioa (eskuin/ezker)
def pilota_hasi(eskuina):	# hasieran edo tantoa bukatutakoan
# parametroa boolearra: egiazkoa-eskuinerantza, bestela ezkerrerantz
    global pilota_pos, pilota_abiad
    pilota_pos = [ZABALERA/2, ALTUERA/2]	# pilota erditik irteten da
    # abiadura zoriz
    pilota_abiad = [random.randrange(120, 240)/60,
                    -random.randrange(60, 180)/60]
    if not eskuina:			# ezkerrarantz
        pilota_abiad[0] *= -1

# jokoaren hasiera eta bukaera
def init():
    # aldagai globalak
    global bukaera, pala1_pos, pala2_pos, pala1_abiad, pala2_abiad
    global MEZU1, MEZU2, tantoak1, tantoak2
    bukaera = False
    MEZU1 = MEZU2 = ""
    tantoak1 = tantoak2 = 0
    # palak hasieran zentratuta. bi hasieraketa batera
    pala1_pos = pala2_pos = ALTUERA / 2
    pala1_abiad = pala2_abiad = 0

def joko_buk(irab):
    # bukaera ezarri eta bukaerako mezua
    global bukaera, MEZU1, MEZU2
    bukaera = True
    MEZU1 = "AMAITU DA"
    MEZU2 = str(irab) + ". jokalaria irabazle!"

# gertaeren kudeatzailea: gertaerek idazketa dakarte
# programaren mamia
def draw(c):	# aldagai globalak
    global tantoak1, tantoak2, pala1_pos, pala2_pos, pilota_pos, pilota_abiad

    # palaren posizio bertikala eguneratzea, pantailan mantenduta
    if not bukaera:
        pala1_pos += pala1_abiad
        pala1_pos = max(pala1_pos, PALA_ALT_ERDIA)
        pala1_pos = min(pala1_pos, ALTUERA-PALA_ALT_ERDIA)
        pala2_pos += pala2_abiad
        pala2_pos = max(pala2_pos, PALA_ALT_ERDIA)
        pala2_pos = min(pala2_pos, ALTUERA-PALA_ALT_ERDIA)

    # draw mid line and gutters
    c.draw_line([ZABALERA / 2, 0],[ZABALERA / 2, ALTUERA], 1, "White")
    c.draw_line([PALA_ZAB, 0],[PALA_ZAB, ALTUERA], 1, "White")
    c.draw_line([ZABALERA - PALA_ZAB, 0],[ZABALERA - PALA_ZAB, ALTUERA], 1, "White")

    # palak marraztea
    c.draw_line((PALA_ZAB_ERDIA, pala1_pos-PALA_ALT_ERDIA),
                (PALA_ZAB_ERDIA, pala1_pos+PALA_ALT_ERDIA), PALA_ZAB, "White")
    c.draw_line((ZABALERA-PALA_ZAB_ERDIA, pala2_pos-PALA_ALT_ERDIA),
                (ZABALERA-PALA_ZAB_ERDIA, pala2_pos+PALA_ALT_ERDIA), PALA_ZAB, "White")

    # pilota-ren kokapena eguneratzea eta marraztea: bi koordenadatan
    pilota_pos[0] += pilota_abiad[0]
    pilota_pos[1] += pilota_abiad[1]
    c.draw_circle(pilota_pos, ERRADIOA, 1, "White", "White")

    # pilota ezker-paretara iristen
    if pilota_pos[0] <= ERRADIOA + PALA_ZAB:
        if (pilota_pos[1] >= pala1_pos - PALA_ALT_ERDIA and
            pilota_pos[1] <= pala1_pos + PALA_ALT_ERDIA):
            # Pala pilotari dagokion tokian dago -> abiadura handitzea
            pilota_abiad[0] *= -1.1
        else:
            # puntua 2. jokalariarentzat
            if not bukaera:
                tantoak2 += 1
                if tantoak2 == tanto_kop:
                    joko_buk(2)
            pilota_hasi(True)  		# berriro hasi pilota, erditik

    # pilota eskuin-paretara iristen
    if pilota_pos[0] >= ZABALERA - 1 - ERRADIOA-PALA_ZAB:
        if (pilota_pos[1] >= pala2_pos - PALA_ALT_ERDIA and
            pilota_pos[1] <= pala2_pos + PALA_ALT_ERDIA):
            # Pala pilotari dagokion tokian dago -> abiadura handitzea
            pilota_abiad[0] *= -1.1
        else:
            # puntua 1. jokalariarentzat
            if not bukaera:
                tantoak1 +=1
                if tantoak1 == tanto_kop:
                    joko_buk(1)
            pilota_hasi(False)

    if pilota_pos[1] <= ERRADIOA or pilota_pos[1] >= ALTUERA - 1 - ERRADIOA:
        # pilota jaurti egiten du goian edo behean talka egitean
        pilota_abiad[1] *= -1

    # markagailuaren inprimaketa
    c.draw_text(str(tantoak1), (ZABALERA/4 - 20, 75), 40, "White")
    c.draw_text(str(tantoak2), (3*ZABALERA/4 - 20, 75), 40, "White")

    # mezuaren inprimaketa (beti hutsa, bukaeran izan ezik)
    c.draw_text(MEZU1, (ZABALERA/4, 3*ALTUERA/4), 40, "White")
    c.draw_text(MEZU2, (65+ZABALERA/4, 6*ALTUERA/7), 25, "White")

def keydown(key):
    # tekla sakatzearen eragina: palaren abiadura konstantea
    # 1. jokalaria "w" tekla pala igotzeko eta "s" jaisteko
    # 2. jokalaria gezien teklekin
    global pala1_abiad, pala2_abiad
    if key == simplegui.KEY_MAP["w"]:		# 1. pala gora
        pala1_abiad = -pala_has_abiadura
    elif key == simplegui.KEY_MAP["s"]:		# 1. pala behera
        pala1_abiad = pala_has_abiadura
    elif key == simplegui.KEY_MAP["up"]:	# 2. pala gora
        pala2_abiad = -pala_has_abiadura
    elif key == simplegui.KEY_MAP["down"]:	# 2. pala behera
        pala2_abiad = pala_has_abiadura

def keyup(key):
    # tekla askatzearen eragina: palaren mugimendua geratu egiten da
    global pala1_abiad, pala2_abiad
    if key == simplegui.KEY_MAP["w"] or key == simplegui.KEY_MAP["s"]:
        pala1_abiad = 0
    elif key == simplegui.KEY_MAP["up"] or key == simplegui.KEY_MAP["down"]:
        pala2_abiad = 0

# frame-a (irudia sortzea)
# irudia sortzeko metodoa
frame = simplegui.create_frame("Pong", ZABALERA, ALTUERA)
# eguneraketa
frame.set_draw_handler(draw)
# tekla sakatzean
frame.set_keydown_handler(keydown)
# tekla askatzean
frame.set_keyup_handler(keyup)
# botoi lagungarria
frame.add_button("Restart", init, 100)

# hastea
init()
frame.start()
pilota_hasi(False)

Lokalean (zure ordenagailuan) exekutatu nahi izanez gero, codeskulptor.org gunerako asmatutako simplegui.py instalatu beharko litzateke, baina ez da erraza, hainbat mendekotasun dituelako (pillow, pygame eta matplotlib) eta batzuetan arazoak daudelako Python3-rekin (https://pypi.python.org/pypi/SimpleGUITk http://stackoverflow.com/questions/16387770/how-to-integrate-simplegui-with-python-2-7-and-3-0-shell). Are gehiago codeskulptor.org bera python2.7-rako dago egokituta.

11.2.4. Proposatutako hobekuntzak

[aldatu]

1) 11.1. programaren kodea laburtzeko idatzi_taula_has() eta idatzi_taula(t) funtzioak bateratu funtzio bakar batean.

2) 11.2. programan defini ezazu zerrenden hasieraketa 6. kapituluan azaldutako comprehension ezaugarria baliatuta.

3) 11.3. programa alda ezazu konbinazio irabazleak programak detekta ditzan eta irabazteko baliatu gero. Galzorian egoera detektatu den bezalaxe, Irabazteko zorian egoteko aukera ere detekta dezake programak, eta jokaldi hori baliatu irabazteko. galzorian(t) funtzioan oinarrituta definitzea erraza da.

4) 11.4. programan aldaketak egin: puntu kopurua, pilotaren eta palen tamaina, abiadura...

5) 11.4. programa sinplifikatu behar duzu eta ezkerreko jokalaria kendu. Jokalariaren ordez pareta utzi, eta geratzen den jokalariaren helburua ahalik eta tanto gutxien galtzea izango da. Gero, programa hobetzeko hainbat gehikuntza egin daitezke: denbora kontrolatu eta azaldu, pilotaren abiadura handitzen joan...

6) 5. ariketa aldatu alde bakar batean bi jokalari egon daitezen, frontoi batean bi jokalari daudela simulatzeko.

7) [erronka handia] 11.4. programa aldatu behar duzu makinaren aurka jokatzeko. Alde bateko palaren mugimenduak programak berak mugitu beharko ditu. Makinak beti irabaztea lortzen duzunean, gehitu erloju bat eta erronka litzateke denbora-tarte batean partida kopuru bat baino gutxiago galtzea. Hori konbina liteke pilotaren abiadura hautatzeko aukera gehitzearekin.

8) https://inventwithpython.com/pygame/chapter3.html gunetik kopiatuz (gure ariketa-bilduman ere kopia bat dago) proba ezazu memoria-joko hori. Ondo ibil dadin pygame instalatu behar da eta python2.7 erabili. Konplexua da: irudiak daude, sagua erabiltzen da... Saiatu ulertzen eta euskarara ekartzen. Behin ulertuta saia zaitez aldaketak egiten gero; adibidez, irudiak aldatzea.