4 in einer Reihe - Ein Denkspiel in "C"


Dieses Spiel wird in einer senkrechten Ebene von 7 horizontalen und 6 vertikalen Feldern gespielt. Die Spieler setzen abwechselnd einen Stein auf eine bestimmte Spalte. Der Stein fällt daraufhin auf das tiefste unbesetzte Feld herunter. Derjenige Spieler, dem es gelingt, zuerst vier Steine horizontal, vertikal oder diagonal miteinandern zu verbinden, hat gewonnen.

In dieser Programmversion tritt der Rechner als Spielpartner an. Der Dialog zwischen Spieler und ATARI findet über die Titelzeile des Spielfensters, dessen Infozeile und die Maus statt. In der oberen rechten Bildschirmecke wird die Echtzeituhr samt Datumsangabe angezeigt. Es empfiehlt sich daher, dieselbe vor dem Laden des Programms einzustellen. Während der Bedenkzeit des Computers wird diese Ausgabe nicht aktualisiert, um die Zugzeiten kurz zu halten. Rechts neben dem Spielfeld werden die Bedenkzeiten des Spielers und des Rechners und die aktuelle Spielstufe angezeigt. Das Programm ist vollständig in „C" geschrieben.

Bedient wird das Programm ausschließlich mit der Maus. Folgende Funktionen stehen durch einfaches Anklicken zur Verfügung:

Es stehen fünf verschiedene Spielstärken (1 bis 5) zur Verfügung, wovon 1 die leichteste ist. Die Zugzeiten zu Spielbeginn differieren erheblich. Sie liegen zwischen einer und 400 Sekunden. Mit abnehmender Anzahl der noch zu besetzenden Spalten allerdings, nimmt die Zugzeit des Rechners erheblich ab.

Zu Beginn des Programmes werden sämtliche Variablen global definiert. Es werden die Typen ’short’ (16 Bit), ’int’ (32 Bit) und ’char’ (8 Bit) verwendet.

Nachstehend folgt eine Erläuterung der Aufgaben einzelner Funktionen:

main
Initialisierung von VDI, AES und einem Window; Hauptschleife für sämtliche Programmfunktionen.

nowinner
Unentschiedenes Spielende,

playerwins
Spielende bei Sieg des Spielers,

atariwins
Spielende bei Sieg des Rechners,

init
Initialisieren des Spielfeldes, der Zugzeitvariablen, etc; Ausgabe des Spielfeldes

entry
Überwachen der Maus; Aufruf der entsprechenden Routinen bei Auswahl einer Funktion.

depth
Ermitteln der ersten freien Zeilenposition innerhalb einer angewählten Spalte.

display
Ausgabe eines durchgeführten Zuges,

points
Ermitteln der Nachbarspielsteine für einen vom Computer geprüften Zug.

sub1500
Erhöhen der Bewertungspunktzahl in Abhängigkeit von der Anzahl der eigenen Nachbarspielsteine.

computer
Hauptroutine für den Rechnerzug; entweder wird der allererste Zug zufällig ausgewählt, oder aber die rekursive Funktion rekursion aufgerufen.

rekursion
Ermitteln des besten Zuges auf der Basis einer Zugtiefenschachtelung mit Punktebewertung

print___items
Ausgabe der anwählbaren Funktionen im Window.

get___time
Holen der aktuellen Uhrzeit und Umwandlung in sec.

show____time
Anzeigen der spielerspezifischen Bedenkzeit.

print___max
Ausgabe der Spielstufe.

test
Ermittlung der Anzahl noch besetzbarer Spalten.

show____date
Ausgabe der Echtzeituhr mit Tagesdatum.

abbruch
Sicherheitsabfrage bei Auswahl der Abbruch-Funktion.


short 1,j,x,y,handle1,handle2,key,ar[72],move,xpos,ypos,buttons,index, 
	pu,w,xx,yy,player,zw,bp,bz,zu,pl,x1,x2,y1,y2,b2,p2,style,myexit, 
	leer,tmax,tt,fr[91,wr191.Cornerst 41,xr[0],yr[10],br[10],pr[10],
	zuege[501;

int dummy,window,work_in[12],work_out[57],datevec[7],time,start, 
	time_player,time_atari,timebuf;
char buf[20],buf1[20],datum[50];

main()

{ appl_init();
	for (j=0; j<10; work_in[j++] = 1); work_int[10] = 2;
	handle1=graf_handle(&dummy,&dummy, fitdummy,&dummy);
	v_opnvwk(work_in,&handle1,work_out);
	v_clrwk(handle1);
	window=g_open(1,640,400,"Ihr Zug"," ");
	g_window(window,0,0,640,400);
	g_reopenCwindow);
	handle2=g_vdihandle(window);
	dummy=vst_color(handle1,1); dummy=vst_effects(handle 1,4);
	v_gtext(handle1,1, 15, "von P.M. & A.Q. (C)1986");
	dummy=vst_effects(handle 1,0); print_items();
	dummy=graf_mouse(3,&dummy);

	do
	{ init();
		do { test(); if (leer==0) { nowinner(); continue; } 
			entry();
			if (myexit==0)
			{ if (pu>=100) { playerwins(); continue; }
				test(); if (leer==0) { nowinner(); continue; } 
				player=1; computer(); player=1; index=bz; depth();
				display(); points();
				if (pu>=100) { atariwins(); }
			}
		}
		while(myexit==0);
	}
	while(myexit==1);

	dummy=graf_mouse(0,&dummy);
	g_exit();
	v_clsvwk(handle1);
	appl_exit();
}
nowinner()
{ g_info(window, "Sie haben Glck. Das Spiel endet unentschieden."); 
myexit=1; g_title(window,"Spielende, bitte Mausknopf drcken!"); 
do { show_date(); vq_mouse(handle2,&buttons,&xpos,&ypos); } while(buttons==0);
}

playerwins()
{ g_info(window,"Welch bses Schicksal. Sie haben zufllig gewonnen!"); 
	myexit=1; g_title(window,"Spielende, bitte Mausknopf drcken!"); 
	do { show_date(); vq_mouse(handle2,&buttons,&xpos,&ypos); } while(buttons==0);
}

atariwins()
{ g_info(window,"Es tut mir fast leid: SIE HABEN VERLOREN!");
	myexit=1; g_title(window,"Spielende, bitte Kausknopf drcken");
	do { show_date(); vq_mouse(handle2,&buttons,&xpos,&ypos); } while(buttons==0)
}

init()
{ myexit=0; time_player=0; time_atari=0; tmax=2; zu=0; 
	g_Info(window," ");
	for (i=0; i<72; ar[i++]=99);
	for (i = 10; i<=55;	i+=9) {	for (j=0; j<7; ar[i+j++]=0); }
	dummy=vsf_color(handle2,1); dummy=vsf_interior(handle2,2);
	vsf_perimeter(handle2,1); dummy=vsf_style(handle2,1);
	for (y=1; y<7; y++)
	{ for (x=1; x<8; x++)
		{ corners[0]=100+x*45; corners[1]=y*45;
			corners[2]=corners[0]+40; corners[3]=corners[1]+40; 
			g_rfbox(window,corners);
		}
	}
	dummy=vsf_interior(handle2, 2) ; print_max();
	player=1; show_time(); player= -1; show tlmeO;

}

entry()
{ player= -1; move = -1; v_show_c(handle2,0);
	get_time(); start=time; 
	do
	{ g_title(window,"Ihr Zug?");
		do { show_date(); vq_mouse(handle2,&buttons,&xpos,&ypos); } while(buttons==0);
		if (xpos>11 && xpos<113)
		{ if (ypos>353 && ypos<375) { abbruch() continue; }
		if (ypos>233 && ypos<255) { myexit=1; continue; }
		if (ypos>293 && ypos<315 && tmax<6) {tmax++; print_max(); continue; }
		if (ypos>323 && ypos<345 && tmax>2) {tmax-—; print_max(); continue; }
		if (ypos>263 && ypos<285 && zu>0)
		{ dummy=vsf_style(handle2,1);
			for (i=0; i<2; i++)
			{ zu--; index=zuege[zu]; depth();
				if (move<0) move=1» else move++; ar[move*9+index]=0; 
				corners[0]=100+index*45; corners[1]=move*45;
				corners[2]=corners[0]+40; corners[3]=corners[1]+40;
				g_rfbox(window,corners);
			}
			do { vq_mouse(handle2,&buttons,&xpos,&ypos); } while(buttons!=0); 
			move= -1;
		}
	}
	if (xpos>144 && xpos<460 && ypos>60) { index=(xpos-100)/45; depth(); }
	}
	while(move<0 && myexit==0); 
	v_hide_c(handle2); zuege[zu]=index; zu++;
	get_time(); time_player+=time-start; show_time();
	if (myexit ==0) { display(); points(); }
}

depth()
{ move= -1; 
	for (y=7; y>0; y—) { 
		if (ar[y*9+index]==0) { move=y; break) }}

display()
{ ar[move*9+index]=player;
	if (player<0)
	style = 4; else style=8; dummy=vsf_style(handle2,style);
	y=1; corners[0]=100+index*45; corners[1]=y*45;
	corners[2]=corners[0]+40; corners[3]=corners[1]+40;
	g_rfbox(window,corners);
	while(y<move)
	{ delay(3); y + + ; dummy = vsf_style(handle2,1);
		corners[1]=(y-1)*45; corners[3]=corners[1]+40;
		g_rfbox(window,corners); dummy=vsf_style(handle2,style);
		corners[1]=y*45; corners[3]=corners[1]+40; 
		g_rfbox(window,corners);
	}
	for (i=0; i<3;	i++)
	{ delay(10); dummy=vsf_style(handle2,1); g_rfbox(window,corners); 
	delay(10); dummy=vsf_style(handle2,style); g_rfbox(window,corners);
	}
}

points()
{ pu=0;
	for (xx= -1; xx<2; xx++)
	{ for (yy= -1) yy<2; yy++)
		{ if (xx==0) { if(yy==0) continue) }
			w=1; fr[(xx+1)*3+yy+1]=0;
			while<ar!move*9+index+xx*w+<yy*9)*w]==player) { w++; } 
			if (ar[move*9+index+xx*w+(yy*9)*w]==0) fr[(xx+1)*3+yy+1]=1; 
			wr[(xx+1)*3+yy+1]=w-1;
		}
	}
	for (yy=-1; yy<2; yy++)
	{ zw=wr[yy+1]+wr[6-yy+1];
		if (zw)=3) { sub1500(); continue; } 
		if (fr[yy+1]==0 && fr[6-yy+1]==0) zw=0;
		sub1500();
	}
	zw=wr[5]; if (zw<(4-move)) zw=0;
	sub1500();
}

sub1500()
{ if (zw==1) pu++;
	if (zw==2) pu+=10;
	if (zw>=3) pu+=100;
}

computer()
{ g_title(window,"Jetzt bin ich an der Reihe!");
	get_time(); start = time; tt=0; player= -1 bz=0; br[1]= -999;
	if (zu<2)
	{ do
		{ date(dummy,&datevec); bz=3+(datevec[6] % 3); }
		while(ar[54+bz]!=0);
	}
	else rekursion(); 
	zuege[zu]=bz; zu++;
	get_time(); time_atari+=1+(time-start); player=1; show_time();
}

rekursion()
{ tt++; player*= -1; xr[tt]=1;
	label1:
	if (ar[xr[tt]+9]!=0) goto label2;
	index=xr[tt]; depth(); yr[tt] =move ; points(); pr[tt]=pu; 
	br[tt+1]=0; pr[tt+1]=0;
	if (tt+1< = tmax) br[tt + 1]= -999;
	if (tt==1) { if (pu>=100) { bz=xr[1]; return; } } 
	ar[yr[tt]*9+xr[tt]]=player;
	if (pu>=100) { br[tt]=pu; ar[yr[tt]*9+xr[tt]]=0; xr[tt]=7; goto label2; } 
	if (tt<tmax) rekursion(); 
	if (br[tt+1]== -999) br[tt+1]=0;

if (pr[tt]-br[tt+1]>br[tt])
	{ br[tt]=pr[tt]-br[tt+1]; if (tt==1) bz=xr[1]; }

if (pr[tt]-br[tt+1]==br[tt])
	{ date(dummy,&datevec);
	if (datevec[6]%2==0)
		{ br[tt]=pr[tt]-br[tt+1]; if (tt==1) bz=xr[1]; } }
	ar[yr[tt]*9+xr[tt]]=0;
	label2:
	if (xr[tt]<7) { xr[tt]++; goto label1; }
	tt--; player*= -1;

}

print_items()
{ dummy=vsf_color(handle1,1); dummy=vsf_interior(handle1,2);
	dummy = vsf_style(handle1,4);
	corners[0] = 12; corners[2]=corners[0] + 104;
	for(y=1; y<6; y++)
	{ corners[1]=220+y*30-16; corners[3] = 220+y*30+5; 
		v_bar(handle1,corners); }
	corners[0]=520; corners[2]=corners[0]+71;
	for (y=0; y<3; y++)
	{ corners[1]=174+y*60; corners[3]=corners[1]+51;
		v_bar(handle1,corners); }
	v_gtext(handle1,36,370,"ABBRUCH");
	v_gtext(handle1,20,250,"Neues Spiel");
	v_gtext(handle1,16,310,"Spielstufe +"); 
	v_gtext(handle1, 16,340,"Spielstufe -");
	v_gtext(handle1, 16,280,"Zugrcknahme") ; 
	v_gtext(handle1,528,253,"Spieler"); 
	v_gtext(handle1,524,313,"Computer"); 
	v_gtext(handle1,528,207,"Stufe ");

}

get_time()
{ date(dummy,&datevec);
	time=datevec[6]+datevec[5]*60+datevec[4]*3600;
}

show_time()
{ if (player<0)
	{ y=274; time=time_player; } else { y=334; time=time_atari; } 
	timebuf = time/3600; time- = timebuf*3600; itoa(timebuf,&buf1);
	if (timebuf<10) { strcat(&buf1,"0"); reverse(&buf1); } strcpy(&buf,buf1); 
	strcat(&buf,"."); timebuf=time/60; time-=timebuf*60; itoa(timebuf,&buf1); 
	if (timebuf<10) { strcat(&buf1,"0"); reverse(&buf1); } strcat(&buf,&buf1); 
	strcat(&buf,":"); itoa(time,&buf1);
	if (time<10) { strcat(&buf1,"0"); reverse(&buf1); } strcat(&buf,buf1);
	v_gtext(handle1,524,y,buf);
}


print_max()
{ dummy=tmax-1; itoa(dummy,&buf); v_gtext(handle 1,576,207,buf);
	do { vq_mouse(handle2,&buttons,&xpos,&ypos); } while(buttons!=0);
}

test()
{ leer=0; for(index=1; index<8; index++)
	{ depth(); if (move>0) leer++; }
}

show_date()
{ date(dummy,&datevec);
	switch(datevec[3])
	{ case 0: strcpy(&datum,"Sonntag"); break;
	  case 1: strcpy(&datum,"Montag"); break;
	  case 2: strcpy(&datum,"Dienstag”); break;
	  case 3: strcpy(&datum,"Mittwoch"); break;
	  case 4: strcpy(&datum,"Donnerstag"); break;
	  case 5: strcpy(&datum,"Freitag"); break;
	  case 6: strcpyC&datum,"Samstag"); break;
	}
	strcat(&datum,", der ");
	dummy=datevec[2]; itoa(dummy,&buf); strcat(&datum,buf); strcat(&datum, ".");
	dummy=datevec[1]; itoaCdummy,&buf); strcatC&datum,buf); strcatC&datum, ".19"); 
	dummy=datevec[0]; itoaCdummy,Abuf); strcatC&datum,buf); strcatC&datum, ", "); 
	dummy=datevec[4]; itoa(dummy,&buf);
	if (dummy<10) { strcat(&buf,"0"); reverse(&buf); } strcat(&datum,buf); 
	strcat(&datum,";"); dummy=datevec[5]; itoa(dummy,&buf);
	if (dummy<10) { strcat(&buf,"0"); reverse(&buf); } strcat(&datum,buf);
	strcat(&datum," Uhr");
	while(strlen(datum)<37) { strcat(&datum," "); }
	v_gtext(handle1,340,15,datum);
}

abbruch()
{ v_hide_c(handle2); g_info(window,"Sie wollen wirklich aufhren? Cj/n)");
	key=evnt_keybd(); key=key&255; if (key==74 || key-=106) myexit=2; 
	g_info(window," "); v_show_c(handle2,0);
}


Aus: ST-Computer 03 / 1986, Seite 59

Links

Copyright-Bestimmungen: siehe Über diese Seite