Instructions
Requirements and Specifications
Source Code
#include
#include
struct Player
{
char name[15];
};
struct Board
{
struct Player black;
struct Player white;
int* grid;
int* score;
int turn;
};
// function to display score and grid
void displayGrid(struct Board board)
{
printf("Score: %s (Black) %d:%d %s (White)\n", board.black.name, board.score[0], board.score[1], board.white.name);
for (int i = 0; i < 8; i++)
{
printf(" --- --- --- --- --- --- --- --- \n");
printf("%d ", i + 1);
for (int j = 0; j < 8; j++)
{
printf("| ");
if (*(board.grid + i * 8 + j) == 0)
printf(" ");
else if (*(board.grid + i*8 + j) ==1) // black
printf("B");
else if (*(board.grid + i * 8 + j) == 2) // white
printf("W");
printf(" ");
}
printf("|\n");
}
printf(" --- --- --- --- --- --- --- --- \n");
printf(" a b c d e f g h\n");
}
int isValidMove(struct Board board, int row, int col)
{
// check that the move is valid
// first, check horizontal
int discs_to_eat = 0;
int found_other = 0;
int turn = board.turn+1; // current turn
// left side of the disc
for (int col_ = col-1; col_ >= 0; col_--)
{
if (*(board.grid + 8 * row + col_) != turn && *(board.grid + 8 * row + col_) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row + col_) == turn)
break;
}
if (discs_to_eat > 0)
return discs_to_eat;
// right side
for (int col_ = col + 1; col_ < 8; col_++)
{
if (*(board.grid + 8 * row + col_) != turn && *(board.grid + 8 * row + col_) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row + col_) == turn)
break;
}
if (discs_to_eat > 0)
return discs_to_eat;
// check vertical lines
// top side
for (int row_ = 0; row_ < row - 1; row_++)
{
if (*(board.grid + 8 * row_ + col) != turn && *(board.grid + 8 * row_ + col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row_ + col) == turn)
break;
}
if (discs_to_eat > 0)
return discs_to_eat;
// bottom side
for (int row_ = row + 1; row_ < 8; row_++)
{
if (*(board.grid + 8 * row_ + col) != turn && *(board.grid + 8 * row_ + col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row_ + col) == turn)
break;
}
if (discs_to_eat > 0)
return discs_to_eat;
// diagonal from left to disc
int current_row = row;
int current_col = col;
while (current_row > 0 && current_col > 0)
{
current_row--;
current_col--;
}
for (int cell = 0; cell < 8; cell++)
{
if (*(board.grid + 8 * current_row + current_col) != turn && *(board.grid + 8 * current_row + current_col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * current_row + current_col) == turn && current_row != row && current_col != col)
break;
current_row++;
current_col++;
if (current_row == 8 || current_col == 8)
break;
}
if (discs_to_eat > 0)
return discs_to_eat;
// diagonal from disc to right
current_row = row + 1;
current_col = col + 1;
for (int cell = 0; cell < 8; cell++)
{
if (*(board.grid + 8 * current_row + current_col) != turn && *(board.grid + 8 * current_row + current_col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * current_row + current_col) == turn && current_row != row && current_col != col)
break;
current_row++;
current_col++;
if (current_row == 8 || current_col == 8)
break;
}
if (discs_to_eat > 0)
return discs_to_eat;
return -1;
}
int applyMove(struct Board board, int row, int col)
{
// check that the move is valid
// first, check horizontal
int discs_to_eat = 0;
int found_other = 0;
int turn = board.turn+1; // current turn
int discs_eaten = 0;
// left side of the disc
for (int col_ = 0; col_ < col - 1; col_++)
{
if (*(board.grid + 8 * row + col_) != turn && *(board.grid + 8 * row + col_) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row + col_) == turn)
break;
}
if (discs_to_eat > 0)
{
for (int col_ = 0; col_ < col - 1; col_++)
{
if (*(board.grid + 8 * row + col_) != turn && *(board.grid + 8 * row + col_) > 0)
{
*(board.grid + 8 * row + col_) = turn;
board.score[turn-1] += 1;
discs_eaten++;
}
else if (*(board.grid + 8 * row + col_) == turn)
break;
}
return discs_eaten;
}
// right side
for (int col_ = col + 1; col_ < 8; col_++)
{
if (*(board.grid + 8 * row + col_) != turn && *(board.grid + 8 * row + col_) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row + col_) == turn)
break;
}
if (discs_to_eat > 0)
{
for (int col_ = col + 1; col_ < 8; col_++)
{
if (*(board.grid + 8 * row + col_) != turn && *(board.grid + 8 * row + col_) > 0)
{
*(board.grid + 8 * row + col_) = turn;
board.score[turn-1] += 1;
discs_eaten++;
}
else if (*(board.grid + 8 * row + col_) == turn)
break;
}
return discs_eaten;
}
// check vertical lines
// top side
for (int row_ = 0; row_ < row - 1; row_++)
{
if (*(board.grid + 8 * row_ + col) != turn && *(board.grid + 8 * row_ + col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row_ + col) == turn)
break;
}
if (discs_to_eat > 0)
{
for (int row_ = 0; row_ < row - 1; row_++)
{
if (*(board.grid + 8 * row_ + col) != turn && *(board.grid + 8 * row_ + col) > 0)
{
*(board.grid + 8 * row_ + col) = turn;
board.score[turn-1] += 1;
discs_eaten++;
}
else if (*(board.grid + 8 * row_ + col) == turn)
break;
}
return discs_eaten;
}
// bottom side
for (int row_ = row + 1; row_ < 8; row_++)
{
if (*(board.grid + 8 * row_ + col) != turn && *(board.grid + 8 * row_ + col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * row_ + col) == turn)
break;
}
if (discs_to_eat > 0)
{
for (int row_ = row + 1; row_ < 8; row_++)
{
if (*(board.grid + 8 * row_ + col) != turn && *(board.grid + 8 * row_ + col) > 0)
{
*(board.grid + 8 * row_ + col) = turn;
board.score[turn-1] += 1;
discs_eaten += 1;
}
else if (*(board.grid + 8 * row_ + col) == turn)
break;
}
return discs_eaten;
}
// diagonal from left to disc
int current_row = row;
int current_col = col;
while (current_row > 0 && current_col > 0)
{
current_row--;
current_col--;
}
for (int cell = 0; cell < 8; cell++)
{
if (*(board.grid + 8 * current_row + current_col) != turn && *(board.grid + 8 * current_row + current_col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * current_row + current_col) == turn && current_row != row && current_col != col)
break;
current_row++;
current_col++;
if (current_row == 8 || current_col == 8)
break;
}
if (discs_to_eat > 0)
{
current_row = row;
current_col = col;
while (current_row > 0 && current_col > 0)
{
current_row--;
current_col--;
}
for (int cell = 0; cell < 8; cell++)
{
if (*(board.grid + 8 * current_row + current_col) != turn && *(board.grid + 8 * current_row + current_col) > 0)
{
*(board.grid + 8 * current_row + current_col) = turn;
board.score[turn-1] += 1;
discs_eaten++;
}
else if (*(board.grid + 8 * current_row + current_col) == turn && current_row != row && current_col != col)
break;
current_row++;
current_col++;
if (current_row == 8 || current_col == 8)
break;
}
return discs_eaten;
}
// diagonal from disc to right
current_row = row + 1;
current_col = col + 1;
for (int cell = 0; cell < 8; cell++)
{
if (*(board.grid + 8 * current_row + current_col) != turn && *(board.grid + 8 * current_row + current_col) > 0)
discs_to_eat++;
else if (*(board.grid + 8 * current_row + current_col) == turn && current_row != row && current_col != col)
break;
current_row++;
current_col++;
if (current_row == 8 || current_col == 8)
break;
}
if (discs_to_eat > 0)
{
current_row = row + 1;
current_col = col + 1;
for (int cell = 0; cell < 8; cell++)
{
if (*(board.grid + 8 * current_row + current_col) != turn && *(board.grid + 8 * current_row + current_col) > 0)
{
*(board.grid + 8 * current_row + current_col) = turn;
board.score[turn-1] += 1;
discs_eaten++;
}
else if (*(board.grid + 8 * current_row + current_col) == turn && current_row != row && current_col != col)
break;
current_row++;
current_col++;
if (current_row == 8 || current_col == 8)
break;
}
return discs_eaten;
}
}
int getFreeCells(struct Board board)
{
int free_cells = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (*(board.grid + 8 * i + j) == 0)
free_cells++;
}
}
return free_cells;
}
int* requestMove(Board board)
{
char c1, c2;
int move[2];
// default values
move[0] = -1;
move[1] = -1;
char columns[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
// ask a player for a move
while (1) // this loop repeats until the player enters a valid move
{
printf("Enter row an column (i.e: d5) or pass (p): ");
scanf(" %c%c", &c1, &c2);
//c1 = input[0];
//c2 = input[1];
if (c1 == 'p' || c1 == 'P') // pass
{
move[0] = -2;
move[1] = -2;
break;
}
else
{
for (int i = 0; i < 8; i++)
{
if (columns[i] == c1)
{
move[1] = i;
}
}
int row = c2 - '0';
if (row >= 1 && row <= 8)
{
move[0] = row - 1;
}
// checck that the position of the movement is empty
if (move[0] != -1 && move[1] != -1)
{
int row = move[0];
int col = move[1];
if (*(board.grid + row* 8 + col) != 0) // not empty
{
// invalidate move
move[0] = -1;
move[1] = -1;
}
}
// now, check that the move is valid
if (move[0] >= 0)
{
int discs_to_eat = isValidMove(board, move[0], move[1]);
if (discs_to_eat <= 0) // not valid
{
// invalidate move
move[0] = -1;
move[1] = -1;
}
}
}
if (move[0] == -1 || move[1] == -1) // not valid row or column entered
printf("Please enter a valid move.\n");
else
break;
}
return move;
}
int main()
{
// Board object
struct Board board;
// initialize grid
board.grid = (int*)malloc(8 * 8 * sizeof(int));
// set first turn to black disc
board.turn = 0;
// initialize board's array
board.score = (int*)malloc(2 * sizeof(int));
*(board.score + 0) = 0;
*(board.score + 1) = 0;
// initialize grid
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
*(board.grid + i * 8 + j) = 0;
}
// place the 4 disks in the center
*(board.grid + 3 * 8 + 3) = 2; // white
*(board.grid + 3 * 8 + 4) = 1; // black
*(board.grid + 4 * 8 + 3) = 1; // black
*(board.grid + 4 * 8 + 4) = 2; // white;
// display greet message
printf("\t*** Welcome to Othello! ***\n");
// ask player 1 name
printf("Enter name of Player 1 (Black): ");
scanf("%s", &board.black.name);
// ask player 2 name
printf("Enter name of Player 2 (White): ");
scanf("%s", &board.white.name);
// array to hold the player's move
int* move;
// begin game
while (getFreeCells(board) > 0)
{
displayGrid(board);
// get position to move
if (board.turn == 0)
printf(" *** Black's turn *** \n");
else
printf(" *** White's turn *** \n");
move = requestMove(board);
int row = move[0];
int col = move[1];
if (move[0] == -2) // pass
{
if (board.turn == 1)
board.turn = 0;
else
board.turn = 1;
}
else
{
if (board.turn == 0) // black disc
{
*(board.grid + row * 8 + col) = 1;
applyMove(board, move[0], move[1]);
board.turn = 1;
}
else
{
*(board.grid + row * 8 + col) = 2;
applyMove(board, move[0], move[1]);
board.turn = 0;
}
}
}
// no more free cells, so get winner
//save to a file
FILE* fp;
int black_score = board.score[0];
int white_score = board.score[1];
if (black_score > white_score)
{
printf("%s is the winner!\n", board.black.name);
fprintf(fp, "%s is the winner!\n", board.black.name);
}
else if (white_score > black_score)
{
printf("%s is the winner!\n", board.white.name);
fprintf(fp, "%s is the winner!\n", board.white.name);
}
fprintf(fp, " *** Final Score *** \n");
fprintf(fp, "Score: %s (Black) %d:%d %s (White)\n", board.black.name, board.score[0], board.score[1], board.white.name);
flose(fp);
}