C-Kurs/TicTacToe/Musterlösung: Unterschied zwischen den Versionen
(Musterlösung zur TicTacToe aufgabe) |
Martin (Diskussion | Beiträge) (überarbeitet) |
||
Zeile 1: | Zeile 1: | ||
− | |||
− | |||
<pre> | <pre> | ||
#include <stdio.h> | #include <stdio.h> | ||
− | #include < | + | #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 | // Konvertiert Mauskoordinaten in Spielfeldkoordinaten | ||
Zeile 73: | Zeile 24: | ||
} | } | ||
− | + | // 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[]) { | 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); | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
// 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; | ||
} | } | ||
− | |||
− | |||
− | |||
− | |||
− | + | // 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; | ||
} | } | ||
− | + | ||
− | + | // Kreuzgrafik laden | |
− | + | SDL_Surface *cross = SDL_LoadBMP("images/cross.bmp"); | |
− | |||
− | 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( | + | 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; | SDL_Event event; | ||
− | + | int row, col; | |
− | + | int quit = 0, turn = 0, player = PLAYER_A; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
// Event-Loop | // Event-Loop | ||
while (!quit) { | while (!quit) { | ||
− | |||
if (SDL_PollEvent(&event)) { | if (SDL_PollEvent(&event)) { | ||
switch (event.type) { | switch (event.type) { | ||
− | |||
case SDL_MOUSEBUTTONDOWN: | 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; | 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; }