3
\$\begingroup\$

I made a Tic-tac-toe game where you can play against the program or with another player in C++ and I know the code is far too long for what it is. I've tried to optimize it using non-void functions (so I don't have to create multiple functions instead of 1 for similar code) and loops to condense some repetitive code. But I couldn't get anything to work.

I'm still a beginner, so I know I'm missing something.

//Tic-tac-toe
#include <iostream>
#include <string>
#include <vector>

//variables
bool AI_is_smart, game_over, cheat, mistake;
int order, move, x, y;
int turn=1;

//vectors
    std::vector<std::string> boxes{" ", " ", " ", " ", " ", " ", " ", " ", " "};

//functions
//Shows the progression of the game
void gameboard(){
    std::cout<<" ___ ___ ___ \t _ _ _\n";
    std::cout<<"| "<<boxes[0]<<" | "<<boxes[1]<<" | "<<boxes[2]<<" |\t|0|1|2|\n";
    std::cout<<" ___ ___ ___ \t _ _ _ \n";
    std::cout<<"| "<<boxes[3]<<" | "<<boxes[4]<<" | "<<boxes[5]<<" |\t|3|4|5|\n";
    std::cout<<" ___ ___ ___ \t _ _ _ \n";
    std::cout<<"| "<<boxes[6]<<" | "<<boxes[7]<<" | "<<boxes[8]<<" |\t|6|7|8|\n";
    std::cout<<" ___ ___ ___ \t _ _ _\n\n";
}

//Determines if the game should end
bool game_over_conditions(){
    if (boxes[0]+boxes[1]+boxes[2]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[3]+boxes[4]+boxes[5]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[6]+boxes[7]+boxes[8]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[0]+boxes[3]+boxes[6]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[1]+boxes[4]+boxes[7]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[2]+boxes[5]+boxes[8]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[0]+boxes[4]+boxes[8]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[2]+boxes[4]+boxes[6]=="xxx"){std::cout<<"x WINS!\n"; game_over = true;}
    else if (boxes[0]+boxes[1]+boxes[2]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[3]+boxes[4]+boxes[5]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[6]+boxes[7]+boxes[8]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[0]+boxes[3]+boxes[6]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[1]+boxes[4]+boxes[7]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[2]+boxes[5]+boxes[8]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[0]+boxes[4]+boxes[8]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[2]+boxes[4]+boxes[6]=="ooo"){std::cout<<"o WINS!\n"; game_over = true;}
    else if (boxes[0]!=" "&&boxes[1]!=" "&&boxes[2]!=" "&&boxes[3]!=" "&&
            boxes[4]!=" "&&boxes[5]!=" "&&boxes[6]!=" "&&boxes[7]!=" "&&
            boxes[8]!=" ")
            {std::cout<<"TIE!\n"; game_over = true;}
}
    
//Determines if the AI should move with winning intent. If not then it should move randomly
bool AI_type(){   
    if(game_over==true){std::cout<<" ";}
    else if(boxes[0]+boxes[2]=="oo"&&boxes[1]==" "){std::cout<<"Program's turn (o) ...\n";boxes[1]="o";AI_is_smart=true;}
    else if(boxes[1]+boxes[2]=="oo"&&boxes[0]==" "){std::cout<<"Program's turn (o) ...\n";boxes[0]="o";AI_is_smart=true;}
    else if(boxes[3]+boxes[4]=="oo"&&boxes[5]==" "){std::cout<<"Program's turn (o) ...\n";boxes[5]="o";AI_is_smart=true;}
    else if(boxes[3]+boxes[5]=="oo"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;}
    else if(boxes[4]+boxes[5]=="oo"&&boxes[3]==" "){std::cout<<"Program's turn (o) ...\n";boxes[3]="o";AI_is_smart=true;}
    else if(boxes[6]+boxes[7]=="oo"&&boxes[8]==" "){std::cout<<"Program's turn (o) ...\n";boxes[8]="o";AI_is_smart=true;}
    else if(boxes[6]+boxes[8]=="oo"&&boxes[7]==" "){std::cout<<"Program's turn (o) ...\n";boxes[7]="o";AI_is_smart=true;}
    else if(boxes[7]+boxes[8]=="oo"&&boxes[6]==" "){std::cout<<"Program's turn (o) ...\n";boxes[6]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[3]=="oo"&&boxes[6]==" "){std::cout<<"Program's turn (o) ...\n";boxes[6]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[6]=="oo"&&boxes[3]==" "){std::cout<<"Program's turn (o) ...\n";boxes[3]="o";AI_is_smart=true;}
    else if(boxes[3]+boxes[6]=="oo"&&boxes[0]==" "){std::cout<<"Program's turn (o) ...\n";boxes[0]="o";AI_is_smart=true;}
    else if(boxes[1]+boxes[4]=="oo"&&boxes[7]==" "){std::cout<<"Program's turn (o) ...\n";boxes[7]="o";AI_is_smart=true;}
    else if(boxes[1]+boxes[7]=="oo"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;}
    else if(boxes[4]+boxes[7]=="oo"&&boxes[1]==" "){std::cout<<"Program's turn (o) ...\n";boxes[1]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[5]=="oo"&&boxes[8]==" "){std::cout<<"Program's turn (o) ...\n";boxes[8]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[8]=="oo"&&boxes[5]==" "){std::cout<<"Program's turn (o) ...\n";boxes[5]="o";AI_is_smart=true;}
    else if(boxes[5]+boxes[8]=="oo"&&boxes[2]==" "){std::cout<<"Program's turn (o) ...\n";boxes[2]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[4]=="oo"&&boxes[8]==" "){std::cout<<"Program's turn (o) ...\n";boxes[8]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[8]=="oo"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;}
    else if(boxes[4]+boxes[8]=="oo"&&boxes[0]==" "){std::cout<<"Program's turn (o) ...\n";boxes[0]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[4]=="oo"&&boxes[6]==" "){std::cout<<"Program's turn (o) ...\n";boxes[6]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[6]=="oo"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;} 
    else if(boxes[4]+boxes[6]=="oo"&&boxes[2]==" "){std::cout<<"Program's turn (o) ...\n";boxes[2]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[2]=="xx"&&boxes[1]==" "){std::cout<<"Program's turn (o) ...\n";boxes[1]="o";AI_is_smart=true;}
    else if(boxes[1]+boxes[2]=="xx"&&boxes[0]==" "){std::cout<<"Program's turn (o) ...\n";boxes[0]="o";AI_is_smart=true;}
    else if(boxes[3]+boxes[4]=="xx"&&boxes[5]==" "){std::cout<<"Program's turn (o) ...\n";boxes[5]="o";AI_is_smart=true;}
    else if(boxes[3]+boxes[5]=="xx"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;}
    else if(boxes[4]+boxes[5]=="xx"&&boxes[3]==" "){std::cout<<"Program's turn (o) ...\n";boxes[3]="o";AI_is_smart=true;}
    else if(boxes[6]+boxes[7]=="xx"&&boxes[8]==" "){std::cout<<"Program's turn (o) ...\n";boxes[8]="o";AI_is_smart=true;}
    else if(boxes[6]+boxes[8]=="xx"&&boxes[7]==" "){std::cout<<"Program's turn (o) ...\n";boxes[7]="o";AI_is_smart=true;}
    else if(boxes[7]+boxes[8]=="xx"&&boxes[6]==" "){std::cout<<"Program's turn (o) ...\n";boxes[6]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[3]=="xx"&&boxes[6]==" "){std::cout<<"Program's turn (o) ...\n";boxes[6]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[6]=="xx"&&boxes[3]==" "){std::cout<<"Program's turn (o) ...\n";boxes[3]="o";AI_is_smart=true;}
    else if(boxes[3]+boxes[6]=="xx"&&boxes[0]==" "){std::cout<<"Program's turn (o) ...\n";boxes[0]="o";AI_is_smart=true;}
    else if(boxes[1]+boxes[4]=="xx"&&boxes[7]==" "){std::cout<<"Program's turn (o) ...\n";boxes[7]="o";AI_is_smart=true;}
    else if(boxes[1]+boxes[7]=="xx"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;}
    else if(boxes[4]+boxes[7]=="xx"&&boxes[1]==" "){std::cout<<"Program's turn (o) ...\n";boxes[1]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[5]=="xx"&&boxes[8]==" "){std::cout<<"Program's turn (o) ...\n";boxes[8]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[8]=="xx"&&boxes[5]==" "){std::cout<<"Program's turn (o) ...\n";boxes[5]="o";AI_is_smart=true;}
    else if(boxes[5]+boxes[8]=="xx"&&boxes[2]==" "){std::cout<<"Program's turn (o) ...\n";boxes[2]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[4]=="xx"&&boxes[8]==" "){std::cout<<"Program's turn (o) ...\n";boxes[8]="o";AI_is_smart=true;}
    else if(boxes[0]+boxes[8]=="xx"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;}
    else if(boxes[4]+boxes[8]=="xx"&&boxes[0]==" "){std::cout<<"Program's turn (o) ...\n";boxes[0]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[4]=="xx"&&boxes[6]==" "){std::cout<<"Program's turn (o) ...\n";boxes[6]="o";AI_is_smart=true;}
    else if(boxes[2]+boxes[6]=="xx"&&boxes[4]==" "){std::cout<<"Program's turn (o) ...\n";boxes[4]="o";AI_is_smart=true;} 
    else if(boxes[4]+boxes[6]=="xx"&&boxes[2]==" "){std::cout<<"Program's turn (o) ...\n";boxes[2]="o";AI_is_smart=true;}
    else{AI_is_smart=false;}
}
    
//AI moves randomly else sequentially
void program_move_random(){
    srand (time(NULL));
    move = rand()%9;
    if(AI_is_smart==false){
        std::cout<<"Program's turn (o) ...\n";
        if (boxes[move]!="x"&&boxes[move]!="o") {boxes[move]="o";}
        else{   if(boxes[0]==" ") { ; boxes[0]="o";}
                else if(boxes[0]!=" "){ int x=1;
                    if(boxes[x]==" ") {;boxes[x]="o";}
                    else if(boxes[x]!=" "){ int x=2;
                        if(boxes[x]==" ") {;boxes[x]="o";}
                        else if(boxes[x]!=" "){  int x=3;
                            if(boxes[x]==" ") {;boxes[x]="o";}
                            else if(boxes[x]!=" "){ int x=4; 
                                if(boxes[x]==" ") {;boxes[x]="o";}
                                else if(boxes[x]!=" "){ int x=5;
                                    if(boxes[x]==" ") {;boxes[x]="o";}
                                    else if(boxes[x]!=" "){ int x=6;
                                        if(boxes[x]==" ") {;boxes[x]="o";}
                                        else if(boxes[x]!=" "){  int x=7;       
                                            if(boxes[x]==" ") {;boxes[x]="o";}
                                            else if(boxes[x]!=" "){  int x=8;
                                                if(boxes[x]==" ") {;boxes[x]="o";}
                                                else if(boxes[x]!=" "){std::cout<<" ";
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        
    }


    else if(AI_is_smart==false&&game_over==true){std::cout<<" ";
    }
}
           
//Player moves when vs Program 
void player_move(){
    if(game_over==false){std::cin>>move;
        if (boxes[move]=="o"){std::cout<<"Don't Cheat! You lose a turn...\n";}
        else if (boxes[move]=="x"){std::cout<<"You already own that square! Please try again...\n";
            std::cout<<"Your Turn (x) ...\n";
            std::cin>>move;   
            if (boxes[move]=="x"){std::cout<<"Don't delay the game! You lose a turn...\n";}
            else if (boxes[move]=="o"){std::cout<<"Don't Cheat! You lose a turn...\n";}
            else {boxes[move]="x";}
        }
        else {boxes[move]="x";}
    }
}
            
//Player 1 moves in pvp
void player1_move(){
    if(game_over==false){
        std::cin>>move;
        if (boxes[move]=="o"){std::cout<<"Don't Cheat! Player x loses a turn...\n";}
        else if (boxes[move]=="x"){std::cout<<"You already own that square! Player x please try again...\n";
            std::cout<<"Player 1's turn (x)...\n";
            std::cin>>move;   
            if (boxes[move]=="x") {std::cout<<"Don't delay the game! Player x loses a turn...\n";}
            else if (boxes[move]=="o") {std::cout<<"Don't Cheat! Player x loses a turn...\n";}
            else {boxes[move]="x";}
        }
        else {boxes[move]="x";}
    }
}
    
//Player 2 moves in pvp
void player2_move(){
    if(game_over==false){
        std::cin>>move;
        if (boxes[move]=="x"){std::cout<<"Don't Cheat! Player o loses a turn...\n";}
        else if (boxes[move]=="o"){std::cout<<"You already own that square! Player o please try again...\n";
            std::cout<<"Player 1's turn (o)...\n";
            std::cin>>move;   
            if (boxes[move]=="o") {std::cout<<"Don't delay the game! Player o loses a turn...\n";}
            else if (boxes[move]=="x") {std::cout<<"Don't Cheat! Player o loses a turn...\n";}
            else {boxes[move]="o";}
        }
        else {boxes[move]="o";}
    }
}

int main() {
    std::cout<<"Tic-tac-toe\n";
    std::cout<<" ___ ___ ___ "<<'\n';
    std::cout<<"| 0 | 1 | 2 |"<<'\n';
    std::cout<<" ___ ___ ___ "<<'\n';
    std::cout<<"| 3 | 4 | 5 |"<<'\n';
    std::cout<<" ___ ___ ___ "<<'\n';
    std::cout<<"| 6 | 7 | 8 |"<<'\n';
    std::cout<<" ___ ___ ___ "<<"\n\n";
    std::cout<<"Player vs Program (Player moves first)... Press 1.\n";
    std::cout<<"Player vs Program (Program moves first)... Press 2.\n";
    std::cout<<"Player vs Player... Press 3.\n";
    std::cin>>order;

    /**********************************
    1. Player vs Program (Player moves first) 
    **********************************/
    if (order==1) {std::cout<<"\nSelected: Player vs Program (Player moves first)...\n";
    
        for(game_over=false; game_over==false&&turn<8;){ 
            
            if(game_over==false){
            std::cout<<"\nTurn #"<<turn<<"\n";
        
            std::cout<<"Player's turn (x)...\n";
            player_move();
            gameboard();
            game_over_conditions();
        
            AI_type();
            program_move_random();
            gameboard();
            game_over_conditions();
        
            std::cout<<"\n_______________________\n\n";
            turn++;}
        }
    }
        
    /**********************************
    2. Player vs Program (Program moves first)
    **********************************/
    else if (order==2) {std::cout<<"Selected: Player vs Program (Program moves first)...\n\n";

        for(game_over=false; game_over==false&&turn<8;){ 
            
            if(game_over==false){
            std::cout<<"\nTurn #"<<turn<<"\n";
        
            AI_type();
            program_move_random();
            gameboard();
            game_over_conditions();
        
            std::cout<<"Player's turn (x)...\n";
            player_move();
            gameboard();
            game_over_conditions();

            std::cout<<"\n_______________________\n\n";
            turn++;}
        }
    }
        
    /**********************************
    3. Player vs Player
    **********************************/
    else if (order==3) {std::cout<<"Selected: Player vs Player...\n\n";
        for(game_over=false; game_over==false&&turn<8;){
            if(game_over==false){
            
            std::cout<<"Player 1's turn (x) ...\n";
            player1_move();
            gameboard();
            game_over_conditions();
        
            std::cout<<"Player 2's turn (x) ...\n";
            player2_move();
            gameboard();
            game_over_conditions();}
        }
    }
}
\$\endgroup\$
2

1 Answer 1

1
\$\begingroup\$

You are hard-coding which board indices You check. If You look how indices change, then there are rather simple patterns how they are generated.

a) For example generate indices through some loop

//
// For example to go through all rows
//
for (int row = 0; row < 3; row++) {


    auto myCount = 0;
    auto emptyCount = 0;
    auto emptyIndex = 0;

    // go to the end of a row
    for (int column = 0; column < 3; column++) {
        auto boxIndex = 3 * row + column;


        /// gather information about row

        if (boxes[boxIndex] == "o") {
            myCount++;
        }
        else if (boxes[boxIndex] == " ") {
            emptyCount++;
            emptyIndex = boxIndex;
        }
    }

    /// decide what to do with a row

    if (myCount == 2 && emptyCount == 1) {
        std::cout << "Program's turn (o) ...\n";
        boxes[boxIndex] = "o";
        AI_is_smart = true;

        break; // we found first row for AI, we can stop searching ...
    }
}

b) For example generate indices by making a stepper / walker

You gave it starting position, information about board, how many steps it has to make. Then You will ask it to move itself by one step and report it to You.

//
// For example to go through all rows
//
for (int startRow = 0; startRow < 3; startRow++) {

    // initialize_stepper arguments (board rowCount, board columnCount, startRow, startColumn, columnIncrease)

    Stepper stepper = intitialize_stepper( 3, 3, 3, startRow, 0, 0, 1);

    // move_one_step_and_return_index() returns boxIndex or -1 if no position is possible
    while ((boxIndex = move_one_step_and_return_index( &stepper )) != -1) {
        

        if (boxes[boxIndex] == "o") {
            // ...
        }
    }
}

// stepper is someting like this
int intitialize_stepper( int rowCount, int columnCount, int stepCount, int startRow, int startColumn, int stepRowIncrease, int stepColumnIncrease ) {
   ...
}

int move_one_step_and_return_index( Stepper *s )
{
   if( s->steps_remaining <= 0 ) return -1;

   s->row += s->row_step;
   s->column += s->column_step;  
   s->steps_remaining -- ;

   if( s->row >= s->rowCount || s->row < 0 ) return -1;
   if( s->column >= s->column Count || s->column < 0 ) return -1;

   auto boxIndex = s->columnCount * s->row + s->column;
   return boxIndex;
}

```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.