Reputation: 31
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
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
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
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