Advertisement
Guest User

Untitled

a guest
Dec 17th, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.85 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <ntsid.h>
  3. #include <stdbool.h>
  4. #include <string.h>
  5. #include <math.h>
  6. #include <limits.h>
  7. #include <ctype.h>
  8. #include <stdlib.h>
  9. #include <time.h>
  10.  
  11. #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
  12. #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
  13. #define MAX_SIZE 200
  14.  
  15. static char CORNER_SYMBOL = 'O';
  16. static char *HORIZONTAL_EGDE = "---";
  17. static char *EMPTY_HORIZONTAL_EGDE = "   ";
  18. static char *VERTICAL_EGDE = "|";
  19. static char *EMPTY_VERTICAL_EGDE = " ";
  20. static char *LOAD_KEYWORD = "load";
  21. static char *SAVE_KEYWORD = "save";
  22. static char *UNDO_KEYWORD = "undo";
  23. static char *REDO_KEYWORD = "redo";
  24.  
  25. int n, i, j, k, l, index1, m, boardersLimit;
  26.  
  27. int linesNum, dotsNum, boxesNum, movesNum;
  28. int difficulty;
  29. time_t startTime, endMove;
  30. int totalTime;
  31. int mode;
  32. enum EdgeOwner {
  33.     EMPTY, PLAYERA, PLAYERB
  34. };
  35. enum color {
  36.     UNDEFINED = -1, GREEN = 0, RED = 1, BLUE = 2
  37. };
  38. enum EdgeType {
  39.     HORIZONTAL, VERTICAL, BOX
  40. };
  41.  
  42. typedef struct {
  43.     enum EdgeType edgeType;
  44.     int edgeNum;
  45.     enum EdgeOwner from;
  46. } EdgeChange;
  47.  
  48. typedef struct {
  49.     int moveNum;
  50.     enum EdgeOwner player;
  51.     EdgeChange *changedEdges;
  52.     int remainingBox;
  53.     int playerAScore;
  54.     int playerBScore;
  55.     int edgeChangeLength;
  56.     int hiddenMoves;
  57.     int moves;
  58.     int playerAmoves;
  59.     int playerBmoves;
  60. } Capture;
  61.  
  62. enum EdgeOwner vertical[MAX_SIZE] = {EMPTY};
  63. enum color verticalColor[MAX_SIZE];
  64. enum color verticalColorBeforeBox[MAX_SIZE];
  65. enum EdgeOwner horizontal[MAX_SIZE] = {EMPTY};
  66. enum color horizontalColor[MAX_SIZE] = {UNDEFINED};
  67. enum color horizontalColorBeforeBox[MAX_SIZE];
  68. char boxes[MAX_SIZE];
  69. bool AIPlayer;
  70. static int moves = 0, hiddenMoves = 0; // if hiddenMoves is an odd int so it's the turn of player B otherwise it's the turn of player A
  71. static int playerAScore = 0;
  72. static int playerBScore = 0;
  73. static char playerAname[30] = "";
  74. static char playerBname[30] = "";
  75. static char AI_PLAYER_NAME[5] = "$(AI)";
  76. static int playerAmoves = 0;
  77. static int playerBmoves = 0;
  78. static int remainingBoxes = 4;
  79. Capture undoList[MAX_SIZE];
  80. int redoList[MAX_SIZE];
  81. int undoIndex = 0, redoIndex = 0, undoFlag = 0/* to undo all possible AI moves after the undo of player's move*/, redoFlag = 0;
  82. static enum color playerAcolor;
  83. static enum color playerBcolor;
  84.  
  85. static int MAX_BOXES_NUMBER = INT_MAX;
  86.  
  87. enum MoveType {
  88.     UNDO, REDO, SAVE, LOAD, MOVE
  89. };
  90.  
  91. typedef struct {
  92.     enum MoveType moveType;
  93.     int value;
  94. } MoveInput;
  95.  
  96. int getValidGridSize() {
  97.     int num = 0;
  98.     printf("Please enter a number: ");
  99.     scanf("%d", &num);
  100.     getchar();
  101.     while (num < 1 || num > MAX_BOXES_NUMBER / num) {
  102.         printf("Invalid input... please enter a number: ");
  103.         scanf("%d", &num);
  104.         getchar();
  105.     }
  106.     printf("size : %d\n", num);
  107.     return num;
  108. }
  109.  
  110.  
  111. enum color selectColor() {
  112.     int a = 0, flag = 0;
  113.     char b[2];
  114.     while (!flag) {
  115.         scanf("%s", b);
  116.         while (strlen(b) != 1 || !isdigit(b[0])) {
  117.             printf("Invalid input !! \n");
  118.             scanf("%s", b);
  119.         }
  120.         a = atoi(b);
  121.         if (a >= 1 && a <= 3) {
  122.             flag = 1;
  123.         } else {
  124.             printf("Invalid Color !! \n");
  125.         }
  126.     }
  127.     return (a - 1);
  128. }
  129.  
  130. enum EdgeOwner whichTurn();
  131.  
  132. bool checkCompleteBox(int num, int edge, int downEdge, int edge1, EdgeChange *ptr, int *i1);
  133.  
  134. void colorString(char arr[], enum color color)    // green=1 , red=2 , blue=3
  135. {
  136.     /*
  137.     HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
  138.     WORD wOldColorAttrs;
  139.     CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
  140.     GetConsoleScreenBufferInfo(h, &csbiInfo);
  141.     wOldColorAttrs = csbiInfo.wAttributes;
  142.     switch (color) {
  143.         case GREEN :
  144.             SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
  145.             break;
  146.         case RED :
  147.             SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
  148.             break;
  149.         case BLUE :
  150.             SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
  151.             break;
  152.     }
  153.     */
  154.     printf("%s", arr);
  155.     /*SetConsoleTextAttribute(h, wOldColorAttrs);*/
  156. }
  157.  
  158. enum EdgeOwner getPlayerTurn();
  159.  
  160. char getPlayerPrefix(int playerName);
  161.  
  162. char getCurrentPlayerPrefix();
  163.  
  164. char *getCurrentPlayerName();
  165.  
  166. void undoMove();
  167.  
  168. void printPlayerColorSelect(char *playerName) {
  169.     if (playerAcolor != GREEN)
  170.         colorString("1-Green ", GREEN);
  171.     if (playerAcolor != RED)
  172.         colorString("2-Red ", RED);
  173.     if (playerAcolor != BLUE)
  174.         colorString("3-Blue", BLUE);
  175.     printf("%s", "\n");
  176.     printf("Enter %s's Color : ", playerName);
  177. }
  178.  
  179. enum EdgeOwner getPlayerTurn() {
  180.     return hiddenMoves % 2 ? PLAYERB : PLAYERA;
  181. }
  182.  
  183. enum color getPlayerColor(enum EdgeOwner owner);
  184.  
  185. void redoMove();
  186.  
  187. void enterPlayers() {
  188.     setbuf(stdout, NULL);
  189.     printf("Enter First Player Name : ");
  190.     scanf("%s", playerAname);
  191.     while (!isalpha(playerAname[0]) || strlen(playerAname) > 10) {
  192.         printf("Invalid Name , first character must be alphabetic, max length is 10 char..\nEnter First Player Name : ");
  193.         scanf("%s", playerAname);
  194.     }
  195.     playerAcolor = UNDEFINED; // invalidate it.
  196.  
  197.     printPlayerColorSelect(playerAname);
  198.     playerAcolor = selectColor();
  199.     if (!AIPlayer) {
  200.         printf("Enter Second Player Name : ");
  201.         scanf("%s", playerBname);
  202.         while (!isalpha(playerBname[0]) || strlen(playerBname) > 10 || !strcmp(playerBname, playerAname)) {
  203.             printf("Invalid Name , first character must be alphabetic, max length is 10 char, and must be different from the first player's name..\nEnter Second Player Name : ");
  204.             scanf("%s", playerBname);
  205.         }
  206.     } else {
  207.         strcpy(playerBname, AI_PLAYER_NAME);
  208.     }
  209.     printPlayerColorSelect(playerBname);
  210.     playerBcolor = selectColor();
  211.     while (playerBcolor == playerAcolor) {
  212.         printf("This color has been selected !! \n\n");
  213.         printPlayerColorSelect(playerBname);
  214.         playerBcolor = selectColor();
  215.     }
  216.     printf("\n");
  217. }
  218.  
  219. enum color getPlayerColor(enum EdgeOwner owner) {
  220.     return owner == PLAYERA ? playerAcolor : owner == PLAYERB ? playerBcolor : UNDEFINED;
  221. }
  222.  
  223. void initializeMap() {
  224.     for (i = 0; i < movesNum; ++i) {
  225.         if (i < linesNum) {
  226.             horizontal[i] = false;
  227.             horizontalColor[i] = UNDEFINED;
  228.             horizontalColorBeforeBox[i] = UNDEFINED;
  229.             verticalColor[i] = UNDEFINED;
  230.             vertical[i] = false;
  231.             verticalColorBeforeBox[i] = UNDEFINED;
  232.  
  233.         }
  234.         if (i < boxesNum)boxes[i] = ' ';
  235.     }
  236. }
  237.  
  238. void colorChar(char s, enum color color) {
  239.     char *pChar = malloc(sizeof(char));
  240.     *pChar = s;
  241.     colorString(pChar, color);
  242. }
  243.  
  244. void printCornersRow(int x) {
  245.     printf("%-2d ", x + 1);
  246.     for (j = 0; j < n; j++) {
  247.         printf("%c", CORNER_SYMBOL);
  248.         colorString(horizontal[n * i + j] != EMPTY ? HORIZONTAL_EGDE : EMPTY_HORIZONTAL_EGDE,
  249.                     getPlayerColor(horizontal[n * i + j]));
  250.     }
  251.     printf("%c\n", CORNER_SYMBOL);
  252. }
  253.  
  254. void printInternalRow(int rowNumber) {
  255.     printf("   ");
  256.     colorString(vertical[rowNumber * (n + 1)] ? VERTICAL_EGDE : EMPTY_VERTICAL_EGDE,
  257.                 getPlayerColor(vertical[rowNumber * (n + 1)]));
  258.     printf(" ");
  259.     for (j = 0; j < n; j++) {
  260.         if (boxes[rowNumber * n + j] == toupper(playerAname[0])) {
  261.             colorChar(boxes[rowNumber * n + j], playerAcolor);
  262.         } else {
  263.             colorChar(boxes[rowNumber * n + j], playerBcolor);
  264.         }
  265.         printf(" ");
  266.         colorString(vertical[rowNumber * (n + 1) + j + 1] ? VERTICAL_EGDE : EMPTY_VERTICAL_EGDE,
  267.                     getPlayerColor(vertical[rowNumber * (n + 1) + j + 1]));
  268.         printf(" ");
  269.     }
  270.     printf("\n");
  271.  
  272. }
  273.  
  274. void printMap() {
  275.     printf("   ");
  276.     for (i = 0; i <= n; ++i) {
  277.         printf("%-2d  ", i + 1);
  278.     }
  279.     printf("\n");
  280.     for (i = 0; i <= n; i++) {
  281.         printCornersRow(i);
  282.         if (i != n) {
  283.             printInternalRow(i);
  284.         }
  285.     }
  286.     printf("Moves : %d\n", moves);
  287.     printf("Turn of %s (%c)\n", getCurrentPlayerName(), getCurrentPlayerPrefix());
  288.     printf("%s's Moves (%c) : %d\n", playerAname, getPlayerPrefix(PLAYERA), playerAmoves);
  289.     printf("%s's Moves (%c) : %d\n", playerBname, getPlayerPrefix(PLAYERB), playerBmoves);
  290.     printf("%s (%c) : %d\n", playerAname, getPlayerPrefix(PLAYERA), playerAScore);
  291.     printf("%s (%c) : %d\n", playerBname, getPlayerPrefix(PLAYERB), playerBScore);
  292.     printf("Time passed : %2d : %2d\n", totalTime / 60, totalTime % 60);
  293.     printf("Remaining Boxes : %d\n", remainingBoxes);
  294. }
  295.  
  296. char getCurrentPlayerPrefix() {
  297.     return getPlayerTurn() == PLAYERA ? toupper(playerAname[0]) : tolower(playerBname[0]);
  298. }
  299.  
  300. void setMode() {
  301.     n = getValidGridSize();
  302.     linesNum = n * (n + 1);
  303.     dotsNum = (n + 1) * (n + 1);
  304.     boxesNum = n * n;
  305.     movesNum = 2 * n * (n + 1);
  306.     remainingBoxes = n * n;
  307.     boardersLimit = n + 1;
  308. }
  309.  
  310. bool isFourDigitString(char *a) {
  311.     if (strlen(a) != 4) return false;
  312.     for (i = 0; i < strlen(a); ++i) {
  313.         if (!isdigit(a[i])) {
  314.             return false;
  315.         }
  316.     }
  317.     return true;
  318. }
  319.  
  320. int getLeftEdge(int row, int col) {
  321.     row--;
  322.     col--;
  323.     if (row < 0 || col <= 0 || row > n || col > n) return -1;
  324.     return n * (row) + (col - 1);
  325. }
  326.  
  327. int getRightEdge(int row, int col) {
  328.     row--;
  329.     col--;
  330.     if (row < 0 || col < 0 || row > n || col >= n) return -1;
  331.     return n * (row) + (col);
  332. }
  333.  
  334. int getUpEdge(int row, int col) {
  335.     row--;
  336.     col--;
  337.     if (row <= 0 || col < 0 || row > n || col > n) return -1;
  338.     return boardersLimit * (row - 1) + col;
  339. }
  340.  
  341. int getDownEdge(int row, int col) {
  342.     row--;
  343.     col--;
  344.     if (row < 0 || col < 0 || row >= n || col > n) return -1;
  345.     return boardersLimit * (row) + col;
  346. }
  347.  
  348. void countMoves() {
  349.     if (getPlayerTurn() == PLAYERA) {
  350.         playerAmoves++;
  351.     } else {
  352.         playerBmoves++;
  353.     }
  354. }
  355.  
  356. void move(int inputMove) {
  357.     int input[4];
  358.     input[3] = inputMove % 10;
  359.     input[2] = (inputMove / 10) % 10;
  360.     input[1] = (inputMove / 100) % 10;
  361.     input[0] = (inputMove / 1000) % 10;
  362.     if (abs(input[1] - input[3]) + abs(input[0] - input[2]) != 1) {
  363.         printf("Dots should be neighbors to be connected .. ");
  364.         return;
  365.     }
  366.     if (input[1] > boardersLimit || input[3] > boardersLimit || input[0] > boardersLimit || input[2] > boardersLimit) {
  367.         printf("Please enter valid dots .. ");
  368.         return;
  369.     }
  370.  
  371.     Capture moveCapture;
  372.     moveCapture.player = getPlayerTurn();
  373.     moveCapture.moveNum = inputMove;
  374.     moveCapture.changedEdges = malloc(9 * sizeof(EdgeChange));
  375.     moveCapture.playerAmoves = playerAmoves;
  376.     moveCapture.playerBmoves = playerBmoves;
  377.     moveCapture.playerAScore = playerAScore;
  378.     moveCapture.playerBScore = playerBScore;
  379.     moveCapture.remainingBox = remainingBoxes;
  380.     moveCapture.hiddenMoves = hiddenMoves;
  381.     // memory leak might happen.
  382.     int q = 0;
  383.     int *changePos = &q;
  384.     if (input[0] == input[2]) {
  385.         int edgeNum = getLeftEdge(input[0], MAX(input[1], input[3]));
  386.         if (horizontal[edgeNum] != EMPTY) {
  387.             printf("Edge %d is already connected ", inputMove);
  388.             return;
  389.         } else {
  390.             moveCapture.changedEdges[(*changePos)++] = (EdgeChange) {HORIZONTAL, edgeNum, horizontal[edgeNum]};
  391.             horizontal[edgeNum] = getPlayerTurn();
  392.             countMoves();
  393.             if (checkCompleteBox(edgeNum, getLeftEdge(input[0] + 1, MAX(input[1], input[3])),
  394.                                  getDownEdge(input[0], input[1]), getDownEdge(input[2], input[3]),
  395.                                  moveCapture.changedEdges, changePos) |
  396.                 checkCompleteBox(edgeNum, getLeftEdge(input[0] - 1, MAX(input[1], input[3])),
  397.                                  getUpEdge(input[0], input[1]), getUpEdge(input[2], input[3]),
  398.                                  moveCapture.changedEdges, changePos)) {
  399.                 hiddenMoves++;
  400.             }
  401.         }
  402.     } else {
  403.         int edgeNum = getUpEdge(MAX(input[0], input[2]), input[1]);;
  404.         if (vertical[edgeNum] != EMPTY) {
  405.             printf("Edge %d is already connected ", inputMove);
  406.             return;
  407.         } else {
  408.             moveCapture.changedEdges[(*changePos)++] = (EdgeChange) {VERTICAL, edgeNum, vertical[edgeNum]};
  409.             vertical[edgeNum] = getPlayerTurn();
  410.             countMoves();
  411.             if (checkCompleteBox(getLeftEdge(input[0], input[1]), getLeftEdge(input[2], input[3]), edgeNum,
  412.                                  getUpEdge(MAX(input[0], input[2]), input[3] - 1), moveCapture.changedEdges,
  413.                                  changePos) |
  414.                 checkCompleteBox(getRightEdge(input[0], input[1]), getRightEdge(input[2], input[3]), edgeNum,
  415.                                  getUpEdge(MAX(input[0], input[2]), input[3] + 1), moveCapture.changedEdges,
  416.                                  changePos)) {
  417.                 hiddenMoves++;
  418.             }
  419.         }
  420.     }
  421.     moveCapture.moves = moves++;
  422.     hiddenMoves++;
  423.     moveCapture.edgeChangeLength = *changePos;
  424.     undoList[undoIndex++] = moveCapture;
  425. }
  426.  
  427. char getPlayerPrefix(int playerName) {
  428.     return (playerName == PLAYERA ? (char) toupper(playerAname[0]) : (char) tolower(playerBname[0]));
  429. };
  430.  
  431. char *getCurrentPlayerName() {
  432.     return getPlayerTurn() == PLAYERA ? (char *) playerAname : (char *) playerBname;
  433. }
  434.  
  435. bool checkCompleteBox(int horizontalOne, int horizontalTwo, int verticalOne, int verticalTwo, EdgeChange *ptr,
  436.                       int *changePos) {
  437.     if (horizontalOne == -1 || horizontalTwo == -1 || verticalOne == -1 || verticalTwo == -1)return false;
  438.     if (horizontal[horizontalOne] != EMPTY && vertical[verticalOne] != EMPTY && vertical[verticalTwo] != EMPTY &&
  439.         horizontal[horizontalTwo] != EMPTY) {
  440.         // capture everything
  441.         if (horizontal[horizontalOne] != getPlayerTurn()) {
  442.             ptr[(*changePos)++] = (EdgeChange) {HORIZONTAL, horizontalOne, horizontal[horizontalOne]};
  443.         }
  444.         if (horizontal[horizontalTwo] != getPlayerTurn()) {
  445.             ptr[(*changePos)++] = (EdgeChange) {HORIZONTAL, horizontalTwo, horizontal[horizontalTwo]};
  446.         }
  447.         if (vertical[verticalOne] != getPlayerTurn()) {
  448.             ptr[(*changePos)++] = (EdgeChange) {VERTICAL, verticalOne, vertical[verticalOne]};
  449.         }
  450.         if (vertical[verticalTwo] != getPlayerTurn()) {
  451.             ptr[(*changePos)++] = (EdgeChange) {VERTICAL, verticalTwo, vertical[verticalTwo]};
  452.         }
  453.         ptr[(*changePos)++] = (EdgeChange) {BOX, MIN(horizontalOne, horizontalTwo)};
  454.         horizontal[horizontalOne] = vertical[verticalOne] = vertical[verticalTwo] = horizontal[horizontalTwo] = getPlayerTurn();
  455.         boxes[MIN(horizontalOne, horizontalTwo)] = getCurrentPlayerPrefix();
  456.         if (getPlayerTurn() == PLAYERA) {
  457.             playerAScore++;
  458.         } else {
  459.             playerBScore++;
  460.         }
  461.         remainingBoxes--;
  462.         return true;
  463.     }
  464.     return false;
  465. }
  466.  
  467. void processInput(MoveInput input) {
  468.     switch (input.moveType) {
  469.         case UNDO:
  470.             undoMove();
  471.             undoMove();
  472.             return;
  473.         case REDO:
  474.             redoMove();
  475.             redoMove();
  476.             return;
  477. //        case SAVE:
  478. //            saveGame(input.value);
  479. //            return;
  480. //        case LOAD:
  481. //            loadGame(input.value);
  482. //            return;
  483.         case MOVE:
  484.             move(input.value);
  485.             redoIndex = 0;
  486.             return;
  487.         default:
  488.             printf("Invalid Input format\n");
  489.     }
  490. }
  491.  
  492. void redoMove() {
  493.     if (!redoIndex) {
  494.         printf("Redo List is Empty.\n");
  495.         return;
  496.     }
  497.     move(redoList[redoIndex--]);
  498. }
  499.  
  500. void undoMove() {
  501.     if (!undoIndex) {
  502.         printf("Undo List is Empty.\n");
  503.         return;
  504.     }
  505.     Capture capture = undoList[--undoIndex];
  506.     for (i = 0; i < (capture.edgeChangeLength); i++) {
  507.         switch (capture.changedEdges[i].edgeType) {
  508.             case VERTICAL:
  509.                 vertical[capture.changedEdges[i].edgeNum] = capture.changedEdges[i].from;
  510.                 break;
  511.             case HORIZONTAL:
  512.                 horizontal[capture.changedEdges[i].edgeNum] = capture.changedEdges[i].from;
  513.                 break;
  514.             case BOX:
  515.                 boxes[capture.changedEdges[i].edgeNum] = ' ';
  516.                 break;
  517.         }
  518.     }
  519.     playerAScore = capture.playerAScore;
  520.     playerBScore = capture.playerBScore;
  521.     playerAmoves = capture.playerAmoves;
  522.     playerBmoves = capture.playerBmoves;
  523.     remainingBoxes = capture.remainingBox;
  524.     hiddenMoves = capture.hiddenMoves;
  525.     moves = capture.moves;
  526.     redoList[++redoIndex] = capture.moveNum;
  527. }
  528.  
  529. MoveInput getInput() {
  530.     bool firstInput = 1;
  531.     static char a[5];
  532.     do {
  533.         if (!firstInput) {
  534.             printf("Please Enter A Valid Input");
  535.         }
  536.         firstInput = false;
  537.         scanf("%s", a);
  538.         if (!strcasecmp(a, UNDO_KEYWORD)) {
  539.             return (MoveInput) {UNDO};
  540.         } else if (!strcasecmp(a, REDO_KEYWORD)) {
  541.             return (MoveInput) {REDO};
  542.         } else if (!strcasecmp(a, SAVE_KEYWORD)) {
  543.             scanf("%d", &i);
  544.             return (MoveInput) {SAVE, i};
  545.         } else if (!strcasecmp(a, LOAD_KEYWORD)) {
  546.             scanf("%d", &i);
  547.             return (MoveInput) {LOAD, i};
  548.         }
  549.     } while (!isFourDigitString(a));
  550.     return (MoveInput) {MOVE, atoi(a)};
  551. }
  552.  
  553. void test() {
  554.     setbuf(stdout, NULL);
  555.     setMode();
  556.     enterPlayers();
  557.     initializeMap();
  558.     printMap();
  559.     time(&startTime);
  560.     while (moves < movesNum) {
  561.         processInput(getInput());
  562.         time(&endMove);
  563.         totalTime = (int) (difftime(endMove, startTime));
  564.         printf("\n\n");
  565.         printMap();
  566.     }
  567. }
  568.  
  569. int main() {
  570.     test();
  571.     return 0;
  572. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement