所以我编写了一个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;
}
那么我该如何更改计算机正在应答的程序?
答案 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传递给函数(该事件永远不会被计算机调用)。