-2

I've been trying to make a tic tac toe game. I had first coded a two-player game which works but then tried to make one side computerized by placing a marker on random slot but can't exactly find the issue with why it's not working properly. We get the first chance and choose the marker but after that the comp should play one slot but instead it asks us again the play the second move. Mostly the function writing and order of calling it is getting jumbled, any help is appreciated!

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

char board[3][3] = {{'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'}};

char current_marker;
int current_player;
int comp_slot;


void drawBoard(){
    cout<< "     |       |    "<<endl;
    cout<<"  "<<board[0][0]<<"  |   "<<board[0][1]<<"   |   "<<board[0][2]<<endl;
    cout<< "_____|_______|_____"<<endl;
    cout<< "     |       |    "<<endl;
    cout<<"  "<<board[1][0]<<"  |   "<<board[1][1]<<"   |   "<<board[1][2]<<endl;
    cout<< "_____|_______|_____"<<endl;
    cout<< "     |       |    "<<endl;
    cout<<"  "<<board[2][0]<<"  |   "<<board[2][1]<<"   |   "<<board[2][2]<<endl;
    cout<< "     |       |     "<<endl;
}


bool placeMarker(int slot){
    int row = slot/3;
    int col;
    if(slot % 3 == 0){
        row = row - 1;
        col = 2;
    }
    else{
       col = (slot % 3) - 1;
    }
    
    if(board[row][col] != 'X' && board[row][col] != 'O'){
        board[row][col] = current_marker;
        return true;
    }
    else return false;
}


int winner(){
    for(int i=0; i<9; i++){
        //row
        if(board[i][0] == board[i][1] && board[i][1] && board[i][2]){
            return current_player;
        }

        if(board[0][i] == board[1][i] && board[1][i] == board[2][i]){
            return current_player;
        }
    }

    //for diagonals
    if(board[0][0] == board[1][1] && board[1][1] == board[2][2]){
        return current_player;
    }

    if(board[0][2] == board[1][1] && board[1][1] == board[2][0]){
        return current_player;
    }

    return 0;
}


void swap_player_marker(){
    if(current_marker == 'X') current_marker = 'O';
    else current_marker = 'X';

    if(current_player == 1) current_player = 2;
    else current_player = 1;
}


void game(){
    //players
    string name1, name2;
    cout<<"Enter your name: ";
    cin>>name1;
    
    cout<<name1<<" choose your marker: "; 
    char h_marker; //X
    cin>>h_marker; 

    current_player = 1;
    current_marker = h_marker; //X
    
    drawBoard();
    int player_won;

    for(int i=0; i<4; i++){
        cout<<"It's your turn. Enter slot: ";
        int slot;
        cin>> slot;

        if(slot < 1 || slot > 9){
            cout<<"Slot invalid! Try another slot!"<<endl;
            i--;
            continue;
        }
        
        if(!placeMarker(slot)){
            cout<<"Slot occupied! Try another slot!"<<endl;
            i--;
            continue;
        }
        
        drawBoard();

        player_won = winner();
        if(player_won == 1){
            cout<<"You won! Congratulations!";
            break;
        }

        if(player_won == 2){
            cout<<"Comp won! Congratulations!";
            break;
        }

        int comp_slot = (rand() % (10 - 1 + 1)) + 1;
        
        if(!placeMarker(comp_slot)){
            cout<<"Slot occupied! Try another slot!"<<endl;
            i--;
            continue;
        }

        swap_player_marker();

    }

    if(player_won == 0){
        cout<<"This game is a TIE";
    }
}


int main(){
    game();
}
WhoMe
  • 1
  • 1
  • 1
  • Don't use `rand()` in C++, it has horrible period and other bad properties. Use the facilities in [](https://en.cppreference.com/w/cpp/numeric/random). But, if you *insist* on `rand()`, you should at least seed it properly with a (*one*) call to `srand()` before use. Also, your use of modulo (`%`) introduces bias, making some numbers more likely than others (look up the "pigeon hole principle"). – Jesper Juhl Sep 01 '22 at 11:36
  • Your loop says "human move, draw the board, check who's won, computer move, swap the marker, repeat", and a successful computer move has no visual indication. Start with writing down a correct loop in some non-programming language. – molbdnilo Sep 01 '22 at 11:45
  • 2
    Also, `(rand() % (10 - 1 + 1)) + 1` is `(rand() % 10) + 1`, which is a number from 1 to 10, but 10 is an invalid move. – molbdnilo Sep 01 '22 at 11:49
  • 1
    You'll be glad to hear you don't need anyone's help to figure this out, just a tool you already have: your debugger! This is exactly what a debugger is for. It [runs your program, one line at a time, and shows you what's happening](https://stackoverflow.com/questions/25385173/), this is something that's every C++ developer must know how to do. With your debugger's help you'll able to quickly find all problems in this and all future programs you write, without having to ask anyone for help. Have you tried using your debugger, already? If not, why not? What did your debugger show you? – Sam Varshavchik Sep 01 '22 at 12:36

1 Answers1

-1

Add srand((undesigned)time(0)) before using rand, Otherwise the number will repeat itself every time.

  • Don't just add that before the call to `rand()`, then you'll be re-seeding the generator before each call - not what you want. You want to seed *once* - probably in `main()`. Also, `time(0)` is a horrible seed - probably ok for something trivial like this, but in general; not what you want. Also, this doesn't really answer OPs question. – Jesper Juhl Sep 01 '22 at 11:51