ttt_multi_game.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #include "ttt_multi_game.h"
  2. struct TttMultiGame {
  3. TttMultiGameState state;
  4. TttMultiGameResult result;
  5. uint8_t board[3][3];
  6. };
  7. void ttt_multi_game_move_reset(TttMultiGameMove* move) {
  8. furi_assert(move);
  9. // make the move invalid
  10. move->player = TttMultiGamePlayerNone;
  11. move->x = 0xff;
  12. move->y = 0xff;
  13. }
  14. void ttt_multi_game_move_copy(TttMultiGameMove* dst, const TttMultiGameMove* src) {
  15. furi_assert(dst);
  16. furi_assert(src);
  17. dst->player = src->player;
  18. dst->x = src->x;
  19. dst->y = src->y;
  20. }
  21. TttMultiGameMove* ttt_multi_game_move_alloc() {
  22. TttMultiGameMove* move = malloc(sizeof(TttMultiGameMove));
  23. ttt_multi_game_move_reset(move);
  24. return move;
  25. }
  26. void ttt_multi_game_move_free(TttMultiGameMove* move) {
  27. furi_assert(move);
  28. free(move);
  29. }
  30. void ttt_multi_game_reset(TttMultiGame* game) {
  31. furi_assert(game);
  32. game->state = TttMultiGameStateTurnX;
  33. game->result = TttMultiGameResultNone;
  34. for(uint8_t i = 0; i < 3; i++) {
  35. for(uint8_t j = 0; j < 3; j++) {
  36. game->board[i][j] = TttMultiGamePlayerNone;
  37. }
  38. }
  39. }
  40. TttMultiGameState ttt_multi_game_get_state(TttMultiGame* game) {
  41. furi_assert(game);
  42. return game->state;
  43. }
  44. TttMultiGameResult ttt_multi_game_get_result(TttMultiGame* game) {
  45. furi_assert(game);
  46. if(game->state != TttMultiGameStateFinished) {
  47. return TttMultiGameResultNone;
  48. }
  49. return game->result;
  50. }
  51. bool ttt_multi_game_is_draw(TttMultiGame* game) {
  52. furi_assert(game);
  53. for(uint8_t i = 0; i < 3; i++) {
  54. for(uint8_t j = 0; j < 3; j++) {
  55. if(game->board[i][j] == TttMultiGamePlayerNone) {
  56. return false;
  57. }
  58. }
  59. }
  60. return true;
  61. }
  62. TttMultiGamePlayer ttt_multi_game_get_winner(TttMultiGame* game) {
  63. furi_assert(game);
  64. // Check rows
  65. for(uint8_t i = 0; i < 3; i++) {
  66. if(game->board[i][0] != TttMultiGamePlayerNone && game->board[i][0] == game->board[i][1] &&
  67. game->board[i][1] == game->board[i][2]) {
  68. return (TttMultiGamePlayer)game->board[i][0];
  69. }
  70. }
  71. // Check columns
  72. for(uint8_t i = 0; i < 3; i++) {
  73. if(game->board[0][i] != TttMultiGamePlayerNone && game->board[0][i] == game->board[1][i] &&
  74. game->board[1][i] == game->board[2][i]) {
  75. return (TttMultiGamePlayer)game->board[0][i];
  76. }
  77. }
  78. // Check diagonals
  79. if(game->board[0][0] == game->board[1][1] && game->board[1][1] == game->board[2][2]) {
  80. return (TttMultiGamePlayer)game->board[0][0];
  81. }
  82. if(game->board[0][2] == game->board[1][1] && game->board[1][1] == game->board[2][0]) {
  83. return (TttMultiGamePlayer)game->board[0][2];
  84. }
  85. return TttMultiGamePlayerNone;
  86. }
  87. static void ttt_multi_game_update_result(TttMultiGame* game) {
  88. furi_assert(game);
  89. if(game->state == TttMultiGameStateFinished) {
  90. return;
  91. }
  92. TttMultiGamePlayer winner = ttt_multi_game_get_winner(game);
  93. if(winner != TttMultiGamePlayerNone) {
  94. game->state = TttMultiGameStateFinished;
  95. if(winner == TttMultiGamePlayerX) {
  96. game->result = TttMultiGameResultXWin;
  97. } else if(winner == TttMultiGamePlayerO) {
  98. game->result = TttMultiGameResultOWin;
  99. }
  100. return;
  101. }
  102. if(ttt_multi_game_is_draw(game)) {
  103. game->result = TttMultiGameResultDraw;
  104. game->state = TttMultiGameStateFinished;
  105. }
  106. }
  107. bool ttt_multi_game_is_move_valid(TttMultiGame* game, TttMultiGameMove* move) {
  108. furi_assert(game);
  109. furi_assert(move);
  110. if(move->x > 2 || move->y > 2) {
  111. return false;
  112. }
  113. if(move->player != ttt_multi_game_current_player(game)) {
  114. return false;
  115. }
  116. if(game->board[move->x][move->y] != TttMultiGamePlayerNone) {
  117. return false;
  118. }
  119. return true;
  120. }
  121. TttMultiGamePlayer ttt_multi_game_current_player(TttMultiGame* game) {
  122. furi_assert(game);
  123. if(game->state == TttMultiGameStateTurnX) {
  124. return TttMultiGamePlayerX;
  125. } else if(game->state == TttMultiGameStateTurnO) {
  126. return TttMultiGamePlayerO;
  127. }
  128. return TttMultiGamePlayerNone;
  129. }
  130. void ttt_multi_game_swap_player(TttMultiGame* game) {
  131. furi_assert(game);
  132. if(game->state == TttMultiGameStateTurnX) {
  133. game->state = TttMultiGameStateTurnO;
  134. } else if(game->state == TttMultiGameStateTurnO) {
  135. game->state = TttMultiGameStateTurnX;
  136. }
  137. }
  138. void ttt_multi_game_make_move(TttMultiGame* game, TttMultiGameMove* move) {
  139. furi_assert(game);
  140. furi_assert(move);
  141. furi_assert(ttt_multi_game_is_move_valid(game, move));
  142. game->board[move->x][move->y] = (uint8_t)move->player;
  143. ttt_multi_game_swap_player(game);
  144. ttt_multi_game_update_result(game);
  145. }
  146. TttMultiGamePlayer ttt_multi_game_player_at(TttMultiGame* game, uint8_t x, uint8_t y) {
  147. furi_assert(game);
  148. furi_assert(x < 3);
  149. furi_assert(y < 3);
  150. return (TttMultiGamePlayer)game->board[x][y];
  151. }
  152. TttMultiGame* ttt_multi_game_alloc() {
  153. TttMultiGame* game = malloc(sizeof(TttMultiGame));
  154. ttt_multi_game_reset(game);
  155. return game;
  156. }
  157. void ttt_multi_game_free(TttMultiGame* game) {
  158. furi_assert(game);
  159. free(game);
  160. }