Here is my game logic:
- Tic Tac Toe - player Vs player
- Player A (first player to enter his name) is getting 'O' and is starting
- Players choose the desired spot to put their sign(X or O) using the arrows keys and pressing enter
- Possible to change the board location via a menu
- Possible to change the score area location via a menu
#include <stdio.h>
#include <Windows.h>
#include<conio.h>
enum key
{
UP,
DOWN,
LEFT,
RIGHT,
INVALID,
ENTER,
NONE
};
typedef enum key key;
key get_key();
enum LOCATION
{
MATRIX=0,
SCORE
};
typedef enum LOCATION LOCATION;
void gotoxy(int x, int y);
void MoveMatrix(int (*locations)[2],char (*matrix)[3]);
void MoveScore(int *score, int(*locations)[2],char names[2][30]);
void PrintMatrix(int(*locations)[2],char *(*matrix)[3]);
void IntitiateMatrix(char(*matrix)[3]);
int PlayGame(char(*matrix)[3], int(*locations)[2],char names[2][30],int score[2]);
void PickBox(char(*matrix)[3], int(*locations)[2], int *box);
void gotoBox(int box, int(*locations)[2]);
void updateScreen(char(*matrix)[3], int(*locations)[2], char names[2][30], int score[2], int box);
char CheckWin(char(*matrix)[3], char symbol);
void PrintScore(int(*locations)[2], int *score, char names[2][30]);
void main()
{
char names[2][30], matrix[3][3],YorN;
int locations[2][2] = { {0,0},{9,0} };
int score[2] = { 0 };
int i = 0, started = 0, won;
//Just to intitiate the names array and the matrix, incase the player chose to change their location using Move Matrix and MoveScore functions, without them firstly inttiated.
IntitiateMatrix(matrix);
strcpy(names[0], "Player A");
strcpy(names[1], "Player B");
//
while (i != 5)
{
system("cls");
printf("1. New game\n");
printf("2. Reset settings\n");
printf("3. Change Matrix Location\n");
printf("4. Change Scores bar location\n");
printf("5. Exit\n");
scanf("%d", &i);
switch (i)
{
case 1:
if (started == 0)
{
system("cls");
printf("Enter player A name! He will use O: ");
scanf("%s", names[0]);
printf("Enter player B name! He will use X: ");
scanf("%s", names[1]);
score[0] = 0;
score[1] = 0;
started = 1;
}
won = PlayGame(matrix, locations, names, score);
IntitiateMatrix(matrix);
switch (won)
{
case 1:
score[0]++;
PrintScore(locations, score, names);
break;
case 2:
score[1]++;
PrintScore(locations, score, names);
break;
default:
break;
}
getch();
break;
case 2:
started = 0;
locations[MATRIX][0] = 0;
locations[MATRIX][1] = 0;
locations[SCORE][0] = 9;
locations[SCORE][1] = 0;
strcpy(names[0], "Player A");
strcpy(names[1], "Player B");
score[0] = 0;
score[1] = 0;
break;
case 3:
MoveMatrix(locations, matrix);
//sleep(100);
break;
case 4:
MoveScore(score, locations, names);
//sleep(100);
break;
case 5:
break;
}
}
}
void gotoxy(int x, int y)
{
COORD coord;
coord.X = y;
coord.Y = x;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void MoveMatrix(int(*locations)[2], char(*matrix)[3])
{
int *x = &locations[MATRIX][0], *y = &locations[MATRIX][1];
key direction;
system("cls");
PrintMatrix(locations, matrix);
gotoxy(*x, *y);
while ((direction=get_key()) != ENTER)
{
Sleep(50);
switch (direction)
{
case ENTER:
PrintMatrix(locations, matrix);
break;
case UP:
if (*x == 0)
break;
(*x)--;
system("cls");
PrintMatrix(locations,matrix);
gotoxy(*x, *y);
break;
case DOWN:
(*x)++;
system("cls");
PrintMatrix(locations, matrix);
gotoxy(*x, *y);
break;
case LEFT:
if (*y == 0)
break;
(*y)--;
system("cls");
PrintMatrix(locations, matrix);
gotoxy(*x, *y);
break;
case RIGHT:
++(*y);
system("cls");
PrintMatrix(locations, matrix);
gotoxy(*x, *y);
break;
default:
break;
}
}
return;
}
void PrintMatrix(int (*locations)[2], char (*matrix)[3])
{
int i, j;
for (i = 0; i < 5; i++)
{
gotoxy(locations[MATRIX][0] + i, locations[MATRIX][1]);
if (i % 2 == 0)
{
for (j = 0; j < 3; j++)
{
if (j == 1)
{
printf("|%c|", matrix[i / 2][j]);
}
else
{
printf("%c", matrix[i / 2][j]);
}
}
}
else
{
printf("-----");
}
}
}
void IntitiateMatrix(char(*matrix)[3])
{
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
matrix[i][j] = ' ';
}
}
void PickBox(char(*matrix)[3], int(*locations)[2], int *box)
{
int picked = 0,tempbox=*box;
gotoBox(*box, locations);
while (picked == 0)
{
switch (get_key())
{
case UP:
if (tempbox <= 3)
break;
else
{
tempbox -= 3;
gotoBox(tempbox, locations);
break;
}
break;
case DOWN:
if (tempbox >= 7)
break;
else
{
tempbox += 3;
gotoBox(tempbox, locations);
break;
}
break;
case LEFT:
if (tempbox == 1 || tempbox == 4 || tempbox == 7)
break;
else
{
tempbox--;
gotoBox(tempbox, locations);
break;
}
break;
case RIGHT:
if (tempbox == 3 || tempbox == 6 || tempbox == 9)
break;
else
{
tempbox++;
gotoBox(tempbox, locations);
break;
}
break;
case ENTER:
if (matrix[(tempbox - 1) / 3][(tempbox - 1) % 3] != ' ')
break;
else
{
*box = tempbox;
picked = 1;
break;
}
default:
break;
}
}
return;
}
void updateScreen(char(*matrix)[3], int(*locations)[2], char names[2][30], int score[2], int box)
{
system("cls");
PrintMatrix(locations, matrix);
PrintScore(locations, score, names);
}
char CheckWin(char(*matrix)[3], char symbol)
{
int i, j;
//rows win
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (matrix[i][j] != symbol)
break;
}
if (j == 3)
return symbol;
}
//colummns win
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (matrix[j][i] != symbol)
break;
}
if (j == 3)
return symbol;
}
//main diagontal
for (i = 0; i < 3; i++)
{
if (matrix[i][i] != symbol)
break;
}
if (i == 3)
return symbol;
//second diagontal
for (i = 0; i < 3; i++)
if (matrix[i][3 - i - 1] != symbol)
break;
if (i == 3)
return symbol;
//no win
return 'T';
}
void MoveScore(int *score, int(*locations)[2], char names[2][30])
{
int *x = &locations[SCORE][0], *y = &locations[SCORE][1];
key direction;
//system("cls");
PrintScore(locations, score,names);
gotoxy(*x, *y);
while ((direction = get_key()) != ENTER)
{
Sleep(50);
switch (direction)
{
case ENTER:
break;
case UP:
if (*x == 0)
break;
(*x)--;
system("cls");
PrintScore(locations, score,names);
gotoxy(*x, *y);
break;
case DOWN:
(*x)++;
system("cls");
PrintScore(locations, score,names);
gotoxy(*x, *y);
break;
case LEFT:
if (*y == 0)
break;
(*y)--;
system("cls");
PrintScore(locations, score,names);
gotoxy(*x, *y);
break;
case RIGHT:
++(*y);
system("cls");
PrintScore(locations, score,names);
gotoxy(*x, *y);
break;
default:
break;
}
}
gotoxy(0, 0);
return;
}
void PrintScore(int(*locations)[2], int *score, char names[2][30])
{
gotoxy(locations[SCORE][0], locations[SCORE][1]);
printf("%s : %d", names[0], score[0]);
gotoxy(locations[SCORE][0]+1, locations[SCORE][1]);
printf("%s : %d", names[1], score[1]);
}
int PlayGame(char(*matrix)[3], int(*locations)[2], char names[2][30], int score[2])
{
int box = 5, i;
char status = 'T';
IntitiateMatrix(matrix);
/*Just for fun
gotoxy(5, 5);
printf("********************************");
gotoxy(6, 5);
printf("*Initiating protocol!..... *");
gotoxy(7, 5);
printf("********************************");
sleep(2000);
gotoxy(6, 5);
printf("*Creating Random Number..... *");
sleep(2000);
gotoxy(6, 5);
printf("*Ultilizing Game Board.. .. *");
sleep(2000);
*/
updateScreen(matrix, locations, names, score,box);
for (i = 0; i < 9&&status=='T'; i++)
{
if (i % 2 == 0)
{
PickBox(matrix, locations, &box);
matrix[(box - 1) / 3][(box - 1) % 3] = 'O';
updateScreen(matrix, locations, names, score, box);
status = CheckWin(matrix, 'O');
}
else
{
PickBox(matrix, locations, &box);
matrix[(box - 1) / 3][(box - 1) % 3] = 'X';
updateScreen(matrix, locations, names, score, box);
status = CheckWin(matrix, 'X');
}
}
switch (status)
{
case 'O':
gotoxy(5, 5);
printf("*****************");
gotoxy(6, 5);
printf("*%s WINS!!",names[0]);
gotoxy(6, 21);
printf("*");
gotoxy(7, 5);
printf("****************");
return 1;
case 'X':
gotoxy(5, 5);
printf("*****************");
gotoxy(6, 5);
printf("*%s WINS!!", names[1]);
gotoxy(6, 21);
printf("*");
gotoxy(7, 5);
printf("****************");
return 2;
case 'T':
gotoxy(5, 5);
printf("*****************");
gotoxy(6, 5);
printf("*Its A TIE!!.. *");
gotoxy(6, 21);
printf("*");
gotoxy(7, 5);
printf("****************");
return 0;
default:
return 0;
break;
}
}
void gotoBox(int box, int(*locations)[2])
{
int Ibox = (box - 1) / 3, Jbox = (box - 1) % 3;
if (Ibox == 1)
Ibox += 1;
else if (Ibox == 2)
Ibox += 2;
if (Jbox == 1)
Jbox += 1;
else if (Jbox == 2)
Jbox += 2;
/* to test if the additions are correct, since there are walls we need to increament x and y through those walls to their cells
gotoxy(10, 10); ///just test
printf("Pixel row [%d][%d] - box %d", locations[MATRIX][0] + Ibox, locations[MATRIX][1] + Jbox,box);
*/
gotoxy(locations[MATRIX][0] + Ibox, locations[MATRIX][1] + Jbox);
}
key get_key()
{
int ch;
if (_kbhit())
{
ch = _getch();
ch == 0 || ch == 224;
switch (ch)
{
case 0:
case 224:
switch (_getch())
{
case 72:
return UP;
case 80:
return DOWN;
case 75:
return LEFT;
case 77:
return RIGHT;
default:
return INVALID;
}
case 56:
return UP;
case 50:
return DOWN;
case 52:
return LEFT;
case 54:
return RIGHT;
case 13:
return ENTER;
default:
return INVALID;
}
}
return NONE;
}
Few notes:
- The array locations is a 2 dimensional array used to store the matrix and the score bar location.
- The function
PickBox
gets the matrix of the game, the locations and a random box that it receive, and it used to navigate in the matrix, visually for the player. If a player hit enter on an empty box. The function will return that box via the pointer to the main function which will assign the corresponding value (X or O) to it.
If you are having some hard time figuring out my meaning about the game, try to run it and play with the menu that will pop up.