My code keeps working for a couple inputs and then ends citing a segmentation fault. I do not do any dynamic memory allocation. It's supposed to be a game of reversi (aka othello). The include lab8part1 contains the stdbool and declares some of the functions.
#include <stdio.h>
#include <stdlib.h>
//#include "lab8part1.h"
#include <stdbool.h>
void printBoard(char board[][26], int n);
bool positionInBounds(int n, int row, int col);
bool checkLegalInDirection(char board[][26], int n, int row, int col, char colour, int deltaRow, int deltaCol);
bool validMove(char board[][26], int n, int row, int col, char colour);
bool computerMove(char board[][26], int n, char colour, char row, char col);
bool UserMove(char board[][26], int n, char colour, char row, char col);
int checkBestMoves(char board[][26], int n, int row, int col, char colour, int deltaRow, int deltaCol);
bool checkifmove(char board[][26], int n, char color);
int
main(void)
{
char board[26][26],
color,
row,
col;
printf("Enter the board dimension: ");
int n;
scanf(" %d", &n);
int start = n / 2;
for (int m = 0; m < n; m++) {
for (int j = 0; j < n; j++) {
if ((m == start - 1 && j == start - 1) ||
(m == start && j == start)) {
board[m][j] = 'W';
}
else if ((m == start - 1 && j == start) ||
(m == start && j == start - 1)) {
board[m][j] = 'B';
}
else {
board[m][j] = 'U';
}
}
}
printf("Computer plays (B/W): ");
scanf(" %c", &color);
char color1;
if (color == 'B') {
color1 = 'W';
}
else {
color1 = 'B';
}
printBoard(board, n);
printf("\n");
char turn = 'B';
bool validmove = true;
while ((checkifmove(board, n, color) == true) ||
(checkifmove(board, n, color1) == true)) {
validmove = true;
if (turn == color) {
validmove = computerMove(board, n, color, row, col);
}
else {
UserMove(board, n, color1, row, col);
}
if (validmove == false) {
break;
}
if (turn == 'W') {
turn = 'B';
}
else {
turn = 'W';
}
}
int whitwin = 0;
int blacwin = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'W') {
whitwin += 1;
}
else {
blacwin += 1;
}
}
}
if (whitwin > blacwin) {
printf("W player wins.");
}
else if (whitwin < blacwin) {
printf("B player wins.");
}
else {
printf("Draw.");
}
return 0;
}
bool
computerMove(char board[][26], int n, char colour, char row, char col)
{
int movesrow[100] = { 0 };
int movescol[100] = { 0 };
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'U') {
if (checkLegalInDirection(board, n, i, j, colour, -1, -1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, -1, 0)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, -1, 1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 0, -1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 0, 1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 1, -1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 1, 0)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 1, 1)) {
movesrow[count] = i;
movescol[count] = j;
}
}
}
count += 1;
}
int bestMoves[600] = { 0 };
int tracker = 0;
int tot = 0;
for (int i = 0; i < count; i++) {
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, -1, -1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, -1, 0);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, -1, 1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 0, -1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 0, 1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 1, -1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 1, 0);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 1, 1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
}
// if computer runs out of moves
if (bestMoves[0] == 0) {
printf("%c player has no valid move.", colour);
return false;
}
int counter = 0;
int bigNum = bestMoves[0];
int duplicates[tracker];
for (int i = 1; i < tracker; i++) {
if (bestMoves[i] > bigNum) {
bigNum = bestMoves[i];
duplicates[0] = i;
counter = 1;
}
else if (bestMoves[i] == bigNum) {
duplicates[counter] = i;
counter++;
}
}
int rowtemp = 0,
coltemp = 0;
for (int i = 0; i < counter; i++) {
for (int j = 0; j < n; j++) {
if ((movesrow[duplicates[i]] < movesrow[duplicates[i + j]]) &&
movescol[duplicates[i]] < movescol[duplicates[i + j]]) {
rowtemp = movesrow[duplicates[i]];
coltemp = movescol[duplicates[i]];
}
else {
rowtemp = movesrow[duplicates[i + j]];
coltemp = movescol[duplicates[i + j]];
}
}
}
row = rowtemp;
col = coltemp;
if (validMove(board, n, (row), (col), colour)) {
board[row][col] = colour;
printf("\nComputer places %c at %c%c\n", colour, (row + 'a'), (col + 'a'));
printBoard(board, n);
return true;
}
else {
return false;
}
}
bool
UserMove(char board[][26], int n, char colour, char row, char col)
{
int movesrow[100] = { 0 };
int movescol[100] = { 0 };
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'U') {
if (checkLegalInDirection(board, n, i, j, colour, -1, -1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, -1, 0)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, -1, 1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 0, -1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 0, 1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 1, -1)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 1, 0)) {
movesrow[count] = i;
movescol[count] = j;
}
if (checkLegalInDirection(board, n, i, j, colour, 1, 1)) {
movesrow[count] = i;
movescol[count] = j;
}
}
}
count += 1;
}
int bestMoves[100] = { 0 };
int tracker = 0;
int tot = 0;
for (int i = 0; i < count; i++) {
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, -1, -1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, -1, 0);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, -1, 1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 0, -1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 0, 1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 1, -1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 1, 0);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
if (tot != 0) {
tracker += 1;
}
tot = 0;
for (int j = 0; j < count; j++) {
tot += checkBestMoves(board, n, movesrow[i], movescol[i], colour, 1, 1);
if (tot != 0) {
bestMoves[tracker] = tot;
}
}
}
// if player runs out of moves
if (bestMoves[0] == 0) {
printf("%c player has no valid move.", colour);
return false;
}
printf("\nEnter a move for colour %c (RowCol): ", colour);
scanf(" %c%c", &row, &col);
if (validMove(board, n, (row - 'a'), (col - 'a'), colour)) {
board[row - 'a'][col - 'a'] = colour;
printBoard(board, n);
}
}
bool
validMove(char board[][26], int n, int row, int col, char colour)
{
int score = 0;
if (checkLegalInDirection(board, n, row, col, colour, -1, -1)) {
score++;
int i = 1;
while (board[row + (i * -1)][col + (i * -1)] != colour) {
board[row + (i * -1)][col + (i * -1)] = colour;
i++;
}
}
if (checkLegalInDirection(board, n, row, col, colour, -1, 0)) {
score++;
int i = 1;
while (board[row + (i * -1)][col + (i * 0)] != colour) {
board[row + (i * -1)][col + (i * 0)] = colour;
i++;
}
}
if (checkLegalInDirection(board, n, row, col, colour, -1, 1)) {
score++;
int i = 1;
while (board[row + (i * -1)][col + (i * 1)] != colour) {
board[row + (i * -1)][col + (i * 1)] = colour;
i++;
}
}
if (checkLegalInDirection(board, n, row, col, colour, 0, -1)) {
score++;
int i = 1;
while (board[row + (i * 0)][col + (i * -1)] != colour) {
board[row + (i * 0)][col + (i * -1)] = colour;
i++;
}
}
if (checkLegalInDirection(board, n, row, col, colour, 0, 1)) {
score++;
int i = 1;
while (board[row + (i * 0)][col + (i * 1)] != colour) {
board[row + (i * 0)][col + (i * 1)] = colour;
i++;
}
}
if (checkLegalInDirection(board, n, row, col, colour, 1, -1)) {
score++;
int i = 1;
while (board[row + (i * 1)][col + (i * -1)] != colour) {
board[row + (i * 1)][col + (i * -1)] = colour;
i++;
}
}
if (checkLegalInDirection(board, n, row, col, colour, 1, 0)) {
score++;
int i = 1;
while (board[row + (i * 1)][col + (i * 0)] != colour) {
board[row + (i * 1)][col + (i * 0)] = colour;
i++;
}
}
if (checkLegalInDirection(board, n, row, col, colour, 1, 1)) {
score++;
int i = 1;
while (board[row + (i * 1)][col + (i * 1)] != colour) {
board[row + (i * 1)][col + (i * 1)] = colour;
i++;
}
}
if (score > 0) {
return true;
}
else {
return false;
}
}
void
printBoard(char board[][26], int n)
{
printf(" ");
for (int i = 0; i < n; i++) {
printf("%c", 'a' + i);
}
for (int m = 0; m < n; m++) {
printf("\n%c ", 'a' + m);
for (int j = 0; j < n; j++) {
printf("%c", board[m][j]);
}
}
}
bool
positionInBounds(int n, int row, int col)
{
if (row >= 0 && row < n && col >= 0 && col < n) {
return true;
}
else {
return false;
}
}
bool
checkLegalInDirection(char board[][26], int n, int row, int col, char colour,
int deltaRow, int deltaCol)
{
if (positionInBounds(n, row, col) == false) {
return false;
}
if (board[row][col] != 'U') {
return false;
}
row += deltaRow;
col += deltaCol;
if (positionInBounds(n, row, col) == false) {
return false;
}
if (board[row][col] == colour || board[row][col] == 'U') {
return false;
}
while ((positionInBounds(n, row, col)) == true) {
if (board[row][col] == colour) {
return true;
}
if (board[row][col] == 'U') {
return false;
}
row += deltaRow;
col += deltaCol;
}
return false;
}
int
checkBestMoves(char board[][26], int n, int row, int col, char colour,
int deltaRow, int deltaCol)
{
int tiles = 0;
if (positionInBounds(n, row, col) == false) {
return false;
}
if (board[row][col] != 'U') {
return false;
}
row += deltaRow;
col += deltaCol;
if (positionInBounds(n, row, col) == false) {
return false;
}
if (board[row][col] == colour || board[row][col] == 'U') {
return false;
}
while ((positionInBounds(n, row, col)) == true) {
if (board[row][col] == colour) {
return tiles;
}
if (board[row][col] == 'U') {
return false;
}
tiles += 1;
row += deltaRow;
col += deltaCol;
}
return false;
}
bool
checkifmove(char board[][26], int n, char color)
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == 'U') {
if (checkLegalInDirection(board, n, i, j, color, -1, -1) ||
checkLegalInDirection(board, n, i, j, color, -1, 0) ||
checkLegalInDirection(board, n, i, j, color, -1, 1) ||
checkLegalInDirection(board, n, i, j, color, 0, -1) ||
checkLegalInDirection(board, n, i, j, color, 0, 1) ||
checkLegalInDirection(board, n, i, j, color, 1, -1) ||
checkLegalInDirection(board, n, i, j, color, 1, 0) ||
checkLegalInDirection(board, n, i, j, color, 1, 1)) {
return true;
}
}
}
}
return false;
}
I have messed with shortening and expanding the array sizes but nothing seems to be working. I also tried using malloc but encountered the same problem.
[Per my top comment], building with
-Wall -O0 -g -fsanitize=address, a few issues ...-Wall, argumentscolandrowarecharand compiler complains about that (converted toint)rowandcolare unitialized (inmain) but the values are never used bycomputerMoveorUserMove(set to zero to eliminate warning). They do not need to be arguments.With a board size of
8and computer withB, incomputerMove, the sanitizer complains about theif:The debug
printfI added shows:The array
duplicatesis of dimensiontracker(which is 4), soi + jis becoming too large and overflowsduplicates. This is UB (undefined behavior).Further,
duplicatesis initialized starting at index of 1. But, in the loop that follows,duplicates[i]is being fetched, so wheniis 0, the array value is random (this is, again, UB).Here is the refactored code. It is annotated:
In the code above, I've used
cppconditionals to denote old vs. new code:Note: this can be cleaned up by running the file through
unifdef -k