我对C#和WPF都很陌生,所以请耐心等待。我正在做C#/ WPF Tic-Tac-Toe游戏。在游戏开始并做了一些动作后,我不断收到以下错误,我不明白为什么:
"类型未处理的例外' System.StackOverflow异常'"
就计算机而言,并不一定是任何策略。所以,我想要的代码就是随机选择谁先行(计算机或人),当计算机转动时,计算机应该只选择一个随机启用的按钮,并分配一个" X"或者" O"它。任何帮助将不胜感激。
另外,如果有更简单或更短的编码方式,请务必告诉我!正如我所说,我对这一切都很陌生。
注意:我还没有提出一个函数/方法来确定获胜者是谁。我不需要帮助。
*****编辑:按照建议,我宣布并实例化了#34; rnd"一次进入" MainWindow"上课和离开" rnd.Next"在" randomSquare"方法。之前,它在游戏中的许多不同点上抛出了错误。现在,它只会在人类第一次出现时抛出错误并且是第9次移动。对于如何解决这个问题,有任何的建议吗?以下是我编辑的代码。*****
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Operation6
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
bool player1 = true;
int playerNumber;
Random rnd1 = new Random();
Random rnd2 = new Random(); /// Edit: Instantiated only once.
public MainWindow()
{
InitializeComponent();
playerNumber = rnd1.Next(1, 3);
if (playerNumber == 1)
computer();
}
private int randomSquare()
{
int number;
number = rnd2.Next(1, 10);
return number;
}
private void computer()
{
int squareNumber = randomSquare();
if (squareNumber == 1 && square1.IsEnabled == true)
{
if (player1)
square1.Content = "X";
else
square1.Content = "O";
square1.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 1 && square1.IsEnabled == false)
computer();
else if (squareNumber == 2 && square2.IsEnabled == true)
{
if (player1)
square2.Content = "X";
else
square2.Content = "O";
square2.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 2 && square2.IsEnabled == false)
computer();
else if (squareNumber == 3 && square3.IsEnabled == true)
{
if (player1)
square3.Content = "X";
else
square3.Content = "O";
square3.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 3 && square3.IsEnabled == false)
computer();
else if (squareNumber == 4 && square4.IsEnabled == true)
{
if (player1)
square4.Content = "X";
else
square4.Content = "O";
square4.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 4 && square4.IsEnabled == false)
computer();
else if (squareNumber == 5 && square5.IsEnabled == true)
{
if (player1)
square5.Content = "X";
else
square5.Content = "O";
square5.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 5 && square5.IsEnabled == false)
computer();
else if (squareNumber == 6 && square6.IsEnabled == true)
{
if (player1)
square6.Content = "X";
else
square6.Content = "O";
square6.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 6 && square6.IsEnabled == false)
computer();
else if (squareNumber == 7 && square7.IsEnabled == true)
{
if (player1)
square7.Content = "X";
else
square7.Content = "O";
square7.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 7 && square7.IsEnabled == false)
computer();
else if (squareNumber == 8 && square8.IsEnabled == true)
{
if (player1)
square8.Content = "X";
else
square8.Content = "O";
square8.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 8 && square8.IsEnabled == false)
computer();
else if (squareNumber == 9 && square9.IsEnabled == true)
{
if (player1)
square9.Content = "X";
else
square9.Content = "O";
square9.IsEnabled = false;
player1 = !player1;
}
else if (squareNumber == 9 && square9.IsEnabled == false)
computer();
else
draw();
}
private void draw()
{
textBlock1.Text = "It's a tie!";
}
private void squareClick(object sender, RoutedEventArgs e)
{
Button square = (Button)sender;
if (player1)
square.Content= "X";
else
square.Content = "O";
square.IsEnabled = false;
player1 = !player1;
computer();
}
}
}
答案 0 :(得分:-1)
在大多数情况下,如果在没有适当的halting子句的情况下调用递归方法,则会发生StackOverflowException。在您的情况下,罪魁祸首可能是非常凌乱computer()
方法,该方法在几个位置调用自身,因此很难逻辑推理可能导致的流量无限递归。但在扫描之后,我说核心原因在于你的randomSquare
方法。
使用Random
类的正确方法是初始化一次,然后在同一个实例上调用Next()
。这样你知道它是从一个随机种子初始化的,然后所有后续调用都是基于那个种子。默认情况下,随机种子基于当前系统时钟。当您为每个呼叫初始化Random
时,您可以根据每个呼叫的系统时钟有效地创建一个新的随机种子,并且因为它是一个非常紧凑的循环,所有这些Randoms将返回相同数量连续多次。这意味着你的computer
方法将连续获得几十/百/千个(每个都递归调用computer
),直到系统时钟发生了足够的变化。它们可能会连续几十/百/三万。
这会很快耗尽堆栈,导致堆栈溢出。
尝试将rnd
更改为成员字段,在构造函数中将其实例化一次,然后只需在rnd.Next
方法中调用randomSquare
。