2023(e)ko martxoaren 27(a), astelehena

10. astea | itsas-bataila (II)














Itsas-bataila



Itsas-batailaren jokoa programatuko dugu. Bi dimentsioatako 6x6 taula batean gertatuko dira ekintza guztiak, taularen errenkadak izendatzeko zenbaki osoak erabiliko dira (1-etik 6-ra), eta taularen zutabeak izendatzeko karaktereak erabiliko dira (A-tik F-ra)






Ordenadoreak etsaien armada kokatuko du 6x6 itsasoan, eta etsaien armada hori hondoratu beharko dugu gehienez 19 jaurtiketa erabiliz. Etsaien armada sei itsasontziz osaturik dago:




  • 2 korazatu, armadako itsasontzi handienak dira (bakoitzak 3 zati)

  • 3 destruktore, armadako itsasontzi ertainak dira (bakoitzak 2 zati) 

  • 1 itsaspeko, armadako itsasontzi txikiena da (1 zati)



Hondoratu behar dugun etsaien armada 6x6 itsasoan kokatzeko, bi dimentsiotako array bat erabiliko dugu, hots, karaktereen array bat. Korazatua adierazteko K idatziko dugu, destruktorea adierazteko D idatziko dugu, itsaspekoa adierazteko P idatziko dugu, ura adierazteko, u idatziko dugu, eta, gainerako toki guztietan X idatzirik egongo da. Adibidez:











itsas_w unitatea



Lehendik programaturik dagoen unitate bat erabiliko dugu, itsas_w izeneko unitatea hain zuzen ere. Unitate horren iturburu-programa ez daukagu, baina bere interfazea ezagutzen dugu. Hori dela eta, guk idatziko dugun programan itsas_w unitatearen ondoko datu-mota erabil dezakegu eta ondoko azpiprogramen deiak egin ditzakegu: 



unit itsas_w ; 

interface (* ----------------------------- interfazearen hasiera ----- *)

type tacItsasoa = array[1..6, 'A'..'F'] of char ;
procedure EtsaienArmadaHasieratu ;
procedure EtsaienArmadaKokatu ;
procedure EtsaienArmadaErakutsi ;
function fncSuEgin(iErrenkada: integer;
cZutabea: char): char ; { K, D, P edo X }
procedure EtsaienArmadaGuztiakKokatu ;

(* ----------------------------- interfazearen amaiera ----- *)

implementation (* ------------------------- inplementazioaren hasiera ----- *)

...

end. (* --------- inplementazioaren eta unitatearen amaiera ----- *) 




Interfazean adierazten dira unitateak bezero-programarekin partekatuko dituen elementuak: konstanteak, datu-motak, funtzioak, prozedurak eta abar. Adibide honetan, datu-mota bat partekatzeaz gain funtzio bat eta lau prozedura partekatzen dira.



Interfazearen datu-motaren azalpena:




  • tacItsasoa datu-motak itsasoa ereduztatzen du, 6x6 itsaso zati horretan burutuko da bataila. Errenkadak izendatzeko zenbakizko indizeak erabiliko dira (1-etik 6-ra) eta zutabeak izendatzeko letrak erabiliko dira (A-tik F-ra)



Interfazearen bost azpiprogramen azalpenak:




  • fncSuEgin funtzioak 6x6 arrayaren koordenatuak hartuko ditu eta posizio horren karakterea itzuliko du (K, D, P edo X)


  • EtsaienArmadaHasieratu prozedurak 6x6 itsasoan X markak idatziko ditu


  • EtsaienArmadaKokatu prozedurak 6x6 itsasoan K, D eta P markak idatziko ditu


  • EtsaienArmadaErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du. Honi esker gure programa-bezerotik posible zaigu jakitea etsaien ontziteria non dagoen, baina prozedura honi dei egiten badiogu itsas-bataila galdu dugulako izango da


  • EtsaienArmadaGuztiakErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du, guztira 16 kokapen desberdin definitu dira itsas_w unitatean





Bost azpiprograma horiek gure programatik aktiba ditzakegu. Horretarako, uses klausulari esker itsas_w unitatea behar-beharrekoa zaigula adieraziko dugu gure iturburu-programaren hasieran:



program ItsasBatailak_w ;

uses
crt, itsas_w ;
const (* 2 korazatu, 3 destruktore eta 1 itsaspeko *)
ARMADA_OSOA = 13 ; (* 2x3 + 3x2 + 1 = 13 *)
JAURTIK_MAX = 19 ;
type
tsJaurtiketa = string[2] ;



Hori dela eta, gure bezero-programak EtsaienArmadaKokatu prozedurari deia egitean etsaien armadaren kokapen zehatz bat gertatuko da (16 kokapen posibleetatik bat) eta jokoa hasi ahalko da. Jakin badakigu etsaien armadak 6 ontzi izango dituela eta bi ontziren artean beti ura dagoela; esate baterako, ondoko irudian erakusten den kokapena ez da itsas_w unitateak emandakoa kokapena desegokia delako:



Erroreak daudelako, goiko irudia ez du eman EtsaienArmadaKokatu prozedurak









ItsasBatailak_w.pas bezero-programa



ItsasBatailak_w.pas bezero-programak itsas_w eta crt unitateak beharko dituela dakigu. Baina, zer gertatuko litzateke  bezero-programak deklaratu eta garatuko balu unitatearen interfazeko funtzioa edo prozeduraren bat? Honako hau galdetzen da: EtsaienArmadaKokatu prozedura unitatean garaturik dago (bezero-programaren erabiltzaileak jakin ez dezan etsaien ontziteria non dagoen), bezero-programak EtsaienArmadaKokatu prozedura berri bat idatz dezake? Bai idatz dezake, errorerik ez dago ez sintaxian ez exekuzioan.



Aurreko erantzunak beste galdera bat sorarazten du: baldin eta EtsaienArmadaKokatu bi prozedura badaude (bat unitatekoa eta bestea bezero-programakoa), zein aktibatuko da bezero-programa exekutatzean? Bezero-programakoa, hots, bezero-programako EtsaienArmadaKokatu prozedura piztuko da eta unitateko EtsaienArmadaKokatu prozedura ez balego bezala da. Ondorioz, unitatean garaturik dagoen zerbait bezero-programan garatzen bada, azken honek "estaltzen" du unitatekoa.

ItsasBatailak_w.pas bezero-programak itsas_w eta crt unitateak beharko ditu eta bere programa nagusia ondoko hau izan daiteke:



{ -----------------------Programa Nagusia-------------------------- }
var
iErrenkada, iJaurtiKont, iOntziZatiak, iUrKont: integer ;
cZutabea: char ;
acItsasoarenEgoera: tacItsasoa ;
aboJaurtiketaErrepikaturik: tboJaurtiketenHistoria ;
sJaurtiketa: tsJaurtiketa ;
boJaurtiketaEgokia, boErrepikatuGabea: boolean ;
cEmaitza: char ;

begin
clrscr ;
writeln ;

writeln('///////////////////////////////////////////////////////////////////') ;
writeln ;
writeln('Garaile ateratzeko, gehienez ', JAURTIK_MAX, ' jaurtiketa dituzu') ;
writeln ;

EtsaienArmadaHasieratu ; (* unitatean garaturik *)
EtsaienArmadaKokatu ; (* unitatean garaturik *)

JaurtiketenHistoriaHasi(aboJaurtiketaErrepikaturik) ; (* hasieran denak "FALSE" *)
ItsasoarenEgoeraHasieratu(acItsasoarenEgoera) ; (* hasieran denak "X" *)
ItsasoaErakutsi(acItsasoarenEgoera) ;

writeln ;
writeln('ARMISTIZIOA:') ;
writeln('Amore eman eta bataila galdutzat jotzen baduzu, etsaien armada ikus dezakezu.') ;
writeln('Garaitu zaituen etsaien armadaren kokapena ikusi nahi duzu, "AR" erantzun. ') ;
writeln ;

iUrKont := 0 ;
iOntziZatiak := 0 ;
iJaurtiKont := 0 ;
repeat
if iUrKont >= 6 then
begin
TextColor(LightCyan) ;
writeln('Jaurtiketa okerrak askotan egin dituzu, armistizioa eskatzerik daukazu!!!') ;
TextColor(White) ;
end ;

iJaurtiKont := iJaurtiKont + 1 ;
boJaurtiketaEgokia := FALSE ;
repeat
repeat
write(iJaurtiKont:3, '. jaurtiketa egin (adibidez 3C koordenatuak, armistizioa eskatzeko "AR"): ') ;
readln(sJaurtiketa) ;
sJaurtiketa := upcase(sJaurtiketa) ;
boJaurtiketaEgokia := fnboJaurtiketaAztertu(sJaurtiketa) ;
until boJaurtiketaEgokia ;

boErrepikatuGabea := fnboErrepikatuGabea(sJaurtiketa, aboJaurtiketaErrepikaturik) ;
until boErrepikatuGabea ;

if sJaurtiketa <> 'AR' then
begin
val(sJaurtiketa[1], iErrenkada) ;
//writeln('iErrenkada = ', iErrenkada) ;
cZutabea := sJaurtiketa[2] ;

cEmaitza := fncSuEgin(iErrenkada, cZutabea) ; (* unitatean garaturik *)

case cEmaitza of { K, D, P edo X }
'K': begin
writeln(iErrenkada:3, cZutabea, ' ---> K, korazatua') ;
iOntziZatiak := iOntziZatiak + 1 ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'K' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
end ;
'D': begin
writeln(iErrenkada:3, cZutabea, ' ---> D, destruktorea') ;
iOntziZatiak := iOntziZatiak + 1 ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'D' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
end ;
'P': begin
writeln(iErrenkada:3, cZutabea, ' ---> P, itsaspekoa') ;
iOntziZatiak := iOntziZatiak + 1 ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'P' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
end ;
'X': begin
writeln(iErrenkada:3, cZutabea, ' ---> URA') ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'u' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
iUrKont := iUrKont + 1 ;
end ;
end ;

writeln((JAURTIK_MAX-iJaurtiKont):4, ' jaurtiketa geratzen d(ir)a');
writeln ;
ItsasoaErakutsi(acItsasoarenEgoera) ;
writeln ;
end ;
until (iOntziZatiak = ARMADA_OSOA) or
(iJaurtiKont = JAURTIK_MAX) or
(sJaurtiketa = 'AR') ;

writeln ;

if sJaurtiketa = 'AR' then
begin
writeln('ARMISTIZIOA, garaile atera diren etsaien ontziteria:') ;
writeln ;
EtsaienArmadaErakutsi ; (* unitatean garaturik *)
end
else
begin
if (iOntziZatiak = ARMADA_OSOA) and (iJaurtiKont <= JAURTIK_MAX) then
begin
TextColor(LightGreen) ;
writeln(iJaurtiKont, ' jaurtiketekin etsaien armada osoa hondoratu duzunez, gerra irabazi duzu!!!') ;
TextColor(White) ;
end
else
begin
TextColor(LightRed) ;
writeln(iJaurtiKont, ' jaurtiketa ondoren itsas-bataila galdu duzu!!!') ;
TextColor(White) ;
writeln('Garaitu zaituen etsaien ontziteria:') ;
writeln ;
EtsaienArmadaErakutsi ; (* unitatean garaturik *)
end ;
end ;

writeln ;
writeln('///////////////////////////////////////////////////////////////////') ;

writeln ;
repeat until keypressed ;
end.





acItsasoarenEgoera karaktereen array horretan itsas-batailaren egoera gordeko dugu uneoro. Bataila hasi aurretik ItsasoarenEgoeraHasieratu prozedurak X karakterez betetzen du 6x6 arraya. Etsaien armada hondoratu nahian, 6x6 itsasoko koordenatu pare bat hautatzeko aukera izango dugu (5D bezalako karaktere-katea) eta koordenatu horiek fncSuEgin funtzioari pasatuz, honek jaurtiketaren emaitza itzuliko digu, eta, ondorioz ItsasoarenEgoeraHasieratu prozedurak bete dituen X guztietatik bat ordeztuko dugu. Arrayaren posizio horretako balio berria, honako hauetatik bat izango da:




  • u ura, gure jaurtiketak huts egin du

  • K korazatua, gure jaurtiketak korazatu baten zatia suntsitu du 

  • D destruktorea, gure jaurtiketak destruktore baten zatia suntsitu du 

  • P itsaspekoa, gure jaurtiketak itsaspekoa suntsitu eta hondoratu du 








Etsaien armadak 3+3+2+2+2+1=13 zatiz osaturik dago, eta guztiak suntsitu arte itsas-bataila ez da bukatuko eta garaile aterako gara 19 jaurtiketa behar izan badugu (19 jaurtiketa edo gutxiago beharko dira itsas-bataila irabazteko). Dagozkigun 19 jaurtiketak agortzean, batailaren galtzaileak gu izango gara eta programa bukatuko da. Baina 19. jaurtiketa egin baino lehenago, bataila galdutzat jotzen badugu, armistizioa eskatu ahalko dugu (AR koordenatuak sartuz) eta etsaien ontziteria pantailaratu ondoren programa bukatuko da.



Ikusi balizko exekuzio bat, non 16 jaurtiketan ura egin ondoren, amore eman eta armistizioa eskatzea erakabi dugun. Ondorioz, programa amaitu aurretik etsaien armadaren kokapena erakusten da:
























    Windows:

  • ItsasBatailak_w.pas   bezero-programaren iturburu-kodea

  • itsas_w.pas   unitatearen iturburu-kodea, hau konpilatzean:

    • itsas_w.ow   unitatearen objektu-kodea lortzen da (itsas_w.pas konpilatu ondoren)
    • itsas_w.ppw   unitate konpilatua lortzen da (itsas_w.pas konpilatu ondoren)


  • ItsasBatailak_w.exe   programa exekutagarria fitxategi hauekin lor daiteke:


    • ItsasBatailak_w.pas

    • itsas_w.ow

    • itsas_w.ppw



    Windows:

  • ItsasBatailak_w.zip   unitate konpilatua eta bezero-programaren iturburu-kodea (itsas_w.ow eta itsas_w.ppw gehi ItsasBatailak_w.pas)



 




    Mac:

  • ItsasBatailak.pas   bezero-programaren iturburu-kodea

  • itsas.pas   unitatearen iturburu-kodea

  • itsas.o   unitatearen objektu-kodea

  • itsas.ppu   unitate konpilatua

  • ItsasBatailak   programa exekutagarria (goiko fitxategiekin lor daiteke)







 

iruzkinik ez:

Argitaratu iruzkina