Advertisement
Guest User

Avoidance Tik-Tac-Toe

a guest
Dec 6th, 2019
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.32 KB | None | 0 0
  1. /*-------------------------------------------------------------------------
  2.     Include files:
  3. -------------------------------------------------------------------------*/
  4. #include <stdio.h>
  5.  
  6. /*-------------------------------------------------------------------------
  7.     Constants and definitions:
  8. -------------------------------------------------------------------------*/
  9. #define N 11
  10. #define MIN_SIZE 1
  11. #define MAX_MOVES N*N + 1
  12. #define COORDS 2
  13. #define ROW_CORD 0
  14. #define COL_CORD 1
  15. #define PLAYER_OFFSET 1
  16. #define CORD_OFFSET 1
  17. #define EMPTY_CELL '_'
  18. #define X_CELL 'X'
  19. #define O_CELL 'O'
  20. #define EVEN_TEST 2
  21. #define ERROR 2
  22.  
  23. /*-------------------------------------------------------------------------
  24.     Function declaration
  25. -------------------------------------------------------------------------*/
  26. void print_welcome();
  27. void print_enter_board_size();
  28. void print_board(char board[N][N], int n);
  29. void print_player_turn(int player_index);
  30. int print_error();
  31. int print_winner(int player_index);
  32. void print_tie();
  33. void SetBoard(char Board[N][N], char Symbol);
  34. int isMove(int Row, int Column, unsigned int TableSize, char Board[N][N]);
  35. int isWinner(char Board[N][N], unsigned int TableSize);
  36. int PlayerMove(char Board[N][N], unsigned MoveList[MAX_MOVES][COORDS], unsigned int TableSize, unsigned* pTurn, int* MoveNum);
  37. int StartGame(char Board[N][N], unsigned* pTurn, int TableSize);
  38. int Undo(int Rollback, unsigned MoveList[MAX_MOVES][COORDS], char Board[N][N], unsigned int TableSize, unsigned* pTurn, int* MoveNum);
  39. int CheckDiagonal(char Board[N][N], unsigned int TableSize);
  40.  
  41.  
  42. /*-------------------------------------------------------------------------
  43.     Implementation
  44. -------------------------------------------------------------------------*/
  45.  
  46. //11 lines
  47. int main()
  48. {
  49.     unsigned int TableSize, pTurn = 0;
  50.     char Board[N][N];
  51.     print_welcome();
  52.     print_enter_board_size();
  53.     scanf("%u", &TableSize);
  54.     SetBoard(Board, EMPTY_CELL);
  55.     print_board(Board, TableSize);
  56.     if (StartGame(Board, &pTurn, TableSize) < (int)(TableSize * TableSize)) return print_winner((int)(!pTurn + PLAYER_OFFSET));
  57.     if (pTurn == MIN_SIZE) return print_winner((int)(pTurn + PLAYER_OFFSET));
  58.     print_tie();
  59.     return 0;
  60. }
  61.  
  62. //Starts the game and continues it until a winner is decided, and then returns the number of moves it tooks
  63. //7 lines
  64. int StartGame(char Board[N][N], unsigned* pTurn, int TableSize)
  65. {
  66.     int MoveNum = 0, GameOver = 0;
  67.     unsigned MoveList[MAX_MOVES][COORDS] = { {0} };
  68.     while ((!GameOver || GameOver == ERROR) && MoveNum != TableSize*TableSize)
  69.     {
  70.         if(GameOver != ERROR) print_player_turn(*pTurn + PLAYER_OFFSET);
  71.         GameOver = PlayerMove(Board, MoveList, TableSize, pTurn, &MoveNum);
  72.         if(GameOver != ERROR) print_board(Board, TableSize);
  73.     }
  74.     return MoveNum;
  75. }
  76.  
  77. //Calculates the player's move and updates it into the board's array
  78. //13 lines
  79. int PlayerMove(char Board[N][N], unsigned MoveList[MAX_MOVES][COORDS], unsigned int TableSize, unsigned* pTurn, int* MoveNum)
  80. {
  81.     int Row, Column, returnval = 0;
  82.     scanf(" %d", &Row);
  83.     if (Row >= 0)
  84.     {
  85.         if (scanf(" %d", &Column) && isMove(Row, Column, TableSize, Board))
  86.         {
  87.             Board[Row-CORD_OFFSET][Column-CORD_OFFSET] = *pTurn ? O_CELL : X_CELL;
  88.             if (isWinner(Board, TableSize)) return 1;
  89.             *MoveNum += 1;
  90.             MoveList[*MoveNum - CORD_OFFSET][ROW_CORD] = Row - CORD_OFFSET;
  91.             MoveList[*MoveNum - CORD_OFFSET][COL_CORD] = Column - CORD_OFFSET;
  92.             *pTurn = !*pTurn;
  93.         }
  94.         else return print_error();
  95.     }
  96.     else returnval = Undo(Row, MoveList, Board, TableSize, pTurn, MoveNum);
  97.     return returnval;
  98. }
  99.  
  100. //Checks if the move is legal or not
  101. //7 lines
  102. int isMove(int Row, int Column, unsigned int TableSize, char Board[N][N])
  103. {
  104.     if (Row > 0) //Regular
  105.     {
  106.         if ((Row > (int)TableSize) || (Column > (int)TableSize)) return 0;
  107.         if (Board[Row - CORD_OFFSET][Column - CORD_OFFSET] != EMPTY_CELL) return 0;
  108.     }
  109.     else if (Row < 0) //Undo
  110.     {
  111.         if (!((-Row) % EVEN_TEST)) return 0;
  112.     }
  113.     else return 0;
  114.     return 1;
  115. }
  116.  
  117. //Rolls back a set odd-number of turns and then passes the turn on
  118. //9 lines
  119. int Undo(int Rollback, unsigned MoveList[MAX_MOVES][COORDS], char Board[N][N], unsigned int TableSize, unsigned* pTurn, int* MoveNum)
  120. {
  121.     if (!isMove(Rollback, Rollback, TableSize, Board)) return print_error();
  122.     if (-Rollback > (int)*MoveNum) return print_error();
  123.     for (int i = 0; i < (-Rollback); i++)
  124.     {
  125.         Board[MoveList[*MoveNum - CORD_OFFSET - i][ROW_CORD]][MoveList[*MoveNum - CORD_OFFSET - i][COL_CORD]] = EMPTY_CELL;
  126.         MoveList[*MoveNum - CORD_OFFSET - i][ROW_CORD] = 0;
  127.         MoveList[*MoveNum - CORD_OFFSET - i][COL_CORD] = 0;
  128.     }
  129.     *MoveNum += Rollback;
  130.     *pTurn = !*pTurn;
  131.     return 0;
  132. }
  133.  
  134. //Checks if there is a winning(or actually losing?) combination in the rows and lines of the board
  135. //9 lines
  136. int isWinner(char Board[N][N], unsigned int TableSize)
  137. {
  138.     for (unsigned i = 0; i < TableSize; i++)
  139.         for (unsigned j = 0; j < TableSize-1; j++)
  140.         {
  141.             if (Board[i][j] != Board[i][j + CORD_OFFSET] || Board[i][j] == EMPTY_CELL) break;
  142.             if ((j == TableSize - 2) && Board[i][j] == Board[i][j + CORD_OFFSET]) return 1;
  143.         }
  144.     for (unsigned i = 0; i < TableSize; i++)
  145.         for (unsigned j = 0; j < TableSize; j++)
  146.         {
  147.             if (Board[j][i] != Board[j + CORD_OFFSET][i] || Board[j][i] == EMPTY_CELL) break;
  148.             if ((j == TableSize - 2) && Board[j][i] == Board[j + CORD_OFFSET][i]) return 1;
  149.         }
  150.     return CheckDiagonal(Board, TableSize);
  151. }
  152.  
  153. //Like isWinner, checks for a winning combination in the two diagonals
  154. //7 lines
  155. int CheckDiagonal(char Board[N][N], unsigned int TableSize)
  156. {
  157.     for (unsigned i = 0; i < TableSize - 1; i++)
  158.     {
  159.         if (Board[i][i] != Board[i + CORD_OFFSET][i + CORD_OFFSET] || Board[i][i] == EMPTY_CELL) break;
  160.         if ((i == TableSize - 2) && Board[i][i] == Board[i + CORD_OFFSET][i + CORD_OFFSET]) return 1;
  161.     }
  162.     for (unsigned i = 0, j = TableSize-1; i < TableSize - 1; i++, j--)
  163.     {
  164.         if (Board[i][j] != Board[i + CORD_OFFSET][j - CORD_OFFSET] || Board[i][j] == EMPTY_CELL) break;
  165.         if ((i == TableSize - 2) && Board[i][j] == Board[i + CORD_OFFSET][j - CORD_OFFSET]) return 1;
  166.     }
  167.     return 0;
  168. }
  169.  
  170. //Initializes a board array to a chosen symbol, practically to '_'
  171. //3 lines
  172. void SetBoard(char Board[N][N], char Symbol)
  173. {
  174.     for (int i = 0; i < N; i++)
  175.         for (int j = 0; j < N; j++)
  176.             Board[i][j] = Symbol;
  177. }
  178.  
  179. //print welcome message
  180. //1 lines
  181. void print_welcome()
  182. {
  183.     printf("*** Welcome to AVOIDANCE TIC-TAC-TOE game ***\n\n");
  184. }
  185.  
  186. //print message to enter board size
  187. //1 lines
  188. void print_enter_board_size()
  189. {
  190.     printf("Please enter board size (1 to %d):\n", N);
  191. }
  192.  
  193. //print the board
  194. //7 lines
  195. void print_board(char board[N][N], int n)
  196. {
  197.     printf("\nCurrent board:\n");
  198.     for (int i = 0; i < n; i++)
  199.     {
  200.         printf("|");
  201.         for (int j = 0; j < n; j++)
  202.         {
  203.             printf("%c|", board[i][j]);
  204.         }
  205.         printf("\n");
  206.     }
  207.     printf("\n");
  208. }
  209.  
  210. //print a request for player with index "player_index" to move
  211. //1 lines
  212. void print_player_turn(int player_index)
  213. {
  214.     printf("\nPlayer ** %d **, enter next move:\n", player_index);
  215. }
  216.  
  217. //print error message
  218. //1 lines
  219. int print_error()
  220. {
  221.     printf("Illegal move!!!, please try again:\n");
  222.     return ERROR;
  223. }
  224.  
  225. //print the winner
  226. //1 lines
  227. int print_winner(int player_index)
  228. {
  229.     return printf("Player %d Wins! Hooray!\n", player_index);
  230. }
  231.  
  232. //print message to announce there is a tie (no one wins)
  233. //1 lines
  234. void print_tie()
  235. {
  236.     printf("It's a tie!\n");
  237. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement