Zum Inhalt springen
Sitzung: Jeden Freitag in der Vorlesungszeit ab 16 Uhr c. t. im MAR 0.005. In der vorlesungsfreien Zeit unregelmäßig (Jemensch da?). Macht mit!

C-Kurs/TicTacToe/Musterlösung: Unterschied zwischen den Versionen

Aus FreitagsrundenWiki
Musterlösung zur TicTacToe aufgabe
 
Martin (Diskussion | Beiträge)
überarbeitet
Zeile 1: Zeile 1:
Nicht so schöne aber hoffentlich funktionierende Musterlösung
<pre>
<pre>
#include <stdio.h>
#include <stdio.h>
#include <SDL.h>
#include <stdlib.h>
 
#include <SDL/SDL.h>
#define EMPTY 0
#define PLAYER_A 1
#define PLAYER_B 2
#define ROWS 3
#define COLS 3
 
int field[ROWS][COLS];
 
void reset_board(){
int i,j;
i=j=0;
for(i=0; i<ROWS; i++){
for(j=0;j<COLS; j++)
field[i][j] = EMPTY;
}
}
 
void draw_board(SDL_Surface *screen, SDL_Surface *background, SDL_Surface *circle, SDL_Surface *cross){
// Hintergrund ins Fenster zeichnen
    SDL_BlitSurface(background, NULL, screen, NULL);
    SDL_Flip(screen);
   


SDL_Rect offset;
#define ROWS    3
offset.x = 25;
#define COLS    3
offset.y = 25;


int i,j;
#define EMPTY     -1
i=j=0;
#define PLAYER_A   0
//iterate over the field
#define PLAYER_B   1
for(i=0; i<ROWS; i++){
for(j=0;j<COLS; j++){
switch(field[i][j]){
// empty nothing to do
case EMPTY:
break;
// player A draaw circle
case PLAYER_A:
SDL_BlitSurface(circle, NULL, screen, &offset);
SDL_Flip(screen);
break;
// player B draw cross
case PLAYER_B:
SDL_BlitSurface(cross, NULL, screen, &offset);
SDL_Flip(screen);
break;
}
//next rectangle we want to draw
offset.x += 100;
}
offset.y +=100;
//reset x to start at top
offset.x = 25;
}


}
// Spielfeld definieren
int board[ROWS][COLS];


// Konvertiert Mauskoordinaten in Spielfeldkoordinaten
// Konvertiert Mauskoordinaten in Spielfeldkoordinaten
Zeile 73: Zeile 24:
}
}


int check_win(int player){
// Zeichnet das Spielfeld
int i,j;
void draw_board(SDL_Surface *back, SDL_Surface *circle, SDL_Surface *cross) {
i=j=0;
    SDL_BlitSurface(back, NULL, SDL_GetVideoSurface(), NULL);
int row_zero = (field[0][0] == player) && (field[0][1] == player) && (field[0][2] == player);
int row_one =  (field[1][0] == player) && (field[1][1] == player) && (field[1][2] == player);
int row_two =  (field[2][0] == player) && (field[2][1] == player) && (field[2][2] == player);
int col_zero = (field[0][0] == player) && (field[1][0] == player) && (field[2][0] == player);
int col_one =  (field[0][1] == player) && (field[1][1] == player) && (field[2][1] == player);
int col_two =  (field[0][2] == player) && (field[1][2] == player) && (field[2][2] == player);


int diag_one = (field[0][0] == player) && (field[1][1] == player) && (field[2][2] == player);
    SDL_Rect offset;
int diag_two = (field[0][2] == player) && (field[1][1] == player) && (field[2][0] == player);
    int row, col;
    for (row=0; row<ROWS; row++) {
        for (col=0; col<COLS; col++) {
            offset.x = 25+100*col;
            offset.y = 25+100*row;
            if (board[row][col] == PLAYER_A) {
                SDL_BlitSurface(circle, NULL, SDL_GetVideoSurface(), &offset);
            } else if (board[row][col] == PLAYER_B) {
                SDL_BlitSurface(cross, NULL, SDL_GetVideoSurface(), &offset);
            }
        }
    }


return row_zero || row_one || row_two || col_zero || col_one || col_two || diag_one || diag_two;
    SDL_Flip(SDL_GetVideoSurface());
}


// Gibt 1 zurück, falls der übergebene Spieler gewonnen hat, andernfalls 0
int check_win(int player) {
    int row, col;
    // horizontal
    for (row=0; row<ROWS; row++) {
        if ((board[row][0] == player) && (board[row][1] == player) && (board[row][2] == player))
            return 1;
    }
   
    // vertikal
    for (col=0; col<COLS; col++) {
        if ((board[0][col] == player) && (board[1][col] == player) && (board[2][col] == player))
            return 1;
    }
   
    // diagonal 1
    if ((board[0][0] == player) && (board[1][1] == player) && (board[2][2] == player)) {
        return 1;
    }
   
    // diagonal 2
    if ((board[0][2] == player) && (board[1][1] == player) && (board[2][0] == player)) {
        return 1;
    }
   
    return 0;
}
}


int check_full(){
void reset_board() {
int i,j;
    int row, col;
for(i=0; i<ROWS; i++){
    for (row=0; row<ROWS; row++) {
for(j=0;j<COLS; j++){
        for (col=0; col < COLS; col++) {
if(field[i][j] == EMPTY)
            board[row][col] = EMPTY;
return 0;
        }
}
    }
}
return 1;
}
}


int wait_for_click() {
    SDL_Event event;
    while (1) {
        if (SDL_PollEvent(&event)) {
            if (event.type == SDL_MOUSEBUTTONDOWN)
                return 0;
            else if (event.type == SDL_QUIT)
                return 1;
        }
        SDL_Delay(10);
    }
}


int main(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
Zeile 110: Zeile 101:
         return 1;
         return 1;
     }
     }
   
 
     // SDL bei Programmende automatisch schließen lassen
     // SDL bei Programmende automatisch schließen lassen
     atexit(SDL_Quit);
     atexit(SDL_Quit);
    // Fenster für Grafikausgabe öffnen
    SDL_Surface *screen = SDL_SetVideoMode(350, 350, 32, SDL_SWSURFACE);
    if ( screen == NULL ) {
        printf("Fehler beim Öffnen des Ausgabefensters: %s\n", SDL_GetError());
        return 1;
    }
    SDL_WM_SetCaption("Freitagsrunde presents: TicTacToe", NULL);


     // Hintergrundgrafik laden
     // Hintergrundgrafik laden
     SDL_Surface *background = SDL_LoadBMP("background.bmp");
     SDL_Surface *background = SDL_LoadBMP("images/background.bmp");
     if (background == NULL) {
     if (background == NULL) {
         printf("Fehler beim Laden von background.bmp: %s\n", SDL_GetError());
         printf("Fehler beim Laden von background.bmp: %s\n", SDL_GetError());
         return 1;
         return 1;
     }
     }
   
// Hintergrund ins Fenster zeichnen
    SDL_BlitSurface(background, NULL, screen, NULL);
    SDL_Flip(screen);


// Kreisgrafik laden
    // Kreisgrafik laden
     SDL_Surface *circle = SDL_LoadBMP("circle.bmp");
     SDL_Surface *circle = SDL_LoadBMP("images/circle.bmp");
     if (circle == NULL) {
     if (circle == NULL) {
         printf("Fehler beim Laden von circle.bmp: %s\n", SDL_GetError());
         printf("Fehler beim Laden von circle.bmp: %s\n", SDL_GetError());
         return 1;
         return 1;
     }
     }
    // grünen Hintergrund transparent machen
 
     SDL_SetColorKey(circle, SDL_SRCCOLORKEY, SDL_MapRGB(circle->format, 0x00,0xFF,0x00));
     // Kreuzgrafik laden
     SDL_Surface *cross = SDL_LoadBMP("images/cross.bmp");
// Kreisgrafik laden
     SDL_Surface *cross = SDL_LoadBMP("cross.bmp");
     if (cross == NULL) {
     if (cross == NULL) {
         printf("Fehler beim Laden von cross.bmp: %s\n", SDL_GetError());
         printf("Fehler beim Laden von cross.bmp: %s\n", SDL_GetError());
         return 1;
         return 1;
     }
     }
     // grünen Hintergrund transparent machen
     // grünen Hintergrund transparent machen
     SDL_SetColorKey(cross, SDL_SRCCOLORKEY, SDL_MapRGB(circle->format, 0x00,0xFF,0x00));
    SDL_SetColorKey(circle, SDL_SRCCOLORKEY, SDL_MapRGB(circle->format, 0x00,0xFF,0x00));
     SDL_SetColorKey(cross, SDL_SRCCOLORKEY, SDL_MapRGB(cross->format, 0x00,0xFF,0x00));
 
    // Fenster für Grafikausgabe öffnen
    SDL_Surface *screen = SDL_SetVideoMode(350, 350, 32, SDL_SWSURFACE);
    if ( screen == NULL ) {
        printf("Fehler beim Öffnen des Ausgabefensters: %s\n", SDL_GetError());
        return 1;
    }
 
    SDL_WM_SetCaption("Freitagsrunde presents: TicTacToe", NULL);
   
    // Spielfeld initialisieren und zeichnen
    reset_board();
    draw_board(background, circle, cross);
      
      
int quit = 0;
     SDL_Event event;
     SDL_Event event;
     SDL_Rect offset;
     int row, col;
    int quit = 0, turn = 0, player = PLAYER_A;
 
int return_code=0;
int row, column;
row=column=0;
 
int current_player = 0;
int reset = 0;
int full = 0;
      
      
     // Event-Loop
     // Event-Loop
     while (!quit) {
     while (!quit) {
        // Event vorhanden?
         if (SDL_PollEvent(&event)) {
         if (SDL_PollEvent(&event)) {
             switch (event.type) {
             switch (event.type) {


                // Mousebutton wurde gedrückt
                 case SDL_MOUSEBUTTONDOWN:
                 case SDL_MOUSEBUTTONDOWN:
current_player = 1 - current_player;
                    // Maus-Koordinaten in Spielfelfkoordinaten umrechnen
convert_coords(event.button.x, event.button.y, &row, &column);
                    convert_coords(event.button.x, event.button.y, &row, &col);
//it is player A's turn
 
if(current_player){
                    // Ist die Zelle noch frei?
//check if player is allowed to set this field
                    if (board[row][col] != EMPTY)
if(field[row][column] != EMPTY){
                        break;
//not allowed his turn again
                       
current_player = 1-current_player;
                    // Zelle besetzen und zeichnen
break;
                    board[row][col] = player;
}
                    draw_board(background, circle, cross);
//was allowed set the field
 
field[row][column] = PLAYER_A;
                    turn++;
if(check_win(PLAYER_A)){
//Set a Message
SDL_WM_SetCaption("Spieler 1 hat gewonnen", NULL);
reset = 1;
}
//it is player B's turn
} else {
//check if player is allowed to set this field
if(field[row][column] != EMPTY){
//not allowed his turn again
current_player = 1-current_player;
break;
}
//was allowed set the field
field[row][column] = PLAYER_B;
if(check_win(PLAYER_B)){
//Set a Message
SDL_WM_SetCaption("Spieler 2 hat gewonnen", NULL);
reset = 1;
}
}
full = check_full();
if(full){
// no empty fields and no winner
SDL_WM_SetCaption("Unentscheiden", NULL);
}
reset = reset || full;
//winner or field is full
if(reset){
reset_board();
// Hintergrund ins Fenster zeichnen
SDL_BlitSurface(background, NULL, screen, NULL);
SDL_Flip(screen);
reset = 0;
}


//draw the board
                    if (check_win(player) || (turn == ROWS*COLS)) {
draw_board(screen, background, circle, cross);
                        if (check_win(player)) {
                            // aktueller Spieler hat gewonnen
                            if (player == PLAYER_A) {
                                SDL_WM_SetCaption("Spieler A hat gewonnen!", NULL);
                            } else {
                                SDL_WM_SetCaption("Spieler B hat gewonnen!", NULL);
                            }
                        } else {
                            // Unentschieden
                            SDL_WM_SetCaption("Unentschieden", NULL);
                        }
                           
                        quit = wait_for_click();
                   
                        // nächste runde vorbereiten
                        SDL_WM_SetCaption("Freitagsrunde presents: TicTacToe", NULL);
                        reset_board();
                        draw_board(background, circle, cross);
                        turn = 0;
                    }


                    player = 1 - player;
                     break;
                     break;



Version vom 22. September 2010, 21:14 Uhr

#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>

#define ROWS    3
#define COLS    3

#define EMPTY      -1
#define PLAYER_A    0
#define PLAYER_B    1

// Spielfeld definieren
int board[ROWS][COLS];

// Konvertiert Mauskoordinaten in Spielfeldkoordinaten
void convert_coords(int x, int y, int *row, int *column) {
    *row = (y-25) / 100;
    if (*row < 0) *row = 0;
    if (*row >= ROWS) *row = ROWS-1;
    *column = (x-25) / 100;
    if (*column < 0) *column = 0;
    if (*column >= COLS) *column = COLS-1;
}

// Zeichnet das Spielfeld
void draw_board(SDL_Surface *back, SDL_Surface *circle, SDL_Surface *cross) {
    SDL_BlitSurface(back, NULL, SDL_GetVideoSurface(), NULL);

    SDL_Rect offset;
    int row, col;
    for (row=0; row<ROWS; row++) {
        for (col=0; col<COLS; col++) {
            offset.x = 25+100*col;
            offset.y = 25+100*row;
            if (board[row][col] == PLAYER_A) {
                SDL_BlitSurface(circle, NULL, SDL_GetVideoSurface(), &offset);
            } else if (board[row][col] == PLAYER_B) {
                SDL_BlitSurface(cross, NULL, SDL_GetVideoSurface(), &offset);
            }
        }
    }

    SDL_Flip(SDL_GetVideoSurface());
}

// Gibt 1 zurück, falls der übergebene Spieler gewonnen hat, andernfalls 0
int check_win(int player) {
    int row, col;
    // horizontal
    for (row=0; row<ROWS; row++) {
        if ((board[row][0] == player) && (board[row][1] == player) && (board[row][2] == player))
            return 1;
    }
    
    // vertikal
    for (col=0; col<COLS; col++) {
        if ((board[0][col] == player) && (board[1][col] == player) && (board[2][col] == player))
            return 1;
    }
    
    // diagonal 1
    if ((board[0][0] == player) && (board[1][1] == player) && (board[2][2] == player)) {
        return 1;
    }
    
    // diagonal 2
    if ((board[0][2] == player) && (board[1][1] == player) && (board[2][0] == player)) {
        return 1;
    }
    
    return 0;
}

void reset_board() {
    int row, col;
    for (row=0; row<ROWS; row++) {
        for (col=0; col < COLS; col++) {
            board[row][col] = EMPTY;
        }
    }
}

int wait_for_click() {
    SDL_Event event;
    while (1) {
        if (SDL_PollEvent(&event)) {
            if (event.type == SDL_MOUSEBUTTONDOWN)
                return 0;
            else if (event.type == SDL_QUIT)
                return 1;
        }
        SDL_Delay(10);
    }
}

int main(int argc, char *argv[]) {
    // Grafiksubsystem der SDL initialisieren
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("SDL konnte nicht initialisiert werden: %s\n", SDL_GetError());
        return 1;
    }

    // SDL bei Programmende automatisch schließen lassen
    atexit(SDL_Quit);

    // Hintergrundgrafik laden
    SDL_Surface *background = SDL_LoadBMP("images/background.bmp");
    if (background == NULL) {
        printf("Fehler beim Laden von background.bmp: %s\n", SDL_GetError());
        return 1;
    }

    // Kreisgrafik laden
    SDL_Surface *circle = SDL_LoadBMP("images/circle.bmp");
    if (circle == NULL) {
        printf("Fehler beim Laden von circle.bmp: %s\n", SDL_GetError());
        return 1;
    }

    // Kreuzgrafik laden
    SDL_Surface *cross = SDL_LoadBMP("images/cross.bmp");
    if (cross == NULL) {
        printf("Fehler beim Laden von cross.bmp: %s\n", SDL_GetError());
        return 1;
    }

    // grünen Hintergrund transparent machen
    SDL_SetColorKey(circle, SDL_SRCCOLORKEY, SDL_MapRGB(circle->format, 0x00,0xFF,0x00));
    SDL_SetColorKey(cross, SDL_SRCCOLORKEY, SDL_MapRGB(cross->format, 0x00,0xFF,0x00));

    // Fenster für Grafikausgabe öffnen
    SDL_Surface *screen = SDL_SetVideoMode(350, 350, 32, SDL_SWSURFACE);
    if ( screen == NULL ) {
        printf("Fehler beim Öffnen des Ausgabefensters: %s\n", SDL_GetError());
        return 1;
    }

    SDL_WM_SetCaption("Freitagsrunde presents: TicTacToe", NULL);
    
    // Spielfeld initialisieren und zeichnen
    reset_board();
    draw_board(background, circle, cross);
    
    SDL_Event event;
    int row, col;
    int quit = 0, turn = 0, player = PLAYER_A;
    
    // Event-Loop
    while (!quit) {
        if (SDL_PollEvent(&event)) {
            switch (event.type) {

                case SDL_MOUSEBUTTONDOWN:
                    // Maus-Koordinaten in Spielfelfkoordinaten umrechnen
                    convert_coords(event.button.x, event.button.y, &row, &col);

                    // Ist die Zelle noch frei?
                    if (board[row][col] != EMPTY)
                        break;
                        
                    // Zelle besetzen und zeichnen
                    board[row][col] = player;
                    draw_board(background, circle, cross);

                    turn++;

                    if (check_win(player) || (turn == ROWS*COLS)) {
                        if (check_win(player)) {
                            // aktueller Spieler hat gewonnen
                            if (player == PLAYER_A) {
                                SDL_WM_SetCaption("Spieler A hat gewonnen!", NULL);
                            } else {
                                SDL_WM_SetCaption("Spieler B hat gewonnen!", NULL);
                            }
                        } else {
                            // Unentschieden
                            SDL_WM_SetCaption("Unentschieden", NULL);
                        }
                            
                        quit = wait_for_click();
                     
                        // nächste runde vorbereiten
                        SDL_WM_SetCaption("Freitagsrunde presents: TicTacToe", NULL);
                        reset_board();
                        draw_board(background, circle, cross);
                        turn = 0;
                    }

                    player = 1 - player;
                    break;

                case SDL_QUIT:
                    quit = 1;
                    break;
            }
        }
    }
    
    // Fenster schließen
    SDL_FreeSurface(screen);
    
    return 0;
}