Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <ntsid.h>
- #include <stdbool.h>
- #include <string.h>
- #include <math.h>
- #include <limits.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
- #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
- #define MAX_SIZE 200
- static char CORNER_SYMBOL = 'O';
- static char *HORIZONTAL_EGDE = "---";
- static char *EMPTY_HORIZONTAL_EGDE = " ";
- static char *VERTICAL_EGDE = "|";
- static char *EMPTY_VERTICAL_EGDE = " ";
- static char *LOAD_KEYWORD = "load";
- static char *SAVE_KEYWORD = "save";
- static char *UNDO_KEYWORD = "undo";
- static char *REDO_KEYWORD = "redo";
- int n, i, j, k, l, index1, m, boardersLimit;
- int linesNum, dotsNum, boxesNum, movesNum;
- int difficulty;
- time_t startTime, endMove;
- int totalTime;
- int mode;
- enum EdgeOwner {
- EMPTY, PLAYERA, PLAYERB
- };
- enum color {
- UNDEFINED = -1, GREEN = 0, RED = 1, BLUE = 2
- };
- enum EdgeType {
- HORIZONTAL, VERTICAL, BOX
- };
- typedef struct {
- enum EdgeType edgeType;
- int edgeNum;
- enum EdgeOwner from;
- } EdgeChange;
- typedef struct {
- int moveNum;
- enum EdgeOwner player;
- EdgeChange *changedEdges;
- int remainingBox;
- int playerAScore;
- int playerBScore;
- int edgeChangeLength;
- int hiddenMoves;
- int moves;
- int playerAmoves;
- int playerBmoves;
- } Capture;
- enum EdgeOwner vertical[MAX_SIZE] = {EMPTY};
- enum color verticalColor[MAX_SIZE];
- enum color verticalColorBeforeBox[MAX_SIZE];
- enum EdgeOwner horizontal[MAX_SIZE] = {EMPTY};
- enum color horizontalColor[MAX_SIZE] = {UNDEFINED};
- enum color horizontalColorBeforeBox[MAX_SIZE];
- char boxes[MAX_SIZE];
- bool AIPlayer;
- 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
- static int playerAScore = 0;
- static int playerBScore = 0;
- static char playerAname[30] = "";
- static char playerBname[30] = "";
- static char AI_PLAYER_NAME[5] = "$(AI)";
- static int playerAmoves = 0;
- static int playerBmoves = 0;
- static int remainingBoxes = 4;
- Capture undoList[MAX_SIZE];
- int redoList[MAX_SIZE];
- int undoIndex = 0, redoIndex = 0, undoFlag = 0/* to undo all possible AI moves after the undo of player's move*/, redoFlag = 0;
- static enum color playerAcolor;
- static enum color playerBcolor;
- static int MAX_BOXES_NUMBER = INT_MAX;
- enum MoveType {
- UNDO, REDO, SAVE, LOAD, MOVE
- };
- typedef struct {
- enum MoveType moveType;
- int value;
- } MoveInput;
- int getValidGridSize() {
- int num = 0;
- printf("Please enter a number: ");
- scanf("%d", &num);
- getchar();
- while (num < 1 || num > MAX_BOXES_NUMBER / num) {
- printf("Invalid input... please enter a number: ");
- scanf("%d", &num);
- getchar();
- }
- printf("size : %d\n", num);
- return num;
- }
- enum color selectColor() {
- int a = 0, flag = 0;
- char b[2];
- while (!flag) {
- scanf("%s", b);
- while (strlen(b) != 1 || !isdigit(b[0])) {
- printf("Invalid input !! \n");
- scanf("%s", b);
- }
- a = atoi(b);
- if (a >= 1 && a <= 3) {
- flag = 1;
- } else {
- printf("Invalid Color !! \n");
- }
- }
- return (a - 1);
- }
- enum EdgeOwner whichTurn();
- bool checkCompleteBox(int num, int edge, int downEdge, int edge1, EdgeChange *ptr, int *i1);
- void colorString(char arr[], enum color color) // green=1 , red=2 , blue=3
- {
- /*
- HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
- WORD wOldColorAttrs;
- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
- GetConsoleScreenBufferInfo(h, &csbiInfo);
- wOldColorAttrs = csbiInfo.wAttributes;
- switch (color) {
- case GREEN :
- SetConsoleTextAttribute(h, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
- break;
- case RED :
- SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
- break;
- case BLUE :
- SetConsoleTextAttribute(h, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
- break;
- }
- */
- printf("%s", arr);
- /*SetConsoleTextAttribute(h, wOldColorAttrs);*/
- }
- enum EdgeOwner getPlayerTurn();
- char getPlayerPrefix(int playerName);
- char getCurrentPlayerPrefix();
- char *getCurrentPlayerName();
- void undoMove();
- void printPlayerColorSelect(char *playerName) {
- if (playerAcolor != GREEN)
- colorString("1-Green ", GREEN);
- if (playerAcolor != RED)
- colorString("2-Red ", RED);
- if (playerAcolor != BLUE)
- colorString("3-Blue", BLUE);
- printf("%s", "\n");
- printf("Enter %s's Color : ", playerName);
- }
- enum EdgeOwner getPlayerTurn() {
- return hiddenMoves % 2 ? PLAYERB : PLAYERA;
- }
- enum color getPlayerColor(enum EdgeOwner owner);
- void redoMove();
- void enterPlayers() {
- setbuf(stdout, NULL);
- printf("Enter First Player Name : ");
- scanf("%s", playerAname);
- while (!isalpha(playerAname[0]) || strlen(playerAname) > 10) {
- printf("Invalid Name , first character must be alphabetic, max length is 10 char..\nEnter First Player Name : ");
- scanf("%s", playerAname);
- }
- playerAcolor = UNDEFINED; // invalidate it.
- printPlayerColorSelect(playerAname);
- playerAcolor = selectColor();
- if (!AIPlayer) {
- printf("Enter Second Player Name : ");
- scanf("%s", playerBname);
- while (!isalpha(playerBname[0]) || strlen(playerBname) > 10 || !strcmp(playerBname, playerAname)) {
- 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 : ");
- scanf("%s", playerBname);
- }
- } else {
- strcpy(playerBname, AI_PLAYER_NAME);
- }
- printPlayerColorSelect(playerBname);
- playerBcolor = selectColor();
- while (playerBcolor == playerAcolor) {
- printf("This color has been selected !! \n\n");
- printPlayerColorSelect(playerBname);
- playerBcolor = selectColor();
- }
- printf("\n");
- }
- enum color getPlayerColor(enum EdgeOwner owner) {
- return owner == PLAYERA ? playerAcolor : owner == PLAYERB ? playerBcolor : UNDEFINED;
- }
- void initializeMap() {
- for (i = 0; i < movesNum; ++i) {
- if (i < linesNum) {
- horizontal[i] = false;
- horizontalColor[i] = UNDEFINED;
- horizontalColorBeforeBox[i] = UNDEFINED;
- verticalColor[i] = UNDEFINED;
- vertical[i] = false;
- verticalColorBeforeBox[i] = UNDEFINED;
- }
- if (i < boxesNum)boxes[i] = ' ';
- }
- }
- void colorChar(char s, enum color color) {
- char *pChar = malloc(sizeof(char));
- *pChar = s;
- colorString(pChar, color);
- }
- void printCornersRow(int x) {
- printf("%-2d ", x + 1);
- for (j = 0; j < n; j++) {
- printf("%c", CORNER_SYMBOL);
- colorString(horizontal[n * i + j] != EMPTY ? HORIZONTAL_EGDE : EMPTY_HORIZONTAL_EGDE,
- getPlayerColor(horizontal[n * i + j]));
- }
- printf("%c\n", CORNER_SYMBOL);
- }
- void printInternalRow(int rowNumber) {
- printf(" ");
- colorString(vertical[rowNumber * (n + 1)] ? VERTICAL_EGDE : EMPTY_VERTICAL_EGDE,
- getPlayerColor(vertical[rowNumber * (n + 1)]));
- printf(" ");
- for (j = 0; j < n; j++) {
- if (boxes[rowNumber * n + j] == toupper(playerAname[0])) {
- colorChar(boxes[rowNumber * n + j], playerAcolor);
- } else {
- colorChar(boxes[rowNumber * n + j], playerBcolor);
- }
- printf(" ");
- colorString(vertical[rowNumber * (n + 1) + j + 1] ? VERTICAL_EGDE : EMPTY_VERTICAL_EGDE,
- getPlayerColor(vertical[rowNumber * (n + 1) + j + 1]));
- printf(" ");
- }
- printf("\n");
- }
- void printMap() {
- printf(" ");
- for (i = 0; i <= n; ++i) {
- printf("%-2d ", i + 1);
- }
- printf("\n");
- for (i = 0; i <= n; i++) {
- printCornersRow(i);
- if (i != n) {
- printInternalRow(i);
- }
- }
- printf("Moves : %d\n", moves);
- printf("Turn of %s (%c)\n", getCurrentPlayerName(), getCurrentPlayerPrefix());
- printf("%s's Moves (%c) : %d\n", playerAname, getPlayerPrefix(PLAYERA), playerAmoves);
- printf("%s's Moves (%c) : %d\n", playerBname, getPlayerPrefix(PLAYERB), playerBmoves);
- printf("%s (%c) : %d\n", playerAname, getPlayerPrefix(PLAYERA), playerAScore);
- printf("%s (%c) : %d\n", playerBname, getPlayerPrefix(PLAYERB), playerBScore);
- printf("Time passed : %2d : %2d\n", totalTime / 60, totalTime % 60);
- printf("Remaining Boxes : %d\n", remainingBoxes);
- }
- char getCurrentPlayerPrefix() {
- return getPlayerTurn() == PLAYERA ? toupper(playerAname[0]) : tolower(playerBname[0]);
- }
- void setMode() {
- n = getValidGridSize();
- linesNum = n * (n + 1);
- dotsNum = (n + 1) * (n + 1);
- boxesNum = n * n;
- movesNum = 2 * n * (n + 1);
- remainingBoxes = n * n;
- boardersLimit = n + 1;
- }
- bool isFourDigitString(char *a) {
- if (strlen(a) != 4) return false;
- for (i = 0; i < strlen(a); ++i) {
- if (!isdigit(a[i])) {
- return false;
- }
- }
- return true;
- }
- int getLeftEdge(int row, int col) {
- row--;
- col--;
- if (row < 0 || col <= 0 || row > n || col > n) return -1;
- return n * (row) + (col - 1);
- }
- int getRightEdge(int row, int col) {
- row--;
- col--;
- if (row < 0 || col < 0 || row > n || col >= n) return -1;
- return n * (row) + (col);
- }
- int getUpEdge(int row, int col) {
- row--;
- col--;
- if (row <= 0 || col < 0 || row > n || col > n) return -1;
- return boardersLimit * (row - 1) + col;
- }
- int getDownEdge(int row, int col) {
- row--;
- col--;
- if (row < 0 || col < 0 || row >= n || col > n) return -1;
- return boardersLimit * (row) + col;
- }
- void countMoves() {
- if (getPlayerTurn() == PLAYERA) {
- playerAmoves++;
- } else {
- playerBmoves++;
- }
- }
- void move(int inputMove) {
- int input[4];
- input[3] = inputMove % 10;
- input[2] = (inputMove / 10) % 10;
- input[1] = (inputMove / 100) % 10;
- input[0] = (inputMove / 1000) % 10;
- if (abs(input[1] - input[3]) + abs(input[0] - input[2]) != 1) {
- printf("Dots should be neighbors to be connected .. ");
- return;
- }
- if (input[1] > boardersLimit || input[3] > boardersLimit || input[0] > boardersLimit || input[2] > boardersLimit) {
- printf("Please enter valid dots .. ");
- return;
- }
- Capture moveCapture;
- moveCapture.player = getPlayerTurn();
- moveCapture.moveNum = inputMove;
- moveCapture.changedEdges = malloc(9 * sizeof(EdgeChange));
- moveCapture.playerAmoves = playerAmoves;
- moveCapture.playerBmoves = playerBmoves;
- moveCapture.playerAScore = playerAScore;
- moveCapture.playerBScore = playerBScore;
- moveCapture.remainingBox = remainingBoxes;
- moveCapture.hiddenMoves = hiddenMoves;
- // memory leak might happen.
- int q = 0;
- int *changePos = &q;
- if (input[0] == input[2]) {
- int edgeNum = getLeftEdge(input[0], MAX(input[1], input[3]));
- if (horizontal[edgeNum] != EMPTY) {
- printf("Edge %d is already connected ", inputMove);
- return;
- } else {
- moveCapture.changedEdges[(*changePos)++] = (EdgeChange) {HORIZONTAL, edgeNum, horizontal[edgeNum]};
- horizontal[edgeNum] = getPlayerTurn();
- countMoves();
- if (checkCompleteBox(edgeNum, getLeftEdge(input[0] + 1, MAX(input[1], input[3])),
- getDownEdge(input[0], input[1]), getDownEdge(input[2], input[3]),
- moveCapture.changedEdges, changePos) |
- checkCompleteBox(edgeNum, getLeftEdge(input[0] - 1, MAX(input[1], input[3])),
- getUpEdge(input[0], input[1]), getUpEdge(input[2], input[3]),
- moveCapture.changedEdges, changePos)) {
- hiddenMoves++;
- }
- }
- } else {
- int edgeNum = getUpEdge(MAX(input[0], input[2]), input[1]);;
- if (vertical[edgeNum] != EMPTY) {
- printf("Edge %d is already connected ", inputMove);
- return;
- } else {
- moveCapture.changedEdges[(*changePos)++] = (EdgeChange) {VERTICAL, edgeNum, vertical[edgeNum]};
- vertical[edgeNum] = getPlayerTurn();
- countMoves();
- if (checkCompleteBox(getLeftEdge(input[0], input[1]), getLeftEdge(input[2], input[3]), edgeNum,
- getUpEdge(MAX(input[0], input[2]), input[3] - 1), moveCapture.changedEdges,
- changePos) |
- checkCompleteBox(getRightEdge(input[0], input[1]), getRightEdge(input[2], input[3]), edgeNum,
- getUpEdge(MAX(input[0], input[2]), input[3] + 1), moveCapture.changedEdges,
- changePos)) {
- hiddenMoves++;
- }
- }
- }
- moveCapture.moves = moves++;
- hiddenMoves++;
- moveCapture.edgeChangeLength = *changePos;
- undoList[undoIndex++] = moveCapture;
- }
- char getPlayerPrefix(int playerName) {
- return (playerName == PLAYERA ? (char) toupper(playerAname[0]) : (char) tolower(playerBname[0]));
- };
- char *getCurrentPlayerName() {
- return getPlayerTurn() == PLAYERA ? (char *) playerAname : (char *) playerBname;
- }
- bool checkCompleteBox(int horizontalOne, int horizontalTwo, int verticalOne, int verticalTwo, EdgeChange *ptr,
- int *changePos) {
- if (horizontalOne == -1 || horizontalTwo == -1 || verticalOne == -1 || verticalTwo == -1)return false;
- if (horizontal[horizontalOne] != EMPTY && vertical[verticalOne] != EMPTY && vertical[verticalTwo] != EMPTY &&
- horizontal[horizontalTwo] != EMPTY) {
- // capture everything
- if (horizontal[horizontalOne] != getPlayerTurn()) {
- ptr[(*changePos)++] = (EdgeChange) {HORIZONTAL, horizontalOne, horizontal[horizontalOne]};
- }
- if (horizontal[horizontalTwo] != getPlayerTurn()) {
- ptr[(*changePos)++] = (EdgeChange) {HORIZONTAL, horizontalTwo, horizontal[horizontalTwo]};
- }
- if (vertical[verticalOne] != getPlayerTurn()) {
- ptr[(*changePos)++] = (EdgeChange) {VERTICAL, verticalOne, vertical[verticalOne]};
- }
- if (vertical[verticalTwo] != getPlayerTurn()) {
- ptr[(*changePos)++] = (EdgeChange) {VERTICAL, verticalTwo, vertical[verticalTwo]};
- }
- ptr[(*changePos)++] = (EdgeChange) {BOX, MIN(horizontalOne, horizontalTwo)};
- horizontal[horizontalOne] = vertical[verticalOne] = vertical[verticalTwo] = horizontal[horizontalTwo] = getPlayerTurn();
- boxes[MIN(horizontalOne, horizontalTwo)] = getCurrentPlayerPrefix();
- if (getPlayerTurn() == PLAYERA) {
- playerAScore++;
- } else {
- playerBScore++;
- }
- remainingBoxes--;
- return true;
- }
- return false;
- }
- void processInput(MoveInput input) {
- switch (input.moveType) {
- case UNDO:
- undoMove();
- undoMove();
- return;
- case REDO:
- redoMove();
- redoMove();
- return;
- // case SAVE:
- // saveGame(input.value);
- // return;
- // case LOAD:
- // loadGame(input.value);
- // return;
- case MOVE:
- move(input.value);
- redoIndex = 0;
- return;
- default:
- printf("Invalid Input format\n");
- }
- }
- void redoMove() {
- if (!redoIndex) {
- printf("Redo List is Empty.\n");
- return;
- }
- move(redoList[redoIndex--]);
- }
- void undoMove() {
- if (!undoIndex) {
- printf("Undo List is Empty.\n");
- return;
- }
- Capture capture = undoList[--undoIndex];
- for (i = 0; i < (capture.edgeChangeLength); i++) {
- switch (capture.changedEdges[i].edgeType) {
- case VERTICAL:
- vertical[capture.changedEdges[i].edgeNum] = capture.changedEdges[i].from;
- break;
- case HORIZONTAL:
- horizontal[capture.changedEdges[i].edgeNum] = capture.changedEdges[i].from;
- break;
- case BOX:
- boxes[capture.changedEdges[i].edgeNum] = ' ';
- break;
- }
- }
- playerAScore = capture.playerAScore;
- playerBScore = capture.playerBScore;
- playerAmoves = capture.playerAmoves;
- playerBmoves = capture.playerBmoves;
- remainingBoxes = capture.remainingBox;
- hiddenMoves = capture.hiddenMoves;
- moves = capture.moves;
- redoList[++redoIndex] = capture.moveNum;
- }
- MoveInput getInput() {
- bool firstInput = 1;
- static char a[5];
- do {
- if (!firstInput) {
- printf("Please Enter A Valid Input");
- }
- firstInput = false;
- scanf("%s", a);
- if (!strcasecmp(a, UNDO_KEYWORD)) {
- return (MoveInput) {UNDO};
- } else if (!strcasecmp(a, REDO_KEYWORD)) {
- return (MoveInput) {REDO};
- } else if (!strcasecmp(a, SAVE_KEYWORD)) {
- scanf("%d", &i);
- return (MoveInput) {SAVE, i};
- } else if (!strcasecmp(a, LOAD_KEYWORD)) {
- scanf("%d", &i);
- return (MoveInput) {LOAD, i};
- }
- } while (!isFourDigitString(a));
- return (MoveInput) {MOVE, atoi(a)};
- }
- void test() {
- setbuf(stdout, NULL);
- setMode();
- enterPlayers();
- initializeMap();
- printMap();
- time(&startTime);
- while (moves < movesNum) {
- processInput(getInput());
- time(&endMove);
- totalTime = (int) (difftime(endMove, startTime));
- printf("\n\n");
- printMap();
- }
- }
- int main() {
- test();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement