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;
}