Vika EDIT:
Nyt toimii :) Graafisella käyttöliittymällä. Minun mielestä ihan hyvin toimii. Tämä tästä projektista.
https://petke.info/labyrintti.exe
EDIT: Ohjelma näyttää vaativan 4K näytön, missä Promptin leveys on suurempi. Unohtakaa tämä merkkipohjainen ohjelma!! Teen graafisen käyttöliittymän.
Olet labyrintissa. Olet yhtenä pienenä kysymysmerkkinä keskellä suurta labyrinttia. Sinulla on hieman epäkunnossa oleva drone, mikä ei pysty lentämään kovin korkealle, mutta näet sen kameran avulla näkymän viidenkymmenen metrin korkeudelta kännykästäsi. Klikkaa nuolinäppäillä mihin suuntaan kävelet ja löydä tiesi ulos.
Windowssille exe: https://petke.info/labyrintti99.exe
Suo siellä vetelä täällä. Aluksi yritin ohjelmoida peliä Red-kielellä hienolla graafisella käyttöliittymällä, mutta se ei oikein sujunut, sitten yritin Javascript versiota, eikä sekään sujunut. Sitten yritin Red-merkkigrafiikkaa, mutta Red-kielessä ei kertakaikkiaan voida lukea näppäinpainallusta!? (no, ainakin sellaisen ohjelmoiminen lienee vaikeaa) Lopulta päädyin Free Pascalilla ohjelmoituun DOS-merkkigrafiikka versioon. Free Pascalilla vois vielä yrittää graafista käyttöliittymää, mutta nyt en jaksa, vaikka nyt kun DOS-Prompt peli on tehty, niin melko sutjakasti se voisi valmistua. Mañana, mañana - niinkuin espanjalaiset sanovat. Huomenna, huomenna.
Peli vaatii, että MS-Prompt ikkunaa pidetään mahdollisimman suurena. Äsken kokeilin käynnistää sitä klikkaamalla Windowsista, ni avasi liian pienen ikkunan ja ohjelma luuli jostain syystä siksi tyhjää kohtaa muuriksi..eli merkkien tulostuksessa ei kai rivin pituus riittänyt - en ny jääny pohtimaan. Pitää siis ensin mennä Promptiin, tehdä siitä iso ja käynnistää ohjelma.
Bugitiedotuksia otetaan mielellään vastaan. Yhden jo tiedänkin: ohjelma vain päättyy, eikä kirjoita:
IF lopussa THEN WRITELN('LOISTAVAA!! PÄÄSIT LABYRINTISTA ULOS');
Jos löytää tiensä ulos - en tiedä miksi.
Program labyrinttiuus; uses winmouse,graph, wincrt,math,sysutils,DateUtils; CONST xkoko = 60; ykoko = 40; maxstep = 999999; TYPE XTYPE = 1..xkoko; YTYPE = 1..ykoko; VAR labyrintti : ARRAY[1..xkoko,1..ykoko] OF smallInt; step : longInt; yritauudestaan : BOOLEAN; px, py : shortInt; key : char; lopussa : BOOLEAN; gd,gm: integer; dx, dy : shortInt; lev,kork : shortInt; error : SmallInt; ok, lopeta : BOOLEAN; TheLine : String; PROCEDURE arvolabyrintti; VAR i : XTYPE; j : YTYPE; ruutu: shortint; BEGIN FOR i:=1 TO xkoko DO FOR j:=1 TO ykoko DO BEGIN ruutu:= Random(2)+1; labyrintti[i,j]:= ruutu; END; END; PROCEDURE paastaanulos; {Tarkistetaan satunnaiskävelyllä päästäänkö edes ulos labyrintista ainakin jotain reittiä. Tämä ei tietenkään ole paras mahdollinen ja tehokkain tapa, mutta riittävän nopea nykytietokoneille ja helpoin ohjelmoida.} VAR x : XTYPE; y : YTYPE; askelx, askely: shortint; BEGIN yritauudestaan:= FALSE; {jos arvotussa labyrintissa arvottiin pelaajan kohdalle tiili eli luku 2, niin turha edes yrittää} if (labyrintti[px,py] = 2) THEN yritauudestaan:= TRUE; x:= px; y:= py; step:=0; REPEAT BEGIN REPEAT askelx:= -2 + (random(3) + 1); {Joman kumman askeleen täytyy olla nolla.} askely:= -2 + (random(3) + 1); {Siis vain askeleet pääilmansuuntiin ovat sallittuja.} step:= step + 1; UNTIL (((askelx = 0) OR (askely = 0)) AND (labyrintti[x+askelx, y+askely] <> 2) OR (step>maxstep)); if (step > maxstep) THEN yritauudestaan:= true; x:= x + askelx; y:= y + askely; END; UNTIL (x = 1) or (x = xkoko) or (y = 1) or (y = ykoko) or (yritauudestaan = true); {ollaan päästy reunaan eli ulos tai luovutaan koko yrityksestä} END; PROCEDURE tulostalahialue; VAR i,j : shortInt; x1,x2,y1,y2 : shortInt; a,b : integer; BEGIN x1:= px - dx; x2:= px + (2 * dx+1); y1:= py - dy; y2:= py + (2 * dy+1); FOR j:=y1 TO y2 DO BEGIN FOR i:=x1 TO x2 DO BEGIN case (labyrintti[i, j]) of 1 : SetFillStyle(SolidFill,white); 2 : SetFillStyle(SolidFill,blue); 3 : SetFillStyle(SolidFill,red); end; a:=(i-x1)*lev; b:=(j-y1)*kork; if ((i<1) or (i>xkoko) or (j<1) or (j>ykoko)) THEN SetFillStyle(SolidFill,green); bar(a-lev,b-kork,a,b); END; END; SetColor(black); TheLine:=Concat('xkoord=',IntToStr(px),' ykoord=',IntToStr(py)); outTextXY(10,10,TheLine); END; PROCEDURE alusta; BEGIN Randomize; dx:=8; dy:=5; lev:=trunc(800 / (2 * dx + 1)); kork:=trunc(600 / (2 * dy + 1)); initmouse; gd := D4bit; gm := m800x600; initgraph(gd,gm,''); error := graphResult; if (error <> grOk) Then begin writeln('800x600x16 is not supported!'); halt(1); end; px:= trunc(xkoko/2); py:= trunc(ykoko/2); yritauudestaan:=true; repeat write('Odota, arvon labyrinttia.'); arvolabyrintti; paastaanulos; until yritauudestaan = false; labyrintti[px,py]:=3; tulostalahialue; setTextStyle(defaultFont,horizDir,2); END; PROCEDURE tv; BEGIN IF ((px = 1) or (px = xkoko)) or ((py = 1) or (py = ykoko)) THEN lopussa:=TRUE; END; PROCEDURE huomauta; BEGIN Writeln('Ei kannata hakata kupolia muuriin!!'); END; PROCEDURE tarkistaylos; BEGIN if labyrintti[px,py-1]=2 THEN huomauta ELSE BEGIN labyrintti[px,py]:=1; py:=py-1; ok:=true; labyrintti[px,py]:=3; tv; END; END; PROCEDURE tarkistaalas; BEGIN if labyrintti[px,py+1]=2 THEN huomauta ELSE BEGIN labyrintti[px,py]:=1; py:=py+1; ok:=true; tv; labyrintti[px,py]:=3; END; END; PROCEDURE tarkistavasen; BEGIN if labyrintti[px-1,py]=2 THEN huomauta ELSE BEGIN labyrintti[px,py]:=1; px:=px-1; ok:=true; labyrintti[px,py]:=3; tv; END; END; PROCEDURE tarkistaoikea; BEGIN if labyrintti[px+1,py]=2 THEN huomauta ELSE BEGIN labyrintti[px,py]:=1; px:=px+1; ok:=true; labyrintti[px,py]:=3; tv; END; END; begin alusta; ok:=false; lopeta:=false; lopussa:=false; repeat key := readkey; if key=#0 then begin REPEAT key:=readkey; case key of #72 : tarkistaylos; #80 : tarkistaalas; #75 : tarkistavasen; #77 : tarkistaoikea; 'a' : lopeta:=true; end; UNTIL ok or lopeta or lopussa; tulostalahialue; ok:=false; {asetetaan taas falseksi seuraavaa näppäimen painallusta varten} end; UNTIL lopeta or lopussa; IF lopussa THEN WRITELN('LOISTAVAA!! PAASIT LABYRINTISTA ULOS'); end.
PetriKeckman kirjoitti:
Bugitiedotuksia otetaan mielellään vastaan.
Ok, huomaan että laitoin teille liian ison haasteen oletusarvoillani. 60x40 labyrintti on liian suuri ja sellaisen bugin huomasin, että kenttö siirtyi ainakin oikealle aina yhden askeleen, kun liikutti pelaajaa oikealle - tällöin ei isokaan Prompti ikkuna riitä, jos labyríntti on iso. EDIT: En ny jaksa enää tänään bugia korjata ja etsiä :(
EDIT: BUGI KORJATTU!! :) :) Sekä .exe:een että tuohon ohjelmalistaukseen! Huolimattomuusvirhe oli bugi nimeltään.
EDIT: Peliä tehty kivemmaksi: se näyttää pelaajan 'gps-koordinaatat', mikä helpottaa ulospääsyä, kun tietää kuinka lähellä reunaa on.
EDIT taas: oli väärä lopetusehdon tarkistus siellä missä tarkisteltiin labyrintin oikeellisuutta! Sille kelpasi vain sellainen, missä oltiin nurkassa! Siksi aiemmissa versioissa jouduttiin testaamaan niin montaa labya. Nyt löytyy nopeasti.
EDIT taas: en ymmärrä miksi tulostuu muureja ylle vaikka pelaaja on päässyt labyssa yläreunaan. En tosiaan ymärrä...Ei näytä kivalta, kun peli ilmoittaa, että 'Onneksi olkoon olet päässyt ulos', vaikka on vielä labyrintissa :(
EDIT: Ohjelma näyttää vaativan 4K näytön, missä Promptin leveys on suurempi. Unohtakaa tämä merkkipohjainen ohjelma!! Teen graafisen käyttöliittymän.
Nyt toimii :) Graafisella käyttöliittymällä. Minun mielestä ihan hyvin toimii. Tämä tästä projektista.
https://petke.info/labyrintti.exe
Ohjelmalistaus korjattu.
Helpotin sekä vaikeutin peliä. Siinä mielessä helpotin, että koko labyrintti näkyy eikä vain osa ja kun aiemmin joka toinen oli muuriruutu, niin nyt vain joka kolmas, mutta! labyrintissa liikkuu nyt sattumanvaraisesti MÖRKÖJÄ. Jos törmäät niihin, niin kuolet. On myös aikarajoitus. Sinulla on vain minuutti aikaa. Jos et siinä ajassa pääse ulos, niin POMMI räjähtää! Vähän tulee klassikkopeli Pacman mieleen? 'Lyökö MÖRKÖ ulos'? Loppuuko aika? Möröt ovat tyhmiä: ne tekevät aukkoja ulos (bugi koodissa :) ).
https://petke.info/labyrintti2.exe
PS: Heilun vähän kuin heinämies täällä Putkassa. Metabolix oli nähnyt vaivaa ja tutkinut mikä mun pasianssin simulointi koodissa oli väärin, niin minä siirryin jo toiseen, mielenkiintoisempaan juttuun. No, onhan tässä aikaa miettiä nyt sitäkin koodia, mutta ensin syömään...
Program labyrinttiuus; uses winmouse,graph, wincrt,math,sysutils,DateUtils; CONST xkoko = 100; ykoko = 80; maxstep = 999999; morkoja = 80; TYPE XTYPE = 1..xkoko; YTYPE = 1..ykoko; koords = RECORD {MÖRKÖJEN KOORDINAATAT!!} x: 1..xkoko; y: 1..ykoko; END; VAR labyrintti : ARRAY[1..xkoko,1..ykoko] OF smallInt; MOROT : ARRAY[1..morkoja] OF koords; step : longInt; yritauudestaan : BOOLEAN; px, py : shortInt; key : char; lopussa : BOOLEAN; gd,gm: integer; dx, dy : shortInt; lev,kork : shortInt; error : SmallInt; ok, lopeta : BOOLEAN; TheLine : String; aikalaskuri : LongInt; xkoord, ykoord, vanhax, vanhay : ShortInt; a,b : integer; r : SmallInt; now1, now2 : TDateTime; aika : SmallInt; PROCEDURE arvolabyrintti; VAR i : XTYPE; j : YTYPE; ruutu: shortint; eikelpaa : BOOLEAN; BEGIN FOR i:=1 TO xkoko DO FOR j:=1 TO ykoko DO BEGIN IF Random(3)+1=2 THEN ruutu:=1 ELSE ruutu:= Random(2)+1; labyrintti[i,j]:= ruutu; END; {Arvotaan myös MORKÖJEN alkukoordinaatat} FOR i:=1 TO morkoja DO BEGIN eikelpaa:=FALSE; REPEAT xkoord:=Random(xkoko)+1; ykoord:=Random(ykoko)+1; IF (xkoord<(px+15)) AND (xkoord>(px-15)) THEN eikelpaa:=TRUE; UNTIL (labyrintti[xkoord,ykoord]=1) AND eikelpaa=FALSE; MOROT[i].x:=xkoord; MOROT[i].y:=ykoord; labyrintti[xkoord,ykoord]:=4; END; END; PROCEDURE paastaanulos; {Tarkistetaan satunnaiskävelyllä päästäänkö edes ulos labyrintista ainakin jotain reittiä. Tämä ei tietenkään ole paras mahdollinen ja tehokkain tapa, mutta riittävän nopea nykytietokoneille ja helpoin ohjelmoida.} VAR x : XTYPE; y : YTYPE; askelx, askely: shortint; BEGIN yritauudestaan:= FALSE; {jos arvotussa labyrintissa arvottiin pelaajan kohdalle tiili eli luku 2, niin turha edes yrittää} if (labyrintti[px,py] = 2) THEN yritauudestaan:= TRUE; x:= px; y:= py; step:=0; REPEAT BEGIN REPEAT askelx:= -2 + (random(3) + 1); {Jomman kumman askeleen täytyy olla nolla.} askely:= -2 + (random(3) + 1); {Siis vain askeleet pääilmansuuntiin ovat sallittuja.} step:= step + 1; UNTIL (((askelx = 0) OR (askely = 0)) AND (labyrintti[x+askelx, y+askely] <> 2) OR (step>maxstep)); if (step > maxstep) THEN yritauudestaan:= true; x:= x + askelx; y:= y + askely; END; UNTIL ((x<2) or (x>xkoko) or (y<2) or (y>ykoko)) or (yritauudestaan = true); {ollaan päästy reunaan eli ulos tai luovutaan koko yrityksestä} END; PROCEDURE tulostalahialue; VAR i,j : shortInt; x1,x2,y1,y2 : shortInt; BEGIN x1:= 0; x2:= xkoko+1; y1:= 0; y2:= ykoko+1; FOR j:=(y1+1) TO y2 DO BEGIN FOR i:=(x1+1) TO x2 DO BEGIN case (labyrintti[i, j]) of 1 : SetFillStyle(SolidFill,white); 2 : SetFillStyle(SolidFill,blue); 3 : SetFillStyle(SolidFill,red); 4 : SetFillStyle(SolidFill,yellow); end; a:=(i-x1+1)*lev; b:=(j-y1+1)*kork; if ((i<2) or (i>xkoko) or (j<2) or (j>ykoko)) THEN SetFillStyle(SolidFill,green); bar(a-lev,b-kork,a,b); END; END; END; PROCEDURE piirraruutu(x1,y1,x2,y2,vari:ShortInt); {piirtää joko mörön tai pelaajan kohtaan x1,y1 ja valkoistaa edellisen ruudun x2,y2} BEGIN case (vari) of 3 : SetFillStyle(SolidFill,red); 4 : SetFillStyle(SolidFill,yellow); end; a:=x1*lev; b:=y1*kork; bar(a,b,a+lev,b+kork); SetFillStyle(SolidFill,white); a:=x2*lev; b:=y2*kork; bar(a,b,a+lev,b+kork); END; PROCEDURE alusta; BEGIN Randomize; dx:=trunc(xkoko/2); dy:=trunc(ykoko/2); initmouse; gd := detect; initgraph(gd,gm,''); error := graphResult; if (error <> grOk) Then begin writeln('grapich state is not supported!'); halt(1); end; lev:=trunc(GetMaxX / (2 * dx + 1)); kork:=trunc(GetMaxY / (2 * dy + 1)); px:= trunc(xkoko/2); py:= trunc(ykoko/2); yritauudestaan:=true; repeat write('Odota, arvon labyrinttia.'); arvolabyrintti; paastaanulos; until yritauudestaan = false; labyrintti[px,py]:=3; tulostalahialue; setTextStyle(defaultFont,horizDir,2); END; PROCEDURE tv; BEGIN if ((px<2) or (px>xkoko) or (py<2) or (py>ykoko)) THEN lopussa:=TRUE; END; PROCEDURE huomauta; BEGIN Writeln('Ei kannata hakata kupolia muuriin!!'); END; PROCEDURE RAJAHDYS; VAR pxword,pyword : word; BEGIN Writeln('RAJAHDYS!!!!!!!!!!!!!!!!!!!!!'); pxword:=trunc((px/xkoko)*GetMAxX); pyword:=trunc((py/ykoko)*GetMaxY); FOR r:=1 TO trunc(GetMaxY/10) DO BEGIN SetFillStyle(SolidFill,Random(GetMAxColor)); FillEllipse(pxword,pyword,30*r,30*r); END; halt(2); END; PROCEDURE tarkistasuunta(dx,dy:ShortInt); {dx on joko -1 tai 1 samoin kuin dy} BEGIN IF labyrintti[px+dx,py+dy]=4 THEN RAJAHDYS; if labyrintti[px+dx,py+dy]=2 THEN huomauta ELSE BEGIN vanhax:=px; vanhay:=py; labyrintti[px,py]:=1; px:=px+dx; py:=py+dy; ok:=true; tv; labyrintti[px,py]:=3; piirraruutu(px,py,vanhax,vanhay,3); IF labyrintti[px,py]=4 THEN RAJAHDYS; END; END; PROCEDURE siirramorkoja; VAR i, vanhax, vanhay, askelx, askely, yrityksia : ShortInt; BEGIN FOR i:=1 TO morkoja DO BEGIN vanhax:=MOROT[i].x; vanhay:=MOROT[i].y; yrityksia:=0; REPEAT REPEAT yrityksia:=yrityksia+1; askelx:=-2+(random(3)+1); askely:=-2+(random(3)+1); UNTIL ((askelx=0) XOR (askely=0)); UNTIL (labyrintti[vanhax+askelx,vanhay+askely]=1) OR (yrityksia>20) OR (labyrintti[vanhax+askelx,vanhay+askely]=3); IF labyrintti[vanhax+askelx,vanhay+askely]=3 THEN RAJAHDYS; IF (yrityksia<20) AND (labyrintti[vanhax+askelx,vanhay+askely]=1) THEN BEGIN MOROT[i].x:=vanhax+askelx; MOROT[i].y:=vanhay+askely; piirraruutu(vanhax+askelx,vanhay+askely,vanhax,vanhay,4); IF labyrintti[MOROT[i].x,MOROT[i].y]=3 THEN RAJAHDYS; END; IF labyrintti[MOROT[i].x,MOROT[i].y]=3 THEN RAJAHDYS; END; END; begin alusta; ok:=false; lopeta:=false; lopussa:=false; now1:=Now; repeat REPEAT aikalaskuri:=0; siirramorkoja; REPEAT aikalaskuri:=aikalaskuri+1; {Tehotonta! Senkun lasketaan kymmeneen miljoonaan ja kasvatetaan aikalaskuria, mutta mihinkäs tässä kiire näppäinpainallusta odotellessa ja mörköjä liikutellessa} UNTIL (aikalaskuri=20000000) OR KeyPressed; now2:=Now; aika:=(trunc(((100000*(now2-now1))))); Writeln('Aikaa jaljella vain',60-aika,' sekuntia!!'); IF aika>60 THEN RAJAHDYS; aikalaskuri:=0; siirramorkoja; IF KeyPressed THEN BEGIN key:=readkey; case key of #72 : tarkistasuunta(0,-1); #80 : tarkistasuunta(0,1); #75 : tarkistasuunta(-1,0); #77 : tarkistasuunta(1,0); 'a' : lopeta:=true; end; END; UNTIL ok or lopeta or lopussa; ok:=false; {asetetaan taas falseksi seuraavaa näppäimen painallusta varten} UNTIL lopeta or lopussa; IF lopussa THEN WRITELN('LOISTAVAA!! PAASIT LABYRINTISTA ULOS'); end.
Kivan retro! Itse joskus meinasin tehdä pelin missä liikuttaisiin luolastossa, mutta en sitten jaksanut ikinä tehdä valmiiksi asti.
Luolaston piirtäminen onnistuu kivasti omalla "tilemap" kirjastolla, mikä taipuu ruutupohjaisiin peleihin ja tasohyppelyihin.
Oma kokeiluni näytti aikanaan tältä.
Mutta "tilemap" kirjastollani voi kohtuullisen helposti myös toteuttaa tämän kaltaisia skrollaavia tasohyppelyitä.
jalski kirjoitti:
Kivan retro! Itse joskus meinasin tehdä pelin missä liikuttaisiin luolastossa, mutta en sitten jaksanut ikinä tehdä valmiiksi asti.
Joo. On joskus vaikeaa ja vaivalloista työstää ideoitaan valmiiksi ohjelmiksi. Jäävät minullakin yleensä puolitiehen.
jalski kirjoitti:
Oma kokeiluni näytti aikanaan tältä.
Näyttääpä hienolta! En ole tottunut kirjastoja käyttämään, mutta taidanpa opetella tuollaisen 'tilemap' kirjaston käytön. Kysyn sitten sinulta neuvoa jos en osaa. Pikkasen jo Googlailin. Hankalalta vaikutti. Jos jaksat ja vaivaudut, niin voisit nyt jo vähän avittaa, että kuinka tuollainen kirjasto otetaan käyttöön?
Teen sitten labyrinttipelistä näyttävämmän näköisen.
PetriKeckman kirjoitti:
Jos jaksat ja vaivaudut, niin voisit nyt jo vähän avittaa, että kuinka tuollainen kirjasto otetaan käyttöön?
Tuo kirjasto on siis omaa tuotantoani 8th ohjelmointikielelle ja käytännössä koostuu muutamasta moduulista: viewport, map ja tilemap.
Näiden avulla kartta pystytään piirtämään mihin kohtaan ruutua tahansa ja se osa kartasta mikä halutaan piirtää. Mukana on myös perustoiminnallisuus kartta editorin toteuttamista varten, kuten hiirituki, karttaruudukon piirtäminen ja halutun ruudun selvitys. Vanhan liiton tasohyppelyn toteutusta varten on mahdollisuus selvittää mikä pikselin väri on kartalla tietyssä pisteessä. Näin voidaan käyttää erillistä törmäyskarttaa kertomaan onko kyseinen kohta esimerkiksi maata tai taso mihin voi alapuolen läpi hypätä.
Jos et tarvitse skrollaavaa karttaa, niin et tarvitse kirjastoa, selviät pienemmällä toiminnallisuudella ja voit yksinkertaisesti piirtää kartan taulukosta silmukassa ruudulle.
Aihe on jo aika vanha, joten et voi enää vastata siihen.