Search code examples
c#tic-tac-toe

tick tac toe against computer


So I programmed an Tic Tac Toe game. At this moment it is an person vs person game. Now I want that the computer is the one person so "person vs computer" I already programmed the computer that it should answer the game, but its still person vs person. How can I change my programm so, that the computer is answering?

the code for the Tic Tac Toe is this:

bool turn = true;
int tic_counter = 0;
public Baden()
{
    InitializeComponent();
}

private void button_click(object sender, MouseEventArgs e)
{
    Button b = (Button)sender;
    if (turn)
        b.Text = "X";
    else
        b.Text = "O";
        computer_make_move();

    turn = !turn;
    b.Enabled = false;
    tic_counter++;

    CheckForWinner();    
}

private void CheckForWinner()
{
    bool there_is_a_winner = false;

    if ((A1.Text == A2.Text) && (A2.Text == A3.Text) && (!A1.Enabled))
        there_is_a_winner = true;
    else if ((B1.Text == B2.Text) && (B2.Text == B3.Text) && (!B1.Enabled))
        there_is_a_winner = true;
    else if ((C1.Text == C2.Text) && (C2.Text == C3.Text) && (!C1.Enabled))
        there_is_a_winner = true;



    if ((A1.Text == B1.Text) && (B1.Text == C1.Text) && (!A1.Enabled))
        there_is_a_winner = true;
    else if ((B2.Text == A2.Text) && (A2.Text == C2.Text) && (!A2.Enabled))
        there_is_a_winner = true;
    else if ((C3.Text == A3.Text) && (A3.Text == B3.Text) && (!A3.Enabled))
        there_is_a_winner = true;


    if ((A1.Text == B2.Text) && (B2.Text == C3.Text) && (!A1.Enabled))
        there_is_a_winner = true;
    else if ((B2.Text == A3.Text) && (A3.Text == C1.Text) && (!B2.Enabled))
        there_is_a_winner = true;


    if (there_is_a_winner)
    {
        disableButtons();
        String winner = "";
        if (turn)
            winner = "O";
        else
            winner = "X";

        MessageBox.Show("Der gewinner ist: " + winner);
        this.Close();
    }
    else
    {
        if(tic_counter == 9)
        {
            MessageBox.Show("Unentschieden!");
            this.Close();
        }
    }
}

And the Computer is this:

private void computer_make_move()
{
    //priority 1:  get tick tac toe
    //priority 2:  block x tic tac toe
    //priority 3:  go for corner space
    //priority 4:  pick open space

    Button move = null;

    //look for tic tac toe opportunities
    move = look_for_win_or_block("O"); //look for win
    if (move == null)
    {
        move = look_for_win_or_block("X"); //look for block
        if (move == null)
        {
            move = look_for_corner();
            if (move == null)
            {
                move = look_for_open_space();
            }
        }

    }
    move.PerformClick();

}

private Button look_for_open_space()
{
    Console.WriteLine("Looking for open space");
    Button b = null;
    foreach (Control c in Controls)
    {
        b = c as Button;
        if (b != null)
        {
            if (b.Text == "")
                return b;
        }//end if
    }//end if

    return null;
}

private Button look_for_corner()
{
    Console.WriteLine("Looking for corner");
    if (A1.Text == "O")
    {
        if (A3.Text == "")
            return A3;
        if (C3.Text == "")
            return C3;
        if (C1.Text == "")
            return C1;
    }

    if (A3.Text == "O")
    {
        if (A1.Text == "")
            return A1;
        if (C3.Text == "")
            return C3;
        if (C1.Text == "")
            return C1;
    }

    if (C3.Text == "O")
    {
        if (A1.Text == "")
            return A3;
        if (A3.Text == "")
            return A3;
        if (C1.Text == "")
            return C1;
    }

    if (C1.Text == "O")
    {
        if (A1.Text == "")
            return A3;
        if (A3.Text == "")
            return A3;
        if (C3.Text == "")
            return C3;
    }

    if (A1.Text == "")
        return A1;
    if (A3.Text == "")
        return A3;
    if (C1.Text == "")
        return C1;
    if (C3.Text == "")
        return C3;

    return null;
}

private Button look_for_win_or_block(string mark)
{
    Console.WriteLine("Looking for win or block:  " + mark);
    //HORIZONTAL TESTS
    if ((A1.Text == mark) && (A2.Text == mark) && (A3.Text == ""))
        return A3;
    if ((A2.Text == mark) && (A3.Text == mark) && (A1.Text == ""))
        return A1;
    if ((A1.Text == mark) && (A3.Text == mark) && (A2.Text == ""))
        return A2;

    if ((B1.Text == mark) && (B2.Text == mark) && (B3.Text == ""))
        return B3;
    if ((B2.Text == mark) && (B3.Text == mark) && (B1.Text == ""))
        return B1;
    if ((B1.Text == mark) && (B3.Text == mark) && (B2.Text == ""))
        return B2;

    if ((C1.Text == mark) && (C2.Text == mark) && (C3.Text == ""))
        return C3;
    if ((C2.Text == mark) && (C3.Text == mark) && (C1.Text == ""))
        return C1;
    if ((C1.Text == mark) && (C3.Text == mark) && (C2.Text == ""))
        return C2;

    //VERTICAL TESTS
    if ((A1.Text == mark) && (B1.Text == mark) && (C1.Text == ""))
        return C1;
    if ((B1.Text == mark) && (C1.Text == mark) && (A1.Text == ""))
        return A1;
    if ((A1.Text == mark) && (C1.Text == mark) && (B1.Text == ""))
        return B1;

    if ((A2.Text == mark) && (B2.Text == mark) && (C2.Text == ""))
        return C2;
    if ((B2.Text == mark) && (C2.Text == mark) && (A2.Text == ""))
        return A2;
    if ((A2.Text == mark) && (C2.Text == mark) && (B2.Text == ""))
        return B2;

    if ((A3.Text == mark) && (B3.Text == mark) && (C3.Text == ""))
        return C3;
    if ((B3.Text == mark) && (C3.Text == mark) && (A3.Text == ""))
        return A3;
    if ((A3.Text == mark) && (C3.Text == mark) && (B3.Text == ""))
        return B3;

    //DIAGONAL TESTS
    if ((A1.Text == mark) && (B2.Text == mark) && (C3.Text == ""))
        return C3;
    if ((B2.Text == mark) && (C3.Text == mark) && (A1.Text == ""))
        return A1;
    if ((A1.Text == mark) && (C3.Text == mark) && (B2.Text == ""))
        return B2;

    if ((A3.Text == mark) && (B2.Text == mark) && (C1.Text == ""))
        return C1;
    if ((B2.Text == mark) && (C1.Text == mark) && (A3.Text == ""))
        return A3;
    if ((A3.Text == mark) && (C1.Text == mark) && (B2.Text == ""))
        return B2;

    return null;
}

So how can I change the programm, that the computer is answering now?


Solution

  • Give this a try:

    private void button_click(object sender, MouseEventArgs e)
    {
        var oldTurn = turn;
    
        Button b = (Button)sender;
        if (turn)
            b.Text = "X";
        else
            b.Text = "O";
    
        turn = !turn;
    
        //try to remove this line since it will block PerformClick in computer_make_move()
        //don't know for sure if that is the button that gets "clicked" in Computer
        //b.Enabled = false;
    
        tic_counter++;
        CheckForWinner();
    
        if (oldTurn)
            computer_make_move();
    }
    

    If you need the button to be disabled, you can extract your code into a differnent method and call this instead of PerformClick

    private void button_click(object sender, MouseEventArgs e)
    {
         ExecuteButtonCode(sender);
    }
    
    private void ExecuteButtonCode(object sender)
    {
        var oldTurn = turn;
    
        Button b = (Button)sender;
        if (turn)
            b.Text = "X";
        else
            b.Text = "O";
    
        turn = !turn;
    
        b.Enabled = false;
    
        tic_counter++;
        CheckForWinner();
    
        if (oldTurn)
            computer_make_move();
    }
    

    And in your computer_make_move call this:

    ExecuteButtonCode(move);
    

    instead of

    move.PerformClick();
    

    You will need to block the exectution of your computer_make_move(); if the game is over.

    Change your CheckForWinner method to this - (removed some code, so that it's easier to see where I put code, placed comments where I removed code):

    private bool gameIsOver = false; //boolean to track if the game is over or not
    private void CheckForWinner()
    {
        bool there_is_a_winner = false;
    
        //[RemovedCode] - Evaluation of your buttons...
    
        if (there_is_a_winner)
        {
            gameIsOver = true;
            //[RemovedCode] - winning code...
        }
        else
        {
            if(tic_counter == 9)
            {
                gameIsOver = true;
                //[RemovedCode] - losing code...
            }
        }
    }
    

    And now add the check if the game is over, to your method:

    private void ExecuteButtonCode(object sender)
    {
        if (gameIsOver)
            return; //return (exit) the method if the game is over and just do nothing in that case
    
        var oldTurn = turn;
    
        Button b = (Button)sender;
        if (b == null)
            return; //return (exit) the method if b is null to prevent the NullReferenceException from occuring
    
        if (turn)
            b.Text = "X";
        else
            b.Text = "O";
    
        turn = !turn;
    
        b.Enabled = false;
    
        tic_counter++;
        CheckForWinner();
    
        if (gameIsOver)
            return; //return (exit) the method if the game is over, to prevent computer from making a move
    
        if (oldTurn)
            computer_make_move();
    }