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

(Musterlösung zur TicTacToe aufgabe)
 
(ü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;
}