在计算机上打TAC TAC脚趾

时间:2018-10-10 11:57:08

标签: c# tic-tac-toe

所以我编写了一个Tic Tac Toe游戏。目前,这是一个人与人的游戏。现在,我希望计算机是一个人,因此“人与计算机”我已经对计算机进行了编程,使其可以回答游戏,但它仍然是人与人之间的游戏。如何更改程序,以便计算机可以应答?

井字游戏的代码是这样:

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();
        }
    }
}

计算机是这样的:

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;
}

那么我该如何更改计算机正在应答的程序?

3 个答案:

答案 0 :(得分:0)

如果您希望通过单击来保持事件,最简单的方法是将按钮单击事件更改为如下所示: 私有void button_click(对象发送者,MouseEventArgs e)     {

    Button b = (Button)sender;
    if (turn)
        b.Text = "X";
    else
        b.Text = "O";

    b.Enabled = false;
    tic_counter++;
    turn = !turn;
    CheckForWinner();

    if (!turn)
        computer_make_move();
}

现在,每当玩家转身时,它将直接进行计算机移动。将computer_make_move保持在else路径中意味着您必须单击一个按钮来执行计算机代码,然后再单击一次。

答案 1 :(得分:0)

尝试一下:

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();
}

如果您需要禁用该按钮,则可以将代码提取到其他方法中,然后调用该方法代替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();
}

然后在您的computer_make_move中调用:

ExecuteButtonCode(move);

代替

move.PerformClick();

如果游戏结束,您将需要阻止computer_make_move();的执行。

将您的CheckForWinner方法更改为-(删除了一些代码,这样可以更轻松地看到我在哪里放置代码,在我删除了代码的位置放置注释):

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...
        }
    }
}

现在将检查游戏是否结束的方法添加到您的方法中:

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();
}

答案 2 :(得分:0)

可以大大帮助编程的一种技巧是:不要在事件函数中放入大量代码。

这是您的一般代码结构:

mouseClickEvent()
{
    // lines of code to handle stuff
    // lines of code to check for a winner
    // lines of code to have the computer decide a move
    // calling mouseClickEvent() for the computer.
}

...,您会遇到问题,因为从两个不同的来源调用mouseClickEvent():用户单击按钮,以及在代码内调用。

嗯,有一个相对简单的解决方法:

void mouseClickEvent(...)
{
    HandlePlayerSelectingSquare(playerNum: 1, source: sender);
}
void HandlePlayerSelectingSquare(int playerNum, Object source)
{
    // misc stuff
    // if playerNum == 0, return - we don't need to continue on
    // figure out a computer move
    // call HandlePlayerSelectingSquare(2, computersButtonChoice)
}

...有意义吗?现在,您有了一种简单的方法来判断播放器还是计算机正在做出选择:通过将playerNum传递给函数(该事件永远不会被计算机调用)。