This is a tic-tac-toe game that I made in C. It works the way that I want it to but I feel like I could have done it better or shorter. Any input as to how I did would be appreciated.
Include Statements and Prototypes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Creating the prototypes
int init(char ttt1[3][3]);
int display_board(char ttt2[3][3]);
int turn(int *player_turns);
int get_move(char ttt3[3][3], int player_turns2, int *move, char player1[], char player2[]);
int validate_move(int move);
int check_win(char ttt[3][3], int turns);
int update_board(char ttt[3][3], const int * move, int turn);
int menu();
Main Function
int main(void) {
int play_again = 1; //set up the loop
if(menu() == 1){ //calling the menu
while(play_again == 1) { //as long as the player wants to play again, loop
int player_turn = 1;
int move = 0;
int turns = 1;
char player1[20];
char player2[20];
char ttt[3][3]; //create the array
init(ttt); //initialize the board
printf("Enter Player 1 name(without using spaces): ");
scanf(" %s", player1);
printf("%s, you are 'X'\n", player1);
printf("Enter Player 2 name(without using spaces): ");
scanf(" %s", player2);
printf("%s, you are 'O'\n", player2);
while (check_win(ttt, turns) == 0) {
get_move(ttt, player_turn, &move, player1, player2); //receive the moves from the player
validate_move(move); //call the function to validate the moves
update_board(ttt, &move, player_turn); //call the function which updates the board based on the players move
display_board(ttt); //redisplay the board
turn(&player_turn); //call the function to change whose turn it is
turns++; //increment turns
}
printf("Would you like to play again?(1 for yes, 2 for no) ");
scanf(" %d", &play_again);
}
}
return 0;
}
Board Initializer
//set up the board for use in the game
int init(char ttt1[3][3]){
ttt1[0][0] = '1';
ttt1[0][1] = '2';
ttt1[0][2] = '3';
ttt1[1][0] = '4';
ttt1[1][1] = '5';
ttt1[1][2] = '6';
ttt1[2][0] = '7';
ttt1[2][1] = '8';
ttt1[2][2] = '9';
return 0;
}
Board Display
This does display the board the way it should but I need a way to clear the screen. I have tried a few ways that I found online but since I am on Mac OS none of it worked. What is a good way to clear the screen that is portable?
//showing the board on the screen
int display_board(char ttt2[3][3]){
printf("%c | %c | %c\n", ttt2[0][0], ttt2[0][1], ttt2[0][2]); //displays the top row
printf("----------\n");
printf("%c | %c | %c\n", ttt2[1][0], ttt2[1][1], ttt2[1][2]); //displays the middle row
printf("----------\n");
printf("%c | %c | %c\n", ttt2[2][0], ttt2[2][1], ttt2[2][2]); //displays the bottom row
return 0;
}
Which Turn
int turn(int *player_turns1){
if(*player_turns1 == 1){ //if it is player one's turn
*player_turns1 = 2; //change it to player two's turn
}
else if(*player_turns1 == 2){ //if it is player two's turn
*player_turns1 = 1; // change it to player one's turn
}
return 0;
}
Move Retrieval
//get the move from the player depending on whose turn it is
int get_move(char ttt3[3][3], int player_turns2, int *move, char player1_1[], char player2_1[]){
if(player_turns2 == 1){ //if it is player one's turn
display_board(ttt3); //display the board
printf("%s, please enter where you would like to move: ", player1_1); //ask for the move
scanf(" %d", move);//get the move from the player
}
else if(player_turns2 == 2){ //if it is player two's turn
display_board(ttt3); //display the board
printf("%s, please enter where you would like to move: ", player2_1); //ask for the move
scanf(" %d", move); //get the move from the player
}
return *move;
}
Move Validator
int validate_move(int move1){
if (move1 < 1 || move1 > 9) { //if the move is on the board
return 0;
}
else //if the move does not fall on the board
return 1;
}
Update the Board
//function that updates the board with the user's move
int update_board(char ttt[3][3], const int *move, int turn){
if(*move == 1 && turn == 1) //top left is chosen by player one
ttt[0][0] = 'X'; //set the square to x
else if(*move == 1 && turn == 2) //top left is chosen by player two
ttt[0][0] = 'O'; //set the square to o
else if(*move == 2 && turn == 1) //top middle is chosen by player one
ttt[0][1] = 'X'; //set the square to x
else if(*move == 2 && turn == 2) //top middle is chosen by player two
ttt[0][1] = 'O'; //set the square to o
else if(*move == 3 && turn == 1) //top right is chosen by player one
ttt[0][2] = 'X'; //set the square to x
else if(*move == 3 && turn == 2) //top right is chosen by player two
ttt[0][2] = 'O'; //set the square to o
else if(*move == 4 && turn == 1) //middle left is chosen by player one
ttt[1][0] = 'X'; //set the square to x
else if(*move == 4 && turn == 2) //middle left is chosen by player two
ttt[1][0] = 'O'; //set the square to o
else if(*move == 5 && turn == 1) //middle is chosen by player one
ttt[1][1] = 'X'; //set the square to x
else if(*move == 5 && turn == 2) //middle is chosen by player two
ttt[1][1] = 'O'; //set the square to o
else if(*move == 6 && turn == 1) //middle right is chosen by player one
ttt[1][2] = 'X'; //set the square to x
else if(*move == 6 && turn == 2) //middle right is chosen by player two
ttt[1][2] = 'O'; //set the square to o
else if(*move == 7 && turn == 1) //bottom right is chosen by player one
ttt[2][0] = 'X'; //set the square to x
else if(*move == 7 && turn == 2) //bottom right is chosen by player two
ttt[2][0] = 'O'; //set the square to o
else if(*move == 8 && turn == 1) //bottom middle is chosen by player one
ttt[2][1] = 'X'; //set the square to x
else if(*move == 8 && turn == 2) //bottom middle is chosen by player two
ttt[2][1] = 'O';//set the square to o
else if(*move == 9 && turn == 1) //bottom right is chosen by player one
ttt[2][2] = 'X'; //set the square to x
else if(*move == 9 && turn == 2) //bottom right is chosen by player two
ttt[2][2] = 'O'; //set the square to o
return 0;
}
Victory/Tie Check
//check the board to see if there is a winner
int check_win(char ttt[3][3], int turns1){
if(ttt[0][0] == ttt[0][1] && ttt[0][1] == ttt[0][2]) { //top row horizontal check
printf("Congratulations, You Won!\n");
return 1;
}
else if(ttt[1][0] == ttt[1][1] && ttt[1][1] == ttt[1][2]) { //middle row horizontal check
printf("Congratulations, You Won!\n");
return 1;
}
else if(ttt[2][0] == ttt[2][1] && ttt[2][1] == ttt[2][2]) { //bottom row horizontal check
printf("Congratulations, You Won!\n");
return 1;
}
else if(ttt[0][0] == ttt[1][0] && ttt[1][0] == ttt[2][0]) { //left column vertical check
printf("Congratulations, You Won!\n");
return 1;
}
else if(ttt[0][1] == ttt[1][1] && ttt[1][1] == ttt[2][1]) { //middle column vertical check
printf("Congratulations, You Won!\n");
return 1;
}
else if(ttt[0][2] == ttt[1][2] && ttt[1][2] == ttt[2][2]) { //right column vertical check
printf("Congratulations, You Won!\n");
return 1;
}
else if(ttt[0][0] == ttt[1][1] && ttt[1][1] == ttt[2][2]) { //top left to bottom right diagonal check
printf("Congratulations, You Won!\n");
return 1;
}
else if(ttt[2][0] == ttt[1][1] && ttt[1][1] == ttt[0][2]) { //top right to bottom left diagonal check
printf("Congratulations, You Won!\n");
return 1;
}
else if(turns1 >= 10) //checks to see if the game ends in a tie
printf("The game ends in a draw, no one wins.\n");
else
return 0;
}
Menu Function
Switch/Case seemed to be the best way that I could think of to do a menu. Options 2-4 are my next projects to be working on.
//the function that controls the menu
int menu(){
int state = 0; //establish the state variable
printf("Welcome to my Tic Tac Toe Game!\n");
printf("How would you like to play?\n");
printf("1. 2D Player vs. Player\n");
printf("2. 2D Player vs. Computer(Not ready yet)\n");
printf("3. 3D Player vs. Player(Not ready yet)\n");
printf("3. 3D Player vs. Computer(Not ready yet)\n");
printf("Enter your choice: ");
scanf(" %d", &state); //get the user's choice for the menu
switch(state){
case 1: //option 1 in the menu
return 1;
case 2: //option 2 in the menu
return 2;
case 3: //option 3 in the menu
return 3;
case 4: //option 4 in the menu
return 4;
default: //if an invalid option is chosen
printf("There was an error. Please try again.");
}
}
I know that this code works as I want it to but I feel like it's too long or that there are easier ways to achieve some of the tasks. Again, any help or input is much appreciated.