4-Gewinnt Problem



  • also die größe des spielfeldes ist durch die aufgabenstellung festgelegt.

    i hat werte zwischen 0 und 4 und k nimmt werte zwischen 0 und 7 an ?!
    Aber hieran kann ja kein Fehler liegen oder?
    Denn die vertikale gewinnabfrage klappt.



  • Mir ist gerade aufgefallen dass bei der vertikalen abfrage auch nur der erste fall funktioniert.

    Aber was ist an meiner Lösung falsch? und wie kann ich es anders machen?



  • Die Probleme fangen damit an, daß

    Dulfried schrieb:

    int f = 4;
    
    while (feld[f][s] != 32){
    	f--;
    }
    feld[f][s] == 'X';
    

    nicht tut was du denks/willst.



  • Und ich kann DirkB und dachschaden nur zustmmen.

    dachschaden schrieb:

    Nee, Jung. DirkB hat dir bereits geschrieben, dass du für so was kleine Funktionen schreiben sollst, die Teilaufgaben übernehmen. [...]

    Schreibe für jedes Teilproblem eine Funktion. Teste sie. Beginne mit den simplen. Zum Bleistift:

    #include <assert.h>
    #include <stddef.h>
    #include <stdbool.h>
    #include <memory.h>
    #include <stdio.h>
    
    void clear( FILE * input_stream )
    {
    	assert( input_stream );
    	int ch;
    	while( ( ch = fgetc( input_stream ) ) != '\n' && ch != EOF );
    }
    
    typedef enum board_size_tag {
    	BOARD_WIDTH   = 16,
    	BOARD_HEIGHT  = 24
    } board_size_t;
    
    typedef enum player_tag {
    	PLAYER_NONE,
    	PLAYER_1,
    	PLAYER_2,
    } player_t;
    
    char const player_symbols[] = { ' ', 'X', 'O' };
    
    typedef struct connect_four_tag
    {
    	player_t  board[ BOARD_HEIGHT * BOARD_WIDTH ];
    	player_t  current_player;
    	size_t    num_rounds;
    	size_t    last_move_row;
    	size_t    last_move_column;
    } connect_four_t;
    
    void connect_four_create( connect_four_t * connect_four )
    {
    	assert( connect_four );
    
    	memset( connect_four->board, 0, sizeof connect_four->board );
    	connect_four->current_player = PLAYER_1;
    	connect_four->num_rounds = 0;
    }
    
    void print( connect_four_t * connect_four )
    {
    	size_t y;
    	size_t x;
    	assert( connect_four );
    
    	printf( "    " );
    	for( x = 0; x < BOARD_WIDTH; ++x )
    		printf( "%2d ", x + 1 );
    	putchar( '\n' );
    
    	for( y = 0; y < BOARD_HEIGHT && printf( " %2d ", BOARD_HEIGHT - y ); printf( " %2d\n", BOARD_HEIGHT - y ), ++y )
    		for( x = 0; x < BOARD_WIDTH; ++x )
    			printf( "%2c ", player_symbols[ connect_four->board[ y * BOARD_WIDTH + x ] ] );
    
    	printf( "    " );
    	for( x = 0; x < BOARD_WIDTH; ++x )
    		printf( "%2d ", x + 1 );
    	putchar( '\n' );
    }
    
    char get_player_symbol( connect_four_t * connect_four )
    {
    	assert( connect_four );
    	return player_symbols[ connect_four->current_player ];
    }
    
    player_t get_piece_at( connect_four_t * connect_four, size_t row, size_t column )
    {
    	assert( connect_four && row < BOARD_HEIGHT && column < BOARD_WIDTH );
    	return connect_four->board[ row * BOARD_WIDTH + column ];
    }
    
    void set_last_move( connect_four_t * connect_four, size_t row, size_t column )
    {
    	assert( row < BOARD_HEIGHT && column < BOARD_WIDTH );
    	connect_four->last_move_row     = row;
    	connect_four->last_move_column  = column;
    }
    
    void set_piece_at( connect_four_t * connect_four, size_t row, size_t column )
    {
    	assert( connect_four && row < BOARD_HEIGHT && column < BOARD_WIDTH );
    	++connect_four->num_rounds;
    	connect_four->board[ row * BOARD_WIDTH + column ] = connect_four->current_player;
    	set_last_move( connect_four, row, column );
    }
    
    bool drop_piece( connect_four_t * connect_four, size_t column )
    {
    	size_t row;
    	assert( connect_four && column < BOARD_WIDTH );
    
    	for( row = 0; row < BOARD_HEIGHT && !get_piece_at( connect_four, row, column ); ++row );
    
    	if( !row )
    		return false;
    
    	set_piece_at( connect_four, --row, column );
    	return true;
    }
    
    void switch_players( connect_four_t * connect_four )
    {
    	assert( connect_four );
    	connect_four->current_player = ( connect_four->current_player == PLAYER_1 ? PLAYER_2 : PLAYER_1 );
    }
    
    player_t get_winner( connect_four_t * connect_four )
    {
        size_t    row     = connect_four->last_move_row;
        size_t    column  = connect_four->last_move_column;
        player_t  winner  = connect_four->current_player;
        size_t offset;
        assert( connect_four );
    
    	for( offset = 1;
    	     column           >=  offset       &&  get_piece_at( connect_four, row, column - offset ) == winner ||
    	     column + offset  <   BOARD_WIDTH  &&  get_piece_at( connect_four, row, column + offset ) == winner;
    	     ++offset );
    
    	if( offset >= 4 )
    		return winner;
    
    	for( offset = 1;
    	     row           >=  offset        &&  get_piece_at( connect_four, row - offset, column ) == winner ||
    	     row + offset  <   BOARD_HEIGHT  &&  get_piece_at( connect_four, row + offset, column ) == winner;
    	     ++offset );
    
    	if( offset >= 4 )
    		return winner;
    
    	for( offset = 1;
    	     row           >=  offset        &&  column           >=  offset       &&  get_piece_at( connect_four, row - offset, column - offset ) == winner ||
    	     row           >=  offset        &&  column + offset  <   BOARD_WIDTH  &&  get_piece_at( connect_four, row - offset, column + offset ) == winner ||
    	     row + offset  <   BOARD_HEIGHT  &&  column           >=  offset       &&  get_piece_at( connect_four, row + offset, column - offset ) == winner ||
    	     row + offset  <   BOARD_HEIGHT  &&  column + offset  <   BOARD_WIDTH  &&  get_piece_at( connect_four, row + offset, column + offset ) == winner;
    	     ++offset );
    
    	return offset >= 4 ? winner : PLAYER_NONE;
    }
    
    bool move_possible( connect_four_t * connect_four )
    {
    	return connect_four->num_rounds < BOARD_WIDTH * BOARD_HEIGHT;
    }
    
    int main( void )
    {
    	connect_four_t  connect_four;
    	player_t        winner;
    	size_t          column;
    
    	connect_four_create( &connect_four );
    
    	do {
    		switch_players( &connect_four );
    		print( &connect_four );
    
    		while( printf( "\nPlayer %c: Which column (1-%d) would you like to place your piece in?\nInput > ", get_player_symbol( &connect_four ), BOARD_WIDTH ),
    		       scanf( "%d", &column ) != 1 || !column || column > BOARD_WIDTH || !drop_piece( &connect_four, --column ) )
    		{
    			fputs( "\nInput error. Please try again.\n\n", stderr );
    			clear( stdin );
    		}
    
    	} while( !( winner = get_winner( &connect_four ) ) && move_possible( &connect_four ) );
    
    	print( &connect_four );
    
    	if( !winner )
    		puts( "\nThere are no further moves possible.\n" );
    	else
    		printf( "\nPlayer %d (%c) won.\n\n", winner, get_player_symbol( &connect_four ) );
    }
    


  • int f = 4;
    
    while (feld[f][s] != 32){
        f--;
    }
    feld[f][s] = 'X';
    

    Hier musst du beachten, dass ich das == verbessert habe. Also ich möchte mit dieser Funktion bewirken, dass erkannt wird ob das Feld schon belegt ist und man die Zeilen von unten nach oben durchprüft. Sobald dann ein Platz unbelegt(32) ist, soll dort das Zeichen gespeichert werden.

    Was ist an dieser Überlegung falsch?

    Danke für deine Mühe, kann mit deinem Code aber leider nicht viel anfangen. Weiß oft nicht ob du da fertige Funktionen benutzt oder was das überhaupt sein soll 😕



  • Ich wäre auch dankbar wenn ihr mir sagen könntet was genau nicht bei meiner Gewinnabfrage funktioniert. Damit ich diese überarbeiten kann.

    PS: Ich arbeite nacher auch noch mit funktionen, habe bisher ja die Funktion für das darstellen des Feldes und auswählen der Zeile erstellt



  • OK, ein Versuch noch dir zu helfen.
    Laß dir mal die Werte von i und k vor der Gewinnabfrage ausgeben (bzw. benutze den Debugger dafür und setze einen Breakpoint dorthin).

    Und nochmals: du willst die beiden Variablen f und s für die Abfrage benutzen!!!



  • Dulfried1 schrieb:

    int f = 4;
     
    while (feld[f][s] != 32){
        f--;
    }
    feld[f][s] = 'X';
    

    Hier musst du beachten, dass ich das == verbessert habe. [...]

    Aha. Und woher soll man das riechen wenn du es weder sagst noch vollständigen Code zeigst?

    Dulfried1 schrieb:

    [...] kann mit deinem Code aber leider nicht viel anfangen. Weiß oft nicht ob du da fertige Funktionen benutzt oder was das überhaupt sein soll 😕

    Die einzigen "fertigen" Funktionen die ich benutzt habe sind puts() , fputs() , memset() , printf() , putchar() und scanf() . Ich wollte dir nur zeigen, wie man etwas "großes" in möglichst klitzekleine Teilbrobleme zerlegt.

    Zeig doch mal kompletten Code ...



  • dass mit dem == hat dirkB vor ein paar antworten schon korrigiert.

    Habe jetzt verstanden wieso es nicht funktioniert hat, ich muss bei der Gewinnabfrage i und k auch von 0 bis 4 bzw. 6 durchlaufen lassen. Habe es deshalb zwischen die Ausgabe des Feldes gepackt.

    Ich muss jetzt nur noch die diagonale Gewinnabfrage machen und wäre nett, wenn ihr mir zeigen könntet, wie ich meine bisherigen Gewinnabfragen in eine Funktion packe und diese dann wieder aufrufe.

    int main()
    {
    
    	char feld[5][7] = { { 32, 32, 32, 32, 32, 32, 32 }, { 32, 32, 32, 32, 32, 32, 32 }, { 32, 32, 32, 32, 32, 32, 32 }, { 32, 32, 32, 32, 32, 32, 32 }, { 32, 32, 32, 32, 32, 32, 32 } };
    	int s = 0, i = 0, k = 0;       //s=spalte
    	int gewonnen1 = 0, gewonnen2 = 0;
    	int reihe = 1;
    
    	for (int i = 0; i < 5; i++){
    
    		for (k = 0; k < 7; k++){
    			printf("%c", feld[i][k]);
    		}
    		printf("\n");
    	}
    
    	while (gewonnen1 != 1 && gewonnen2 != 1){
    
    		if (reihe == 1){
    			printf("Spieler1: In welche Spalte wollen Sie ihren Spielchip setzen?\n");
    			scanf("%d", &s);
    
    			system("cls");
    
    			int f = 4;
    
    			while (feld[f][s] != 32){
    				f--;
    			}
    			feld[f][s] = 'X';
    
    			for (int i = 0; i < 5; i++){
    
    				for (int k = 0; k < 7; k++){
    
    					//Gewinnabfrage vertikal
    					if (i < 2 && i >= 0 && k < 7 && k >= 0){
    						if (feld[i][k] == 'X'  && feld[i + 1][k] == 'X' && feld[i + 2][k] == 'X' && feld[i + 3][k] == 'X'){
    							gewonnen1 = 1;
    						}
    						if (feld[i + 1][k] == 'X'  && feld[i + 2][k] == 'X' && feld[i + 3][k] == 'X' && feld[i + 4][k] == 'X'){
    							gewonnen1 = 1;
    						}
    					}
    					//Gewinnabfrage horizontal
    					if (i <= 4 && i >= 0 && k <= 3 && k >= 0){
    						if (feld[i][k] == 'X'  && feld[i][k + 1] == 'X' && feld[i][k + 2] == 'X' && feld[i][k + 3] == 'X'){
    							gewonnen1 = 1;
    						}
    						if (feld[i][k + 1] == 'X'  && feld[i][k + 2] == 'X' && feld[i][k + 3] == 'X' && feld[i][k + 4] == 'X'){
    							gewonnen1 = 1;
    						}
    						if (feld[i][k + 2] == 'X'  && feld[i][k + 3] == 'X' && feld[i][k + 4] == 'X' && feld[i][k + 5] == 'X'){
    							gewonnen1 = 1;
    						}
    						if (feld[i][k + 3] == 'X'  && feld[i][k + 4] == 'X' && feld[i][k + 5] == 'X' && feld[i][k + 6] == 'X'){
    							gewonnen1 = 1;
    						}
    					}
    
    					printf("%c", feld[i][k]);
    				}
    				printf("\n");
    				reihe = 2;
    			}
    
    			if (gewonnen1 == 1){
    				printf("Spieler 1 hat gewonnen!\n");
    			}
    			else{}
    		}
    
    		else{
    			printf("Spieler2: In welche Spalte wollen Sie ihren Spielchip setzen?\n");
    			scanf("%d", &s);
    
    			system("cls");
    
    			int f = 4;
    
    			while (feld[f][s] != 32){
    				f--;
    			}
    			feld[f][s] = 'O';
    
    			for (int i = 0; i < 5; i++){
    
    				for (int k = 0; k < 7; k++){
    
    					//Gewinnabfrage vertikal
    					if (i < 2 && i >= 0 && k < 7 && k >= 0){
    						if (feld[i][k] == 'O'  && feld[i + 1][k] == 'O' && feld[i + 2][k] == 'O' && feld[i + 3][k] == 'O'){
    							gewonnen2 = 1;
    						}
    						if (feld[i + 1][k] == 'O'  && feld[i + 2][k] == 'O' && feld[i + 3][k] == 'O' && feld[i + 4][k] == 'O'){
    							gewonnen2 = 1;
    						}
    					}
    					//Gewinnabfrage horizontal
    					if (i <= 4 && i >= 0 && k <= 3 && k >= 0){
    						if (feld[i][k] == 'O'  && feld[i][k + 1] == 'O' && feld[i][k + 2] == 'O' && feld[i][k + 3] == 'O'){
    							gewonnen2 = 1;
    						}
    						if (feld[i][k + 1] == 'O'  && feld[i][k + 2] == 'O' && feld[i][k + 3] == 'O' && feld[i][k + 4] == 'O'){
    							gewonnen2 = 1;
    						}
    						if (feld[i][k + 2] == 'O'  && feld[i][k + 3] == 'O' && feld[i][k + 4] == 'O' && feld[i][k + 5] == 'O'){
    							gewonnen2 = 1;
    						}
    						if (feld[i][k + 3] == 'O'  && feld[i][k + 4] == 'O' && feld[i][k + 5] == 'O' && feld[i][k + 6] == 'O'){
    							gewonnen2 = 1;
    						}
    					}
    
    					printf("%c", feld[i][k]);
    				}
    				printf("\n");
    				reihe = 1;
    			}
    		}
    
    		if (gewonnen2 == 1){
    			printf("Spieler 2 hat gewonnen!\n");
    		}
    
    	}
    
    	system("pause");
    	return 0;
    }
    


  • Dulfried1 schrieb:

    #include <stdio.h>   // vielen dank, dasz du es mich
    #include <stdlib.h>  // selbst hinschreiben laesst
    
    int main()
    {
        char feld[5][7] = { { 32, 32,  // yay ... memset() ist was tolles.
        int s = 0, i = 0, k = 0;       // s=spalte // <== Ja toll. Wieso nennst du es dann nicht "spalte" !?
        int gewonnen1 = 0, gewonnen2 = 0;  // Versteh ich nicht. Gewinnen kann eh immer nur der Spieler, der an der Reihe ist!?
        int reihe = 1;  // reihe ... reihe ... hm ... die "reihe", "row" ist doch f!? ... wait ... reihe ist der Spieler, der an der Reihe ist??
    	// dann ist das bloed, denn ein "Spieler" ist kein int. Ein Spieler ist ein Kon_struct_ (<- hint, hint!) dasz den Spieler beschreibt.
    	// ist er der Anziehende oder der Nachziehende (reihe == 1 oder reihe == 2)? Welches Symbol repraesentiert ihn?
       
     
        for (int i = 0; i < 5; i++){  // "habe bisher ja die Funktion für das darstellen des Feldes und auswählen der Zeile erstellt" ach so?
     
            for (k = 0; k < 7; k++){
                printf("%c", feld[i][k]);
            }
            printf("\n");
        }
    
    	// im weiteren Codeduplikation die im Prinzip zweimal dasselbe macht. Variablen, Mensch!
    

Anmelden zum Antworten