4 Gewinnt

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
daniel0904
Beiträge: 2
Registriert: Fr Dez 07, 2012 6:00 pm

4 Gewinnt

Beitrag von daniel0904 » Fr Dez 07, 2012 6:07 pm

Hallo,

ich bin gerade dabei ein 4 gewinnt zu programmieren. Bin totaler Anfänger und habe deshalb so meine Schwierigkeiten.
Mein Spielfeld steht so weit, nur weiß ich nicht wie ich es mache, dass ein Spielstein in das Feld gesetzt wird.
Vielleicht kann mir ja jemand helfen, wäre super =).

Hier mein Quellcode:

Code: Alles auswählen

#include <stdio.h>
#define N 6

void Ausgabe_Spielfeld(char spielfeld[N][7]);
int Eingabe_Zug(int *Spalte);

int main (void)

{
int Spalte;
char spielfeld[N][7]={{0}};

Ausgabe_Spielfeld(spielfeld);
Eingabe_Zug(&Spalte);
getchar();
return (0);

}

void Ausgabe_Spielfeld(char spielfeld[N][7])

{

int i;
printf("   1   2   3   4   5   6   7\n");
printf(" +---+---+---+---+---+---+---+\n");
for(i=0;i<6;i++)
	{
	
	printf (" | %c | ", spielfeld[i][0]);
	printf ("%c | ",	spielfeld[i][1]);
	printf ("%c | ",	spielfeld[i][2]);
	printf ("%c | ",	spielfeld[i][3]);
	printf ("%c | ",	spielfeld[i][4]);
	printf ("%c | ",	spielfeld[i][5]);
	printf ("%c | \n",	spielfeld[i][6]);
	
	
	printf (" +---+---+---+---+---+---+---+\n");
	}

}

int Eingabe_Zug(int *Spalte)

{

	int iGelesen;
	printf("Bitte geben Sie einen Zug ein:");
	iGelesen=scanf("%d",Spalte);
	while (getchar() != '\n');
	return iGelesen;

}
Edit by Xin: CodeTags hinzugefügt

Onraku
Beiträge: 43
Registriert: Fr Sep 09, 2011 2:14 pm

Re: 4 Gewinnt

Beitrag von Onraku » Fr Dez 07, 2012 7:10 pm

Hehe, an 4 Gewinnt sitze ich auch gerade um SDL kennen zu lernen.

Also ohne Code zu posten erklär ich einfach was ich mache, das solltest du dann ziemlich gut selber hinbekommen.

Du rufst deine Eingabefunktion mit der ausgewählten Spalte als Parameter auf, was dir fehlt ist die passende Reihe, um schließlich einen Spielstein zu setzen. Dieser soll natürlich ganz nach unten fallen. Da Du dein Spielfeldarray ja schon mit 0 initialisiert hast nehme ich an, dass diese ein leeres Feld repräsentieren soll. Dann kannst du 1 und 2 für Spieler 1 und 2 setzen.

Zur Bestimmung der Reihe. Mit einer Schleife kannst du von unten (also spielfeld[spalte][anzahlreihe-1] nach oben durchsehen, und wenn dort 0 steht den Stein setzen. Wenn das Feld !=0 steht da schon ne 1 oder 2, das Feld ist besetzt, und du nimmst dir das nächst höhere. Bist du ganz oben angekommen und hast noch kein freies Feld gefunden muss eine neue Spalteneingabe gemacht werden, und die Funktion muss erneut durchlaufen.
Ein Tipp zur Überprüfung: "0" als leeres Feld zu wählen ist sehr sinnvoll, da "0" als FALSE gewertet wird, alles andere als TRUE.

Code: Alles auswählen

if(!(spielfeld[y][x]))       //TRUE wenn frei
    stein setzen;
else
    schleifendurchgang abbrechen, und nächste reihe versuchen.
Aber nun: muss da jetzt eine 1 oder eine 2 rein?
Ich mache das so, dass ich eine Variable c=0 als Counter angelegt habe, die mit sagt in welcher Runde ich bin. Dafür muss nachdem ich einen Stein gesetzt habe c inkrementieren.
c%2 liefert immer 0 oder 1, d.h. mit (c%2 + 1) immer 1 oder 2, und das ist genau das was in das Feld muss.
Danach wie gesagt c++; und die nächste Runde mit dem anderen Spieler ist dran. Die eigentliche Spielschleife fehlt dir ja noch, aber danach hast du ja auch nicht gefragt.

Übrigens ist ein Array, wenn ich das richtig verstehe immer mit [y][x] definiert, also in deinem Fall [spalte][reihe]. Das ist zwar nur Definitionssache, war aber bei mir immer ein Punkt, bei dem ich jedesmal überlegen musste, bzw kompilieren und dann tauschen. Gehen tut beides, aber du kannst deine Ausgabefunktion vereinfachen, indem du eine äußere und eine innere For-Schleife nimmst. also statt

Code: Alles auswählen

printf (" | %c | ", spielfeld[i][0]);
printf ("%c | ", spielfeld[i][1]);
printf ("%c | ", spielfeld[i][2]);
printf ("%c | ", spielfeld[i][3]);
printf ("%c | ", spielfeld[i][4]);
printf ("%c | ", spielfeld[i][5]);
printf ("%c | \n", spielfeld[i][6]); 

kannst du auch eine zweite Schleife laufen lassen, in der du j (als zweite Zählvariable von 0 bis 6 laufen lässt und auf das Feld[j] zugreifst.
Da printf und jeder Drucker zeilenweise und nicht spaltenweise ausgibt, spielt hier die richtige Reihenfolge nun doch eine Rolle.

Im Übrigen findest du hier im Allegro-Tutorial (unter Spieleprogrammierung) auch ein 4 Gewinnt. Das ist zwar in C++, und mit Grafikausgabe, aber für die Spielelogik auch in deinem Fall einen Blick wert. Naja, IMMER einen Blick wert, aber in deinem Fall auch von praktischem Wert.

Wünsche noch viel Erfolg...

sebix
Beiträge: 82
Registriert: Mo Nov 19, 2012 8:27 pm

Re: 4 Gewinnt

Beitrag von sebix » Fr Dez 07, 2012 7:12 pm

Wenn du das Spielfeld global machst, ersparst du dir fehleranfällige Arbeit mit Pointern.

Hier ein überarbeiteter Code für die Ausgabe:

Code: Alles auswählen

void Ausgabe_Spielfeld()
{
	printf("    1   2   3   4   5   6   7\n");
	printf("  +---+---+---+---+---+---+---+\n");
	for(int i = 0; i < N; i++)
	{
		printf("%d ", i+1);
		for (int j = 0; j < 7; j++)
			printf("| %c ", spielfeld[i][j]);
		printf ("|\n  +---+---+---+---+---+---+---+\n");
	}
}
EDIT: War wer schneller, aber die Beiträge ergänzen sich :)
Immernoch unflexibel, da viel hardgecodet ist, aber ich denke ich kann dir so vl einen Anstoß geben ohne dich zu überfordern ;)

Beim Einlesen verstehe ich nicht ganz was du mit der Spalte wolltest. Du solltest aber beachten, dass scanf nicht den eingelesenen Wert zurückgibt, sondern du einen Pointer übergeben musst, in desser Speicher der Wert dann geschrieben wird. Wenn eine zahl eingelesen werden soll, kommt auch garantiert eine solche zurück (bzw. wird so lange der User gefragt, bis er aufgibt). Eine Überprüfung der Gültigkeit habe ich auch gleich eingebaut.

Code: Alles auswählen

int Eingabe_Zug()
{
	int iGelesen;
	printf("Bitte geben Sie einen Zug ein: ");
	do
	{
		scanf("%d", &iGelesen);
	} while (iGelesen < 0 || iGelesen > N); // Ungültige Werte
	return iGelesen;
}
Auswertung der Eingabe dann einfach mittels:

Code: Alles auswählen

	int input = Eingabe_Zug();
	printf("Gewählte Spalte: %d\n", input);
Wichtig ist noch am Anfang das Array zu initialisieren, da sonst eigenartige Werte im Array stehen könnten (bei globalen zwar nicht, aber ein uninitialisiertes Array ist schlechter Stil und sollte man sich nicht angewöhnen.):

Code: Alles auswählen

	for (int i = 0; i < N; i++) {
		for (int j = 0; j < 7; j++)
			spielfeld[i][j] = '_';
	}

daniel0904
Beiträge: 2
Registriert: Fr Dez 07, 2012 6:00 pm

Re: 4 Gewinnt

Beitrag von daniel0904 » Fr Dez 07, 2012 8:15 pm

danke ihr habt mir schon mal weiter geholfen =)

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: 4 Gewinnt

Beitrag von cloidnerux » Fr Dez 07, 2012 8:21 pm

Hier haben wir noch was zur Siegüberprüfung.
http://www.proggen.org/forum/viewtopic.php?f=49&t=4992
Redundanz macht wiederholen unnötig.
quod erat expectandum

Antworten