guy25
guy25

Reputation: 31

Check to see if the diagonal wins in tic tac toe

I have been given the code for a tic tac toe game. I produced the code to check to see if the vertical will win and have tried to check the diagonal. I was able to check the primary diagonal but can't seem to determine how to check the secondary. I thought the code i have would work but it does not. The issue I am having begins on line 172

#include <stdio.h>
#include <stdlib.h>  // rand(), srand()
#include <time.h>    // time()

// Size of the board (square)
const int  BOARD_SIZE     = 3;

// Symbols used for the board
const char BLANK_SYMBOL   = ' ';
const char COMP_SYMBOL    = 'O';
const char HUMAN_SYMBOL   = 'X';

// Human goes first
const int  HUMANS_TURN    = 0;
const int  COMPUTERS_TURN = 1;


// Function prototypes
void initializeBoard(char board[BOARD_SIZE][BOARD_SIZE]);
int  hasWon(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int  hasWonHorizontal(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int  hasWonVertical(char board[BOARD_SIZE][BOARD_SIZE], char mark);
int  hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark);
void getComputerMove(char board[BOARD_SIZE][BOARD_SIZE]);
void getHumanMove(char board[BOARD_SIZE][BOARD_SIZE]);
void printBoard(char board[BOARD_SIZE][BOARD_SIZE]);
void clearScreen(void);


//
// The main function should not be changed
//
int main(void) {
   char board[BOARD_SIZE][BOARD_SIZE];
   int  humanWon    = 0; // boolean (0/1)
   int  computerWon = 0; // boolean (0/1)
   int  move        = 0;

   // Seed the random number generator
   srand(time(0));

   initializeBoard(board);

   while ((move < (BOARD_SIZE * BOARD_SIZE)) && !humanWon && !computerWon) {
      clearScreen();

      if ((move % 2) == COMPUTERS_TURN) {
         getComputerMove(board);
      } else {
         printBoard(board);
         getHumanMove(board);
      }

      computerWon = hasWon(board, COMP_SYMBOL);
      humanWon    = hasWon(board, HUMAN_SYMBOL);
      move++;
   }

   clearScreen();
   printBoard(board);

   if (humanWon) {
      printf(">>>> You won!\n");
   } else if (computerWon) {
      printf("<<<< I won!\n");
   } else { // move >= BOARD_SIZE * BOARD_SIZE
      printf("==== A Draw\n");  
   }

   return 0;
}


//
// Initialized the board to all BLANK_SYMBOL
//
void initializeBoard(char board[BOARD_SIZE][BOARD_SIZE]) {
   int row;

   for (row = 0; row < BOARD_SIZE; row++) {
      int col;

      for (col = 0; col < BOARD_SIZE; col++) {
         board[row][col] = BLANK_SYMBOL;
      }
   }
}


//
// Determines if the 'mark' completely fills a row, column, or diagonal
// returns 1 if yes, 0 if no
//
int hasWon(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   return    hasWonHorizontal(board, mark)
      || hasWonVertical(board, mark)
      || hasWonDiagonal(board, mark);
}


//
// Determines if the 'mark' completely fills a row
// returns 1 if yes, 0 if no
//
int hasWonHorizontal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int won = 0; // boolean (0/1).  Assume lost until proven true
   int row;

   for (row = 0; row < BOARD_SIZE && !won; row++) {
      int match = 1; // boolean (0/1)
      int col;

      for (col = 0; col < BOARD_SIZE; col++) {
         if (board[row][col] != mark) {
            match = 0;
         }
      } 

      won = match;
   }

   return won;
}


//
// Determines if the 'mark' completely fills a column
// returns 1 if yes, 0 if no
//
int hasWonVertical(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int won = 0;
   int col;

   for (col = 0; col < BOARD_SIZE && !won; col++) {
      int match = 1;
      int row;

      for (row = 0; row< BOARD_SIZE; row++) {
         if(board[row][col] != mark) {
            match = 0;
         }
      }

      won = match;
   }

   return won; // Stub -- make this return the correct value
}


//
// Determines if the 'mark' completely fills a diagonal
// returns 1 if yes, 0 if no
//
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int won = 0;
   int match = 1;
   int col;

   for (col = 0; col < BOARD_SIZE && !won; col++) {
      if(board[col][col] != mark) {
         match=0;
      }
      else if(board[BOARD_SIZE-col-1][col] != mark){
         match=0;
      } 
   } 
   won = match;

   return won; // Stub -- make this return the correct value
}


//
// Gets computer move by randomly picking an unoccupied cell
//
void getComputerMove(char board[BOARD_SIZE][BOARD_SIZE]) {
   int row;
   int col;

   do {
      row = rand() % BOARD_SIZE;
      col = rand() % BOARD_SIZE;
   } while (board[row][col] != BLANK_SYMBOL);

   board[row][col] = COMP_SYMBOL;
}


//
// Gets human move by prompting user for row and column numbers
//
void getHumanMove(char board[BOARD_SIZE][BOARD_SIZE]) {
   int rowu;
   int colu;
   printf("Select the value of the row for your move: ");
   scanf("%i", &rowu);
   printf("Select the value of the column for you move: ");
   scanf("%i", &colu);

   board[rowu][colu] = HUMAN_SYMBOL;
}


//
// Prints the board to the screen.  Example:
//
//       0   1   2
//     +---+---+---+
//   0 | X |   |   |
//     +---+---+---+
//   1 |   | O | O |
//     +---+---+---+
//   2 |   |   | X |
//     +---+---+---+
//
void printBoard(char board[BOARD_SIZE][BOARD_SIZE]) {
   printf("   0   1   2\n");
   printf(" +---+---+---+\n");
   printf("0| %c | %c | %c |\n",board[0][0],board[0][1],board[0][2]);
   printf(" +---+---+---+\n");
   printf("1| %c | %c | %c |\n",board[1][0],board[1][1],board[1][2]);
   printf(" +---+---+---+\n");
   printf("2| %c | %c | %c |\n",board[2][0],board[2][1],board[2][2]);
   printf(" +---+---+---+\n");
}



//
// Clears the screen -- uses ANSI terminal control codes
//
void clearScreen(void) {
   const char ESC = 27;

   printf("%c[2J%c[H", ESC, ESC);
}

Upvotes: 0

Views: 6111

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311126

The functions can look the following way

//
// Determines if the 'mark' completely fills a row
// returns 1 if yes, 0 if no
//
int hasWonHorizontal( char board[BOARD_SIZE][BOARD_SIZE], char mark ) 
{
    int won = 0; // boolean (0/1).  

    for ( int row = 0; row < BOARD_SIZE && !won; row++ ) 
    {
        int col = 0;

        while ( col < BOARD_SIZE && board[row][col] == mark ) ++col 

        won = col == BOARD_SIZE;
    } 

    return won;
}


//
// Determines if the 'mark' completely fills a column
// returns 1 if yes, 0 if no
//
int hasWonVertical( char board[BOARD_SIZE][BOARD_SIZE], char mark ) 
{
    int won = 0;

    for ( int col = 0; col < BOARD_SIZE && !won; col++ ) 
    {
        int row = 0;

        while ( row < BOARD_SIZE && board[row][col] == mark ) ++row;

        won = row == BOARD_SIZE;     
    }

    return won; // Stub -- make this return the correct value
}


//
// Determines if the 'mark' completely fills a diagonal
// returns 1 if yes, 0 if no
//
int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) 
{
    int won = 0;
    int i = 0;

    while ( i < BOARD_SIZE && board[i][i ] == mark ) ++i;

    won = i == BOARD_SIZE;

    if ( !won )
    {
        i = 0;
        while ( i < BOARD_SIZE && board[i][BOARD_SIZE - i - 1 ] == mark ) ++i;
        won = i == BOARD_SIZE;
    }

    return won; // Stub -- make this return the correct value
}

Upvotes: 0

R Sahu
R Sahu

Reputation: 206737

Approach 1

Hard code the diagonal element indices.

int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int won = 0;
   int match = 0;

   if ( ( board[0][0] == mark &&
          board[1][1] == mark &&
          board[2][2] == mark ) &&
        ( board[0][2] == mark &&
          board[1][1] == mark &&
          board[2][0] == mark ) )

   {
      match = 1;
   }
   won = match;

   return won; // Stub -- make this return the correct value
}

Approach 2

Use for loops and iterate over the indices.

int hasWonDiagonal(char board[BOARD_SIZE][BOARD_SIZE], char mark) {
   int match = 1;
   int won = 0;
   int row = 0;

   // Check the first diagonal.
   for (row = 0; row < BOARD_SIZE && !won; row++) {
      if(board[row][row] != mark) {
         match=0;
      }
   } 

   // If the first diagonal check already produces a match,
   // there is no need to check the second diagonal.
   if ( match != 1 )
   {
      int col = BOARD_SIZE-1;
      for (row = 0; row < BOARD_SIZE && !won; row++, col--) {
         if(board[row][col] != mark){
            match=0;
         }  
      } 
   }
   won = match;

   return won; // Stub -- make this return the correct value
}

Upvotes: 0

Arthur Laks
Arthur Laks

Reputation: 514

The logic of your code is wrong. You are only checking the secondary diagonal if the cell on the primary diagonal does not equal mark.

You will need two separate variables to keep track of whether there is a victory on each diagonal. Your code should look like this:

int match_prime = 1, match_second = 1;
for(col = 0;col < BOARD_SIZE;++col){
    match_prime = board[col][col] == mark;
    match_second = board[BOARD_SIZE - col - 1][col] == mark;
}
won = match_prime || match_second;

Upvotes: 1

Related Questions