[C] ich brauche Hilfe

c-anf

Grünschnabel
Hallo Boarduser,

ich wende mich nun an euch, da ich nicht mehr weiter komme.
Die Aufgabenstellung ist eine einfachere Version des Spiels Carcassonne zu implementieren. Es gibt eine bestimmte Art der Kartendarstellung für das Spiel: Nord, Ost, Süd, West.
Dort stehen jeweils Zahlen: 0 für Wiese, 1 für Straße und 2 für Stadt.
Die Karten werden generiert und alles läuft wunderbar. Es geht um das Spielen. Die Aufgabe verlangt folgendes:
5 Spielverlauf:
Vor dem Spielbeginn wird als erstes die als Parameter ubergebene Datei ausgelesen und alle dort enthaltenen Karten werden wieder auf den Stack gelegt. (CHECK)
Dann wird die Startkarte (2101) auf das Spielfeld gelegt und das Spiel beginnt. Achten Sie hierbei darauf, die Speicherung des Spielfelds dynamisch zu gestalten.
Solange Karten auf dem Stack liegen werden nun die folgenden Schritte ausgefuhrt:
1. Eine Karte wird vom Stack genommen
2. Alle moglichen Positionen werden von links unten beginnend von links nach rechts durchlaufen.
3. An jeder Position wird uberpruft, ob die aktuelle Karte entweder sofort oder durch Drehung
im Uhrzeigersinn an dieser Position angelegt werden kann. Sobald sie das erste Mal passt, wird für diese Position das folgende berechnet:
(a) Die maximale Lange der anliegenden Straen. Dabei gilt, dass eine Strae an einer Kreuzung endet. Jede Karte uber die die so berechnete langste Strae verlauft bringt einen
Punkt. Dazu kommt abschließeend 1 Punkt fur die anzulegende Karte selbst.
(b) Die maximale Größe der anliegenden Städte. Jede Karte auf der diese Stadt liegt bringt 2 Punkte. Dazu kommen 2 Punkte fur die Karte selbst.
(c) Liegt die Karte nur an Wiesen an, so ist der Wert der Position 0.
(d) Abschlieend wird überpruft ob das Maximum beider Werte größer ist als das Maximum
aller vorherigen Positionen. Ist das der Fall, wird diese Position samt der gefundenen
Ausrichtung abgespeichert.
4. Wurden alle Positionen uberpruft, wird die Karte an die Position mit dem maximalen Wert angelegt. Wurde keine Position gefunden, wird die Karte verworfen.

Wie würdet ihr da drangehen? Ich hab die Startkarte 2101. Ich nehme die erste karte vom Stack, überprüfe zunächst unten 1. ob ihr Nordwert = Südwert der Startkarte ist, wenn ja, punkte erhöhen, wie oben beschrieben, wenn nein, karte im Uhrzeigersinn rotieren und prüfen. Dabei punkte immer mit ner Variable maxScore vergleichen. Wenn punkte höher als maxScore, maxScore = punkte und karte dorthin legen. Wie Speichern, dass ich da später wieder vergleichen kann? Wie weitermachen mit mehreren Karten? Wie überprüfe ich die Codes Nord Ost Süd West, wenn bspw. 2 Karten nebeneinander liegen? Dann habe ich Nord1,Nord2,Ost2,Süd2,Süd1,West1...Wie mache ich das Dynamisch****?
 
ich hoffe, sie ist im Anhang...

Alles was nicht kommentiert wurde, sind Experimente, die nicht geglückt sind...irgend eine Idee****
 

Anhänge

  • carcassonne.c.zip
    3,7 KB · Aufrufe: 30
Hallo

Nach kurzem Durchsehen / Ausprobieren:
- in Zeile 191 schreibst du
C:
struct chararray new;
. new ist aber reserviert. Wähle einen anderen Namen.
- Anscheinend mag mich das Programm nicht...
Code:
carcassonne.exe creation test.txt 1
carcassonne.exe play test.txt
gibt einen Absturz.
- Visual Studio mag das Programm gar nicht. Ich arbeite jetzt ein wenig daran und melde mich später wieder

Gruss
cwriter
 
new ist ein Schlüsselwort in C++ nicht in C.
Der Aufruf muss so erfolgen: carcassonne creation test.txt [9 Stelliger Startwert] [Kartenanzahl]
nimm zum Beispiel sowas: carcassonne creation karten.txt 725139884 5
dann: carcassonne play karten.txt
Gegen Abstürze ist es noch nicht sicher, aber 3 Argumente müsste es abfangen.
Visual Studio's Compiler ist Mist. gcc ist hingegen top!
 
:offtopic:
c-anf hat gesagt.:
Visual Studio's Compiler ist Mist. gcc ist hingegen top!
Verbrenne dir nicht die Finger mit solchen Aussagen. Auf Windows ist VS immer noch die beste Variante.

Wie auch immer: Mit geänderten Einstellungen funktioniert es nun in VS.
Der Absturz wird in Zeile 292 produziert.
Dann gibt es einige Stellen, wo ich nicht ganz drauskomme:
Zeile 88-90:
C:
for(i=0;i<(count*7);i++) spielfeld[i] = (char*)malloc((count*7)*sizeof(char));
card = paint(2,1,0,1);
play(spielfeld, card);
In Zeile 88 allozierst du zwar 7 * count * ein char, doch dieser ist nicht 0-terminiert.
In Zeile 90 rufst du dann die play() auf, worin steht:
C:
for(i=0;i<7;i++) {
		for(j=0;j<7;j++) {
			spielfeld[i][j] = karte.carccard[i][j];
			//printf("%c",spielfeld[i][j]);
		}
		//printf("\n");
	}
Dein array spielfeld ist also nicht 0-terminiert.
Weiter unten schreibst du so lange, bis das Terminierungszeichen kommt, das du gar nicht hast:
C:
        for(i=0;spielfeld[i] != '\0';i++) {
		for(j=0;spielfeld[i][j] != '\0';j++) printf("%c",spielfeld[i][j]);
		printf("\n");
	}
Und hier lässt du die ints auch fröhlich weiteraddieren, obwohl es ja nur maximal 7 Zeichen sind.
Die von mir modifizierte play():
C:
void play(char **spielfeld, struct chararray karte) { // Bekomme Spielfeld und neue Karte zum Rumprobieren


	char **tmp;
	int i,j;
	int punkte=0, maxScore=0;

	for(i=0;i<7;i++) {
		for(j=0;j<7;j++) {
			spielfeld[i][j] = karte.carccard[i][j];
			//printf("%c",spielfeld[i][j]);			
		}
		spielfeld[i][j] = '\0'; //Von mir eingefügt
		//printf("\n");
	}
	for(i=0;spielfeld[i] != '\0';i++) {
		if(i == 7) break; //Von mir eingefügt (weiter unten verändert)
		for(j=0;spielfeld[i][j] != '\0';j++)
		{
			if(j < 8 && spielfeld[i] != '\0') printf("%c",spielfeld[i][j]);
		}
		printf("\n");
	}

}
Im Übrigen frage ich mich, weshalb du alles erst kopierst.
So geht's doch auch und ist erst noch einfacher?!
C:
for(i=0;i<7;i++) {
		for(j=0;j<7;j++) {
			printf("%c",karte.carccard[i][j]);			
		}
		printf("\n");
	}
Um zu deiner Frage zurückzukommen:
c-anf hat gesagt.:
Wie weitermachen mit mehreren Karten?
Schleife für's Kartenladen.
c-anf hat gesagt.:
Wie Speichern, dass ich da später wieder vergleichen kann?
Wie meinst du das? In einer Datei?
c-anf hat gesagt.:
Wie mache ich das Dynamisch?
Wie meinst du das? Dynamisch Karten hinzufügen?

Gruss
cwriter
 
Ich benutze kein Windows, OSX und Linux, daher GCC.
Ich glaube, Du missverstehst mich und die Aufgabe. Also, die Play() funktioniert gar nicht, überhaupt noch nicht, noch tut sie was sie soll. Das waren nur Experimente, die nicht funktioniert haben. Ich hätte sie besser vorher entfernen sollen. Also: Ich bekomme eine Karte, mit einem Code: der Code ist beispielsweise 2101, heiß im Norden Stadt, im Osten Straße, im Süden Wiese, im Westen Straße! Das ist die Startkarte. Dann nehme ich eine von mir generierte Karte. Diese hat ebenfalls einen Code: Sagen wir 2010. Ich muss jetzt beginnend von unten vergleichen, ob Norden der neuen Karte mit Süden der ersten gleich ist. Wenn ja, gibt es Punkte. Hier vergleiche ich 0 mit 2, ist falsch, also drehe ich die neue karte im Uhrzeigersinn. Jetzt ist Westen neues Norden, also habe ich den neuen Code für die neue Karte: 0201. 0 und 0 gehen aber der Score wird nicht erhöht. So geht das ganze weiter, bis ich den besten Score habe. Dort wird die Karte gelegt. in dem Fall wäre die karte so codiert 1020, jetzt liegt die karte oben und ist um 180 grad gedreht. Und das muss ich weiter machen, für alle karten vom Stack. Wie speichere ich das Spielfeld dynamisch, ich brauche sowohl die Karten als auch die Codes und den Score bis dahin, damit ich an jeder freien Stelle der Karten auf dem Spielfeld weitermachen kann mit Überprüfen. Ich lade mal was hoch. augabe.txt muss erzeugt werden. Wie komme ich von den Karten aus karten.txt zu ausgabe.txt? Das ist das, was ich machen soll!

und break sollte man nur in switch verwenden, kein guter Stil, Lesbarkeit der Programme leidet drunter ;)
 

Anhänge

  • beispiel_1.zip
    1,5 KB · Aufrufe: 20
Ah, jetzt verstehe ich: Die Karte selbst ist irrelevant, nur der Code muss passen :)

Kleine Frage noch: Sind STL-templates erlaubt?

Ich werde bis morgen jedenfalls noch etwas basteln ;-)

Gruss
cwriter
 
c-anf hat gesagt.:
Wie speichere ich das Spielfeld dynamisch, ich brauche sowohl die Karten als auch die Codes und den Score bis dahin, damit ich an jeder freien Stelle der Karten auf dem Spielfeld weitermachen kann mit Überprüfen.
In einem struct? Z.B. so? Ich weiss immer noch nicht, was "dynamisch" heissen soll. Mit malloc()/calloc() arbeitest du ja schon.
C:
struct Code
{
    int N, O, S, W;
    int posX,posY;
};
struct Map
{
    Code c;
    char map[7][7];
};
struct Score
{
    Map map;
    int score;
}
Die Stellen besetzen könntest du mit negativen Werten machen, z.B. -1. Ich habe mal eine eigene kleine Version geschrieben:
C:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Code
{
	int N,O,S,W;
	int posX;
	int posY;
};

struct CodeArray
{
	Code c;
	int count;

	int height;
	int width;

	int hb;
	int wb;
	int he;
	int we;
};

CodeArray* LoadFile(char* path)
{
	int count = 0;
	Code c;
	CodeArray* ca;
	FILE* f = fopen(path,"r");
	if(f == NULL) return ca;
	char temp[512];	//grosszügig Speicher reservieren
	while(fgets(temp,512,f))
	{
		if(strstr(temp,"Code:") != NULL)
		{
			count++;
		}
	}
	fseek(f,0,SEEK_SET);
	ca = (CodeArray*)calloc(count,sizeof(CodeArray));
	int ii = 0;
	while(fgets(temp,512,f))
	{
		if(strstr(temp,"Code:") != NULL)
		{
			char* pch = strtok(temp," ");
			if(pch == NULL) return ca;
			pch = strtok(NULL,"\n");
			if(pch == NULL) return ca;
			int i = 0;
			while(i != 4)
			{
				if(i == 0) c.N = pch[i] - 48;
				if(i == 1) c.O = pch[i] - 48;
				if(i == 2) c.S = pch[i] - 48;
				if(i == 3) c.W = pch[i] - 48;
				i++;
			}
			ca[ii].c = c;
			ii++;
		}
		temp[strlen(temp)-1] = '\0';
	}
	ca->count = count;
	fclose(f);
	return ca;
}

Code TurnCode(Code c)
{
	Code cpy;
	cpy.O = c.N;
	cpy.S = c.O;
	cpy.W = c.S;
	cpy.N = c.W;
	return cpy;
}

struct score
{
	int points;
	int maxpoints;
	int maxpindex;
	Code c1;
	Code c2;
};

score MatchMaps(Code c1, Code c2)
{
	/*Notiz:
	N - S passen
	O - W passen

		2
	0		1
		2
		0
	2		1
		2

	*/
	int i = 0;
	Code c_cpy = c2;
	score s;
	s.maxpindex = 0;
	s.maxpoints = 0;
	s.points = 0;
	while(i != 4)
	{
		if(c_cpy.S != c1.N && c_cpy.N == c1.S)
		{
			s.points = c_cpy.N + c1.S;			
			if(s.points > s.maxpoints)
			{
				s.maxpoints = s.points;
				s.maxpindex = i;
				//Wir sperren die Zuordnung
				s.c1 = c1;
				s.c1.S = -1;
				s.c2 = c_cpy;
				s.c2.N = -1;
				s.c2.posY = c1.posY -1;
				s.c2.posX = c1.posX;
			}
		}
		if(c_cpy.O != c1.W && c_cpy.W == c1.O)
		{
			s.points = c_cpy.W + c1.O;
			if(s.points > s.maxpoints)
			{
				s.maxpoints = s.points;
				s.maxpindex = i;
				//Wir sperren die Zuordnung
				s.c1 = c1;
				s.c1.O = -1;
				s.c2 = c_cpy;
				s.c2.W = -1;
				s.c2.posX = c1.posX +1;
				s.c2.posY = c1.posY;
			}
		}
		if(c_cpy.S == c1.N && c_cpy.N != c1.S)
		{
			s.points = c_cpy.S + c1.N;
			if(s.points > s.maxpoints)
			{
				s.maxpoints = s.points;
				s.maxpindex = i;
				//Wir sperren die Zuordnung
				s.c1 = c1;
				s.c1.N = -1;
				s.c2 = c_cpy;
				s.c2.S = -1;
				s.c2.posY = c1.posY +1;
				s.c2.posX = c1.posX;
			}
		}
		if(c_cpy.O == c1.W && c_cpy.W != c1.O )
		{
			s.points = c_cpy.O + c1.W;
			if(s.points > s.maxpoints)
			{
				s.maxpoints = s.points;
				s.maxpindex = i;
				//Wir sperren die Zuordnung
				s.c1 = c1;
				s.c1.W = -1;
				s.c2 = c_cpy;
				s.c2.O = -1;
				s.c2.posX = c1.posX -1;
				s.c2.posY = c1.posY;
			}
		}
		if(s.points > s.maxpoints)
		{
			s.maxpoints = s.points;
			s.maxpindex = i;
		}
		i++;
		c_cpy = TurnCode(c_cpy);
	}
	//maxpindex * 90 = Grad Drehung
	return s;
}

int printCode(Code c)
{
	fprintf(stdout,"N:%d\nO:%d\nS:%d\nW:%d\n",c.N,c.O,c.S,c.W);
	return 0;
}

int main(int argc, char** argv)
{
	CodeArray* ca = LoadFile("karten.txt");
	printf("%d Karten gefunden...\n",ca->count);
	int i = 0;
	//den array befüllen
	ca[0].c.posX = 0;
	ca[0].c.posY = 0;
	ca->height = 1;
	ca->width = 1;
	while(i != ca->count)
	{
		printf("\n\n");
		printCode(ca[i].c);
		printf("\n");
		if(i + 1 != ca->count)
		{	
			printCode(ca[i+1].c);
			score s = MatchMaps(ca[i].c,ca[i+1].c);
			ca[i].c = s.c1;
			ca[i+1].c = s.c2;
			printf("SCORES:\nTURN: %d\nPOINTS: %d\n",s.maxpindex*90,s.maxpoints);
		}
		i++;
	}
	i = 0;
	int wbegin = 100;
	int hbegin = 100;
	int wend = -100;
	int hend = -100;
	while(i != ca->count)
	{
		if(ca[i].c.posX < wbegin) wbegin = ca[i].c.posX;
		if(ca[i].c.posX > wend) wend = ca[i].c.posX;
		if(ca[i].c.posY < hbegin) hbegin = ca[i].c.posY;
		if(ca[i].c.posY > hend) hend = ca[i].c.posY;
		i++;
	}
	ca->hb = hbegin;
	ca->he = hend;
	ca->wb = wbegin;
	ca->we = wend;
	ca->width = wend - wbegin;
	ca->height = hend - hbegin;
	system("PAUSE");
	free(ca);
	return 0;
}
Hierbei werden die Karten (bis auf die letzte) solange gedreht, wie sie auf die vorhergehende passen und dabei wird die Punktzahl errechnet.
c-anf hat gesagt.:
Wie komme ich von den Karten aus karten.txt zu ausgabe.txt?
Das ist nicht einfach. Zuerst musst du die Codes einpassen (als Stellvertreter für die "wirkliche" Karte). Dann musst du die Karte von den char** - arrays auflösen und immer zuerst die oberste Linie zeichnen, dann ein "\n" und die nächste Zeile schreiben. Dazu brauchst du die Positionen der Karte. Ist nicht einfach, ich versuche es auch schon eine Zeit lang. Ich melde mich wieder, wenn ich etwas habe.

Gruss
cwriter
 

Neue Beiträge

Zurück