我已经创建了一个井字游戏程序,它允许玩家通过选择坐标在二维数组中选择移动,然后计算机进行移动。
程序可以运行,但计算机的移动是顺序的而不是随机的,它总是选择数组中下一个可用的空间。现在游戏已经可以运行,我希望将程序改进为三个难度级别:
简单 = 计算机随机生成移动中级 = 计算机随机生成移动,并检查阻止玩家和完成线困难 = 每次通过递归选择最佳移动
我如何让计算机在我的数组中随机选择一组坐标?
(我当前的基本计算机移动循环)
static void Computermove(char[,] gamegrid, char fin) { Console.WriteLine("\nComputer's turn"); Console.ReadKey(); int x = 0; int y = 0; for (x = 0; x < 2; x++) { for (y = 0; y < 2; y++) if (gamegrid[x, y] == ' ') break; if (gamegrid[x, y] == ' ') break; } if (x * y == 9) { fin = 'X'; } else gamegrid[x, y] = 'O'; } // End Computermove
回答:
创建一个新的 Random
类的实例,并使用 Next()
方法来生成代表坐标的两个随机数。
这里是代码:
var r = new Random();var randomX = r.Next(3);var randomY = r.Next(3);
更新:
方法可能看起来像这样:
static void Computermove(char[,] gamegrid, char fin){ if (!ContainsEmptyCells(gamegrid)) { // 表格已满;可能没有人赢 return; } bool goodRandomCoordinateFound = false; int row = 0, column = 0; var random = new Random(); while (!goodRandomCoordinateFound) { row = random.Next(3); column = random.Next(3); if(gamegrid[row, column] == ' ') goodRandomCoordinateFound = true; } gamegrid[row, column] = 'O';}
我发现了导致 StackOverflowException
的问题。这是一个非常微妙的问题,但结论是,在重新生成随机坐标时,应该使用相同的 Random
实例,而不是创建一个新的实例。
这是因为 Random
实际上并不生成真正的随机数。当创建一个 new Random()
实例时,它会使用基于当前时间的种子值进行初始化。
如果你使用相同的种子值创建多个 Random
实例,它们将生成相同的随机数流。
在我们的例子中,如果需要生成新的随机坐标,会创建一个新的 Random 实例而不指定种子,因此种子使用的是当前时间。由于随机实例创建得非常快,种子值相同,因此随机值也相同,导致无限递归。
我已经重写了方法以重用 random
实例,这使得后续对 Next(3)
的调用会产生与我们当前拥有的不同的值。