Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Simuloidaan Paha-akka pasianssia

PetriKeckman [28.05.2023 11:42:34]

#

Muistoja vuodelta 1986, jolloin suoritin Pascalin peruskurssin labratyönä pasianssin simuloinnin. Löysin haalistuneen ja repaleisen ohjelmalistauksen. Jätin tästä versiosta kommentit pois ja poistin koodia, kun alkuperäisessä versiossa oli mahdollista syöttää kortit, nyt ne arvotaan, samasta syystä myös lisäsin koodia.

https://petke.info/paha.exe (Windows)


Pasianssin asetelma:
Pakasta poimitaan ässät ja asetetaan peruskorteiksi riviin kuvapuoli ylöspäin. Peruskorttien alapuolelle asetetaan kahdeksan korttia apuriviin kuvapuolet ylöspäin. Näiden korttien oikealle puolelle asetetaan kahdeksan korttia piilopinoon kuvapuoli alaspäin. Loput korteista jäävät käsipakaksi.

Pelin tavoite:
Pyrittävä rakentamaan peruspakkoihin ylöspäin maata noudattaen.

Pelin kulku:
Apurivistä nostetaan kortteja peruspakkoihin aina kun se on mahdollista.

Jos piilopinossa on kortteja jäljellä, täytetään sieltä apuriviin syntyneet tyhjät kohdat. Jos siirtoja ei voi tehdä, katsotaan käykä näkyvän käsipakan päälimmäisin kortti peruspakkaan. Jos näkyvän käsipakan kortti käy peruspakkaan saa sen ala paljastuvaa korttia yrittää.

Apuriviin syntyviä aukkoja ei saa täyttää käsipakan korteilla (vaikka piilopino olisi loppunut).

Käsipakan saa käydä läpi enintään viisi kertaa.

Simuloinnin tuotoksena sain arvion, että pasianssin läpimeno todennäköisyys on noin 20 prosenttia.

program pahaakkapasiassi;
CONST maxlapikaynti=5;
	maxarvo=15;
TYPE arvot=1..maxarvo;
	maat=1..4;
	korttiosoitin=^kortti;
	kortti=RECORD
		maa: maat;
		arvo: arvot;
		seur: korttiosoitin;
	END;
	maachr=PACKED ARRAY[1..6] OF CHAR;
VAR	pakka,
	kasipakka,
	nakyvakasipakka,
	piilopino,
	kayttamattomat: korttiosoitin;
	peruspakka: ARRAY[1..4] OF korttiosoitin;
	apurivi: ARRAY[1..8] OF korttiosoitin;
	maatchr: ARRAY[1..4] OF maachr;
	lapikayntikerta: 1..maxlapikaynti;
	pelataan: BOOLEAN;
	maxlkm:	INTEGER;
	vastaus: char;
	pasiansseja,
	lapimenoja,
	pros: Double;
FUNCTION ontyhja(osoitin: korttiosoitin): BOOLEAN;
BEGIN
	ontyhja:=(osoitin=NIL);
END;
PROCEDURE siirrakortti(VAR otto,laitto: korttiosoitin);
VAR apu: korttiosoitin;
BEGIN
	IF NOT ontyhja(otto) THEN
	BEGIN
		apu:=otto;
		otto:=otto^.seur;
		apu^.seur:=laitto;
		laitto:=apu;
	END;
END;
FUNCTION kayperuspakkaan(card: korttiosoitin):BOOLEAN;
BEGIN
	IF ontyhja(card) THEN kayperuspakkaan:=FALSE
	ELSE kayperuspakkaan:=card^.arvo=peruspakka[card^.maa]^.arvo+1;
END;
PROCEDURE tulostakortit;
VAR i: Integer;
BEGIN;
	WRITE('Peruspakat:');
	FOR i:=1 TO 4 DO
		BEGIN
		WRITELN(i);
		WITH peruspakka[i]^ DO
			BEGIN
				WRITE(maatchr[2]:4,maa:4);
				WRITE(maatchr[maa]:7, arvo:3,'  ');
			END;
		END;
	WRITE('Nakyvakasipakka:');
	IF NOT ontyhja(nakyvakasipakka) THEN
		WITH nakyvakasipakka^ DO
			WRITELN(maatchr[maa]:7,arvo:3,'  ')
	ELSE
		WRITELN('');
	WRITELN('Apurivi:');
	FOR i:=1 TO 8 DO
		IF NOT ontyhja(apurivi[i]) THEN
			WITH apurivi[i]^ DO
				WRITE(maatchr[maa]:7, arvo:3,'  ');
END;
FUNCTION rivistakay(VAR rivi: Integer): BOOLEAN;
VAR r: Integer;
	kay: BOOLEAN;
BEGIN
	r:=0;
	REPEAT
		r:=r+1;
	UNTIL kayperuspakkaan(apurivi[r]) OR (r>=8);
	IF kayperuspakkaan(apurivi[r]) THEN  rivi:=r;
	rivistakay:=kayperuspakkaan(apurivi[r]);
END;
PROCEDURE kasitteleapurivia;
VAR i: Integer;
BEGIN
	WHILE rivistakay(i) DO
		BEGIN
			WITH apurivi[i]^DO
			BEGIN
				IF vastaus='t' THEN WRITE('Nostetaan apurivista', maatchr[maa]:7,arvo:3,' peruspakkaan.');
				siirrakortti(apurivi[i], peruspakka[maa]);
			END;
			IF NOT ontyhja(piilopino) THEN
				WITH piilopino^ DO
				BEGIN
					IF vastaus='t' THEN WRITELN('...ja piilopinosta', maatchr[maa]:7, arvo:4,' tilalle.');
					siirrakortti(piilopino,apurivi[i]);
				END;
				IF vastaus='t' THEN tulostakortit;
		END;
END;
FUNCTION lapimeni: BOOLEAN;
VAR paknro,
	valmiit: Integer;
BEGIN
	valmiit:=0;
	FOR paknro:=1 TO 4 DO
		IF peruspakka[paknro]^.arvo=maxarvo THEN
			valmiit:=valmiit+1;
	lapimeni:=(valmiit=4);
END;
FUNCTION liikaaselattu:BOOLEAN;
VAR dum: Integer;
BEGIN
	liikaaselattu:=(lapikayntikerta=maxlapikaynti)
		AND ontyhja(kasipakka)
		AND NOT kayperuspakkaan(nakyvakasipakka)
		AND NOT rivistakay(dum)
		AND NOT lapimeni;
END;
FUNCTION korttipiilopinossa: BOOLEAN;
VAR piilossalkm: Integer;
	piilokortit: korttiosoitin;
BEGIN
	piilossalkm:=0;
	piilokortit:=piilopino;
	WHILE NOT ontyhja(piilokortit) DO
	BEGIN
		IF kayperuspakkaan(piilokortit) THEN
			piilossalkm:=piilossalkm+1;
		piilokortit:=piilokortit^.seur;
	END;
	korttipiilopinossa:=(piilossalkm=4);
END;
PROCEDURE katsonakyvaakasipakkaa;
PROCEDURE nostakasipakastaperuspakkaan;
BEGIN
	WHILE kayperuspakkaan(nakyvakasipakka) DO
		WITH nakyvakasipakka^DO
		BEGIN
			IF vastaus='t' THEN WRITELN('Nostetaan kasipakasta',maatchr[maa]:7, arvo:3,' peruspakkaan');
			siirrakortti(nakyvakasipakka, peruspakka[maa]);
			IF vastaus='t' THEN tulostakortit;
		END;
END;
PROCEDURE selaakasipakkaa;
BEGIN
	IF NOT ontyhja(kasipakka) THEN
	BEGIN
		IF vastaus='t' THEN WRITELN('Selataan kasipakkaa, kasipakasta kaannettiin: ');
		REPEAT
			siirrakortti(kasipakka, nakyvakasipakka);
			WITH nakyvakasipakka^ DO
				IF vastaus='t' THEN WRITE(maatchr[maa]:7, arvo:3)
		UNTIL kayperuspakkaan(nakyvakasipakka) OR ontyhja(kasipakka);
	END;
END;
BEGIN
	IF kayperuspakkaan(nakyvakasipakka) THEN
		nostakasipakastaperuspakkaan
	ELSE
		IF NOT lapimeni THEN
			BEGIN
				selaakasipakkaa;
				IF kayperuspakkaan(nakyvakasipakka) THEN
					nostakasipakastaperuspakkaan
				ELSE
					IF NOT liikaaselattu THEN
					BEGIN
						lapikayntikerta:=lapikayntikerta+1;
						IF vastaus='t' THEN WRITELN('Kasipakan selauksessa alkaa', lapikayntikerta,'.s','kierros.');
						WHILE NOT ontyhja(nakyvakasipakka) DO
							siirrakortti(nakyvakasipakka, kasipakka);
					END;
			END;
END;
PROCEDURE alkuasetukset;
VAR i: Integer;
BEGIN
	FOR i:=1 TO 4 DO peruspakka[i]:=NIL;
	FOR i:=1 TO 8 DO apurivi[i]:=NIL;
	pakka:=NIL; kasipakka:=NIL; nakyvakasipakka:=NIL;
	kayttamattomat:=NIL;
	piilopino:=NIL;
	maxlkm:=4*(maxarvo-1);
	maatchr[1]:='hertta';
	maatchr[2]:='ruutu';
	maatchr[3]:='risti';
	maatchr[4]:='pata';
	pelataan:=TRUE;
	pasiansseja:=0;
	lapimenoja:=0;
END;
PROCEDURE uusisolmu(VAR os: korttiosoitin);
BEGIN
	IF ontyhja(kayttamattomat) THEN new(os)
	ELSE
		BEGIN
			os:=kayttamattomat;
			kayttamattomat:=kayttamattomat^.seur;
			os^.seur:=NIL;
		END;
END;
PROCEDURE jaapakka;
VAR i:Integer;
BEGIN

	FOR i:=1 TO 4 DO
		BEGIN
			uusisolmu(peruspakka[i]);
				WITH peruspakka[i]^DO
				BEGIN
					arvo:=1;
					maa:=i;
				END;
		END;
	FOR i:=1 TO 8 DO
		siirrakortti(pakka, apurivi[i]);
	FOR i:=1 TO 8 DO
		siirrakortti(pakka, piilopino);
	kasipakka:=pakka;
	pakka:=NIL;
END;
PROCEDURE kaannapino(VAR pino: korttiosoitin);
VAR apupino: korttiosoitin;
BEGIN
	apupino:=NIL;
	WHILE NOT ontyhja(pino) DO siirrakortti(pino, apupino);
	pino:=apupino;
END;
PROCEDURE sekoitapakka;
VAR m: maat;
	a: arvot;
	vaihtoapu,
	arpo,
	ind,
	luku: Integer;
	arpopakka: ARRAY[1..100] OF Integer;
	card: korttiosoitin;
BEGIN
	Randomize;
	FOR ind:=1 TO maxlkm DO arpopakka[ind]:=ind;
	FOR ind:=1 TO maxlkm DO
	BEGIN
		arpo:=RANDOM(maxlkm)+1;
		vaihtoapu:=arpopakka[ind];
		arpopakka[ind]:=arpopakka[arpo];
		arpopakka[arpo]:=vaihtoapu;
	END;
	IF vastaus='t' THEN	WRITELN('Arpomasi pakka paalimmaisesta kortista lahtien:');
	FOR ind:=1 TO maxlkm DO
	BEGIN
		luku:=arpopakka[ind];
		m:=(luku-1) DIV (maxarvo-1)+1;
		a:=luku-(maxarvo-1)*(m-1)+1;
		IF vastaus='t' THEN WRITELN(ind:3,':',maatchr[m]:8, a:3);
		uusisolmu(card);
		card^.maa:=m;
		card^.arvo:=a;
		card^.seur:=NIL;
		siirrakortti(card, pakka);
	END;
	kaannapino(pakka);
	IF vastaus='t' THEN WRITELN('Jaan kortit poytaan niin aloitetaan peli');
END;
PROCEDURE luesyottoaineistoa;
BEGIN //LUESYOTTOAINEISTOA
	WRITELN('Syota "t", jos haluat tulostaa pasianssipelin vaiheet.');
	WRITE('Syota "s", jos haluat vain simuloida tilastollista tutkimusta varten ');
	WRITELN(' ilman tulostusta. (pysayta ajo silloin painamalla CNTRL-C)');
	WRITELN('Syota "l" jos haluat kokonaan lopettaa simuloinnin');
	READLN(vastaus);
	IF vastaus='l' THEN pelataan:=FALSE;
END;
PROCEDURE keraakortit;
VAR i: Integer;
BEGIN
	FOR i:=1 TO 4 DO
		WHILE NOT ontyhja(peruspakka[i]) DO
			siirrakortti(peruspakka[i], kayttamattomat);
	FOR i:=1 TO 8 DO
		siirrakortti(apurivi[i], kayttamattomat);
	WHILE NOT ontyhja(kasipakka) DO
		siirrakortti(kasipakka, kayttamattomat);
	WHILE NOT ontyhja(nakyvakasipakka) DO
		siirrakortti(nakyvakasipakka, kayttamattomat);
	WHILE NOT ontyhja(piilopino) DO
		siirrakortti(piilopino, kayttamattomat);
END;
BEGIN
	alkuasetukset;
	luesyottoaineistoa;
	WHILE pelataan DO
		BEGIN
			sekoitapakka;
			jaapakka;
			lapikayntikerta:=1;

			IF vastaus='t' THEN tulostakortit;
			REPEAT
				kasitteleapurivia;
				katsonakyvaakasipakkaa;
			UNTIL (liikaaselattu OR lapimeni OR korttipiilopinossa);
			pasiansseja:=pasiansseja+1;
			pros:=100*lapimenoja/pasiansseja;
			WRITELN(pros);
			IF liikaaselattu THEN
				BEGIN
					if vastaus='t' THEN WRITELN('Kasipakkaa on selattu liikaa. Pasianssi ei mennyt lapi.');
				END
			ELSE IF lapimeni THEN
			BEGIN
				IF vastaus='t' THEN WRITELN('Pasianssi meni lapi! :)');
				lapimenoja:=lapimenoja+1;
				END
				ELSE BEGIN
					IF vastaus='t' THEN WRITELN('Ei kannata jatkaa. Kaikki seuraavaksi peruspakkaan kayvat kortit ovat piilopinossa.');
				END;
			keraakortit;
			IF vastaus<>'s' THEN luesyottoaineistoa;
		END;
END.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta