diff --git a/src/main/c/Georg/tictactoe.c b/src/main/c/Georg/tictactoe.c new file mode 100644 index 0000000..fcade80 --- /dev/null +++ b/src/main/c/Georg/tictactoe.c @@ -0,0 +1,240 @@ +#include +#include +#include + +#include "tictactoe.h" + +void printBoard(); + +struct ticTacToe GAME; + +struct command COMMANDS[MAX_COMMANDS] = { + { 1, "\"start menu\" - startet das menu", startMenu}, + { 2, "\"start game\" - startet das spiel", startGame} +}; + +void startTicTacToe(){ + setbuf(stdout, 0); + printf( "%s\n", getWelcomeMessageTicTacToe() ); + printf( "%s\n\n", getRulesMessageTicTacToe() ); + + GAME = createTicTacToe(); + + while( GAME.currentState != -1 ){ + commandFunction command; + printf("search command!\n"); + command = getCommandById( GAME.currentState + 1); + + if( command != NULL) + command(0); + else{ + printf("command not found"); + return; + } + } +} + +char* getWelcomeMessageTicTacToe(){ + return "Hallo und willkommen zu unserem TicTacToe Spiel. Anbei die Anleitung:\n"; +} + +char* getRulesMessageTicTacToe(){ + return "Das spiel wird über die Komandozeile gespielt.\n" + "Jeder Spielzug ist eine Eingabe in die Konsole. Die enstsprechenden Befehle stehen jeweils unterhalb des Spielfelds.\n" + "Um ein Zug zu tätigen musst du \"set x,y\" in die Konsole Eingeben. Die Koordinaten stehen dabei für Zeile und Spalte.\n" + "Mit dem Befehl \"start\" startest du das Spiel" + "Mit dem Befehl \"rules\" kannst du diese Nachricht erneut aufrufen."; +} + +struct ticTacToe createTicTacToe() { + struct ticTacToe newGame; + newGame.currentState = 0; + return newGame; +} + +int handleCommand( char* input ){ + if( strcmp(input, "start menu") == 0 ){ + return 0; + }else if( strcmp(input, "start game") == 0 ){ + return 1; + }else{ + return -1; + } +} + +commandFunction getCommandById( int id ){ + commandFunction result = NULL; + size_t arraySize = sizeof(COMMANDS) / sizeof(COMMANDS[0]); + for (size_t i = 0; i < arraySize; i++) { + //printf( "%s", COMMANDS[i].description ); + if( COMMANDS[i].id == id ){ + result = COMMANDS[i].fun; + break; + } + } + return result; +} + +char* getUserInput(){ + static char userInput[MAX_INPUT_LENGTH]; + printf( ":" ); + fgets(userInput, sizeof(userInput), stdin); + + size_t len = strlen(userInput); + if (len > 0 && userInput[len - 1] == '\n') { + userInput[len - 1] = '\0'; + } + + return userInput; +} + +void initializeBoard( bool board[BORAD_SIZE][BORAD_SIZE] ){ + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + board[i][j] = 0; + } + } +} + +int handleGameInput( char* input ){ + if( strstr(input, "set") != NULL ){ + return 1; + }else{ + return -1; + } +} + +int startMenu( int code ){ + if( code == -1 ){ // command test + return 1; + } + + printf("Welcome to the menu!\n"); + + while( GAME.currentState == 0 ){ + int nextState = handleCommand( getUserInput() ); + + if( nextState == -1 ){ + printf("command not found!"); + }else{ + GAME.currentState = nextState; + } + } + + return 0; +} + +void printBoard(){ + for( int i = 0; i < BORAD_SIZE*4+1; i++ ){ + printf("-"); + } + printf("\n"); + + for (int i = 0; i < 3; ++i) { + printf("| "); + for (int j = 0; j < 3; ++j) { + if( GAME.board[i][j] == true ) + printf( "X" ); + else + printf ( " " ); + + printf(" | "); + } + printf( "\n" ); + } + + for( int i = 0; i < BORAD_SIZE*4+1; i++ ){ + printf("-"); + } + printf("\n"); +} + +int* getMarkerParameters( char* input ){ + int* array = (int*)malloc(2 * sizeof(int)); + + int index = strchr(input, ',') - input; + int firstArgument = input[index-1] - '0'; + int secondArgument = input[index+1] - '0'; + + array[0] = firstArgument-1; + array[1] = secondArgument-1; + + return array; +} + +void setBoardMarker( bool board[BORAD_SIZE][BORAD_SIZE], int* params ){ + board[params[0]][params[1]] = 1; +} + +void handleGame(){ + char* input = getUserInput(); + int nextState = handleCommand( input ); + + // check commands, if no command found return for new Input + // gameCommands are saved and processed after this block + int gameCommand = -1; + if( nextState == -1 ){ // no stateCommand + gameCommand = handleGameInput( input ); + if( gameCommand == -1 ){ + printf("command not found!"); + return; + } + }else{ + GAME.currentState = nextState; + return; + } + + // gameCommand processing + if( gameCommand == 1 ) { // set marker in field + int* params = getMarkerParameters( input ); + setBoardMarker( GAME.board, params ); + free(params); + + printBoard(); + + if( playerHasWon( GAME.board ) ){ + printf("\n\nDu hast gewonnwn!\n\n"); + // start menu + GAME.currentState=0; + } + } +} + +bool playerHasWon( bool board[BORAD_SIZE][BORAD_SIZE]){ + bool player = 1; + // Überprüfe Zeilen und Spalten + for (int i = 0; i < 3; i++) { + // Überprüfe Zeilen + if ((board[i][0] == player && board[i][1] == player && board[i][2] == player) || + // Überprüfe Spalten + (board[0][i] == player && board[1][i] == player && board[2][i] == player)) { + return true; // Spieler hat gewonnen + } + } + + // Überprüfe Diagonalen + if ((board[0][0] == player && board[1][1] == player && board[2][2] == player) || + (board[0][2] == player && board[1][1] == player && board[2][0] == player)) { + return true; // Spieler hat gewonnen + } + + return false; +} + +int startGame( int code ){ + if( code == -1 ){ // command test + return 1; + } + + printf("Welcome to the game!\n"); + bool board[BORAD_SIZE][BORAD_SIZE]; + initializeBoard( board ); + + printBoard(); + + while( GAME.currentState == 1 ){ + handleGame(); + } + + return 0; +} \ No newline at end of file diff --git a/src/main/c/Georg/tictactoe.h b/src/main/c/Georg/tictactoe.h new file mode 100644 index 0000000..efd1d1e --- /dev/null +++ b/src/main/c/Georg/tictactoe.h @@ -0,0 +1,44 @@ +#ifndef TICTACTOE_H +#define TICTACTOE_H + +#include + +#define MAX_INPUT_LENGTH 20 +#define MAX_COMMANDS 3 +#define BORAD_SIZE 3 + +struct ticTacToe{ + int currentState; + bool board[BORAD_SIZE][BORAD_SIZE]; +}; + +// Typdefinition für einen Funktionszeiger +typedef int (*commandFunction)( int ); + +struct command{ + int id; + char* description; + commandFunction fun; +}; + +extern struct ticTacToe GAME; +extern struct command COMMANDS[MAX_COMMANDS]; + + +void startTicTacToe(); +char* getWelcomeMessageTicTacToe(void); +char* getRulesMessageTicTacToe(void); +struct ticTacToe createTicTacToe(); +int handleCommand( char* input ); +void initializeBoard( bool board[3][3] ); +int handleGameInput( char* input ); +int* getMarkerParameters(); +void setBoardMarker( bool board[BORAD_SIZE][BORAD_SIZE], int* params ); +bool playerHasWon( bool board[BORAD_SIZE][BORAD_SIZE] ); + +/* commands */ +commandFunction getCommandById(int id); +int startMenu( int code ); +int startGame( int code ); + +#endif //TICTACTOE_H diff --git a/src/main/c/main.c b/src/main/c/main.c index cbaccdc..4dc37a9 100644 --- a/src/main/c/main.c +++ b/src/main/c/main.c @@ -13,6 +13,7 @@ #include #include "SchereSteinPapier.h" #include "hangman.h" +#include "tictactoe.h" void openInterface(); @@ -33,7 +34,8 @@ void openInterface() printf("\n\nHallo und willkommen bei unserer Spielesammlung!!!\n" "Du hast folgende Spiele zur Auswahl:\n\n" "1: Schere-Stein-Papier\n" - "2: Hangman\n"); + "2: Hangman\n" + "3: TicTacToe\n"); printf("\nBitte waehle die Zahl des entsprechenden Spiels aus, um damit zu starten.\nAm Ende eines Spiels kannst du mit der Taste 0 wieder zurueck zum Hauptmenue kommen.\nIm Hauptmenue beendest du mit der Auswahl 0 das Programm \n\n"); scanf_s("%d", &selection); @@ -49,10 +51,10 @@ void openInterface() case(2): hangman(); break; - /*case(3): - //Spiel() + case(3): + startTicTacToe(); break; - case(4): + /*case(4): //Spiel() break; case(5): diff --git a/src/test/c/Georg/test_tictactoe.c b/src/test/c/Georg/test_tictactoe.c new file mode 100644 index 0000000..6c2bcb5 --- /dev/null +++ b/src/test/c/Georg/test_tictactoe.c @@ -0,0 +1,358 @@ +#include "tictactoe.h" +#include "unity.h" + +void setup(void){ + +} + +void tearDown(void){ + +} + +void test_compileTest_shutBeAllwaysTrue(void){ + TEST_ASSERT_EQUAL_INT(1,1); +} + +void test_welcome_message(void){ + // arrange + char* expectedMessage = "Hallo und willkommen zu unserem TicTacToe Spiel. Anbei die Anleitung:\n"; + + // act + char* message = getWelcomeMessageTicTacToe(); + + // aassert + TEST_ASSERT_EQUAL_STRING(expectedMessage, message); +} + +void test_rules_message(void){ + // arrange + char* expectedMessage = "Das spiel wird über die Komandozeile gespielt.\n" + "Jeder Spielzug ist eine Eingabe in die Konsole. Die enstsprechenden Befehle stehen jeweils unterhalb des Spielfelds.\n" + "Um ein Zug zu tätigen musst du \"set x,y\" in die Konsole Eingeben. Die Koordinaten stehen dabei für Zeile und Spalte.\n" + "Mit dem Befehl \"start\" startest du das Spiel" + "Mit dem Befehl \"rules\" kannst du diese Nachricht erneut aufrufen."; + + // act + char* message = getRulesMessageTicTacToe(); + + // assert + TEST_ASSERT_EQUAL_STRING(expectedMessage, message); +} + +void test_initial_state(void){ + // arrange + struct ticTacToe newGame; + int expectedState = 0; + + // act + newGame = createTicTacToe(); + + // assert + TEST_ASSERT_EQUAL_INT( expectedState, newGame.currentState ); +} + +void test_command_startGame(void){ + // arrange + int expectedState = 1; + char* input = "start game"; + + // act + int actualState = handleCommand( input ); + + // assert + TEST_ASSERT_EQUAL_INT( expectedState, actualState ); +} + +void test_command_startMenu(void){ + // arrange + int expectedState = 0; + char* input = "start menu"; + + // act + int actualState = handleCommand( input ); + + // assert + TEST_ASSERT_EQUAL_INT( expectedState, actualState ); +} + +void test_checkCommandlist(void){ + // arrange + + // act + + size_t arraySize = sizeof(*COMMANDS) / sizeof(COMMANDS[0]); + for (size_t i = 0; i < arraySize; i++) { + TEST_ASSERT_EQUAL_INT( 1, COMMANDS[i].fun(-1) ); + } +} + + +void test_callCommandById(void){ + // arrange + + // act + commandFunction actualCommand = getCommandById( 1 ); + + // assert + TEST_ASSERT_EQUAL_PTR( startMenu, actualCommand ); +} + +void test_callCommandById_startGame(void){ + // arrange + + // act + commandFunction actualCommand = getCommandById( 2); + + // assert + TEST_ASSERT_EQUAL_PTR( startGame, actualCommand ); +} + + +void test_initializeBoard(void){ + // arrange + bool expectedBoard[BORAD_SIZE][BORAD_SIZE]={ + {0,0,0}, + {0,0,0}, + {0,0,0} + }; + + // act + bool actualBoard[BORAD_SIZE][BORAD_SIZE]; + initializeBoard(actualBoard); + + // assert + for (size_t i = 0; i < BORAD_SIZE; i++) { + for (size_t ii = 0; ii < BORAD_SIZE; ii++) { + TEST_ASSERT_EQUAL_INT(expectedBoard[i][ii], actualBoard[i][ii]); + } + } +} + +void test_handleGameInput(void){ + // arrange + char* teststring = "set 3,4"; + int expectedCommand = 1; + + // act + int actualState = handleGameInput( teststring ); + + // assert + TEST_ASSERT_EQUAL_INT( expectedCommand, actualState ); +} + +void test_getMarkerParameters(void){ + // arrange + char* teststring = "set 3,3"; + int expectedParams[2] = {2, 2}; + + // act + int* actualParams = getMarkerParameters( teststring ); + + // assert + for( int i = 0; i < 2; i++ ){ + TEST_ASSERT_EQUAL_INT( expectedParams[i], actualParams[i] ); + } +} + +void test_setBoardFields(){ + // arrange + // arrange + bool board[3][3]={ + {0,0,0}, + {0,0,0}, + {0,0,0} + }; + int params[2] = {2,2}; + + // act + setBoardMarker( board, params ); + + // assert + TEST_ASSERT_EQUAL_INT( 1, board[2][2] ); +} + +void test_checkOnWin_vertically(void){ + // arrange + bool board1[3][3]={ + {0,0,1}, + {0,0,1}, + {0,0,1} + }; + + bool board2[3][3]={ + {0,1,0}, + {0,1,0}, + {0,1,0} + }; + + bool board3[3][3]={ + {1,0,0}, + {1,0,0}, + {1,0,0} + }; + + // act + bool result = playerHasWon( board1 ); + bool result2 = playerHasWon( board2 ); + bool result3 = playerHasWon( board3 ); + + // assert + TEST_ASSERT_EQUAL_INT( 1, result ); + TEST_ASSERT_EQUAL_INT( 1, result2 ); + TEST_ASSERT_EQUAL_INT( 1, result3 ); +} + +void test_negativ_checkOnWin_horizontally(void){ + // arrange + bool board1[3][3]={ + {1,0,0}, + {0,0,0}, + {0,0,0} + }; + + bool board2[3][3]={ + {0,0,0}, + {0,1,0}, + {0,0,0} + }; + + bool board3[3][3]={ + {0,0,0}, + {0,0,0}, + {0,0,1} + }; + + // act + bool result = playerHasWon( board1 ); + bool result2 = playerHasWon( board2 ); + bool result3 = playerHasWon( board3 ); + + // assert + TEST_ASSERT_EQUAL_INT( 0, result ); + TEST_ASSERT_EQUAL_INT( 0, result2 ); + TEST_ASSERT_EQUAL_INT( 0, result3 ); +} + +void test_negativ_checkOnWin_horizontally2(void){ + // arrange + bool board1[3][3]={ + {1,1,0}, + {0,0,0}, + {0,0,0} + }; + + bool board2[3][3]={ + {0,0,0}, + {0,1,1}, + {0,0,0} + }; + + bool board3[3][3]={ + {0,0,0}, + {0,0,0}, + {1,0,1} + }; + + // act + bool result = playerHasWon( board1 ); + bool result2 = playerHasWon( board2 ); + bool result3 = playerHasWon( board3 ); + + // assert + TEST_ASSERT_EQUAL_INT( 0, result ); + TEST_ASSERT_EQUAL_INT( 0, result2 ); + TEST_ASSERT_EQUAL_INT( 0, result3 ); +} + +void test_negativ_checkOnWin_vertically(void){ + // arrange + bool board1[3][3]={ + {1,0,0}, + {0,0,0}, + {0,0,0} + }; + + bool board2[3][3]={ + {0,0,0}, + {1,0,0}, + {0,0,0} + }; + + bool board3[3][3]={ + {0,0,0}, + {0,0,0}, + {1,0,0} + }; + + // act + bool result = playerHasWon( board1 ); + bool result2 = playerHasWon( board2 ); + bool result3 = playerHasWon( board3 ); + + // assert + TEST_ASSERT_EQUAL_INT( 0, result ); + TEST_ASSERT_EQUAL_INT( 0, result2 ); + TEST_ASSERT_EQUAL_INT( 0, result3 ); +} + +void test_negativ_checkOnWin_vertically2(void){ + // arrange + bool board1[3][3]={ + {0,1,0}, + {0,0,0}, + {0,0,0} + }; + + bool board2[3][3]={ + {0,0,0}, + {0,1,0}, + {0,0,0} + }; + + bool board3[3][3]={ + {0,0,0}, + {0,0,0}, + {0,1,0} + }; + + // act + bool result = playerHasWon( board1 ); + bool result2 = playerHasWon( board2 ); + bool result3 = playerHasWon( board3 ); + + // assert + TEST_ASSERT_EQUAL_INT( 0, result ); + TEST_ASSERT_EQUAL_INT( 0, result2 ); + TEST_ASSERT_EQUAL_INT( 0, result3 ); +} + +void test_negativ_checkOnWin_vertically3(void){ + // arrange + bool board1[3][3]={ + {0,0,1}, + {0,0,0}, + {0,0,0} + }; + + bool board2[3][3]={ + {0,0,0}, + {0,0,1}, + {0,0,0} + }; + + bool board3[3][3]={ + {0,0,0}, + {0,0,0}, + {0,0,1} + }; + + // act + bool result = playerHasWon( board1 ); + bool result2 = playerHasWon( board2 ); + bool result3 = playerHasWon( board3 ); + + // assert + TEST_ASSERT_EQUAL_INT( 0, result ); + TEST_ASSERT_EQUAL_INT( 0, result2 ); + TEST_ASSERT_EQUAL_INT( 0, result3 ); +} \ No newline at end of file