输入坐标触发IndexOutOfRangeException?已加边界检查仍报错
C#战舰游戏输入坐标触发IndexOutOfRangeException异常分析
问题代码
using System; using System.Linq; namespace Schiffeversenken { class Program { static void Main(string[] args) { // Größe der Karte const int width = 10; const int height = 10; // Die Karte als 2d Array von ints initialisieren int[,] grid = new int[width, height]; // Schiffe platzieren (fünf Schiffe der Größe 1x1) for (int i = 0; i < 5; i++) { int x = new Random().Next(0, width); int y = new Random().Next(0, height); grid[x, y] = 1; } // Spiel loop while (true) { // Karte anzeigen Console.WriteLine(" 0 1 2 3 4 5 6 7 8 9"); Console.WriteLine(" -------------------"); for (int yCoord = 0; yCoord < height; yCoord++) { Console.Write($" {yCoord} |"); for (int xCoord = 0; xCoord < width; xCoord++) { if (grid[xCoord, yCoord] == 0) { Console.Write(" "); } else if (grid[xCoord, yCoord] == 1) { Console.Write("X"); } else if (grid[xCoord, yCoord] == 2) { Console.Write("O"); } Console.Write("|"); } Console.WriteLine(); } Console.WriteLine(" -------------------"); Console.WriteLine(" 0 1 2 3 4 5 6 7 8 9"); Console.WriteLine(" (X-Koordinate)"); // Schiessen Console.WriteLine("Gib die Koordinaten für deinen Schuss ein (x y):"); int[] input = Console.ReadLine() .Split(' ') .Select(s => int.Parse(s)) .ToArray(); int x = input[0]; int y = input[1]; // Prüfen, ob die Indizes innerhalb der Grenzen des Arrays liegen if (x >= 0 && x < width && y >= 0 && y < height) { // Prüfen, ob ein Schiff getroffen wurde if (grid[x, y] == 1) { Console.WriteLine("Treffer!"); grid[x, y] = 2; } else { Console.WriteLine("Daneben."); } } else { Console.WriteLine("Die Koordinaten liegen außerhalb des Spielfelds."); } } } } }
报错信息
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Schiffeversenken.Program.Main(String[] args) in C:\Users\timoa\RiderProjects\Battleships\Battleships\Program.cs:line 64
异常原因
你添加的边界检查是针对grid数组的坐标范围,但异常并非来自grid数组访问,而是来自input数组的索引访问。
当用户输入不符合预期格式时(比如只输入一个数字、输入非数字内容、输入空行、输入多个空格分隔的多余内容),会出现以下情况:
Console.ReadLine().Split(' ')得到的数组长度不等于2,比如输入空行时数组可能为空,输入一个数字时数组长度为1- 此时直接访问
input[0]或input[1]就会触发IndexOutOfRangeException - 另外,
Select(s => int.Parse(s))还会在输入非数字时触发FormatException,这也是潜在问题
解决方法
需要在访问input数组前,先验证输入的格式有效性,包括:
- 检查输入是否为空
- 检查分割后的数组是否正好有两个元素
- 检查两个元素能否成功转换为整数
- 最后再进行坐标边界检查
修改后的射击逻辑代码如下:
// Schiessen Console.WriteLine("Gib die Koordinaten für deinen Schuss ein (x y):"); string inputLine = Console.ReadLine(); // 检查输入是否为空 if (string.IsNullOrWhiteSpace(inputLine)) { Console.WriteLine("Bitte gib gültige Koordinaten ein."); continue; } // 分割输入,移除空项(处理多个空格的情况) string[] inputParts = inputLine.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); // 检查是否正好两个坐标 if (inputParts.Length != 2) { Console.WriteLine("Bitte gib genau zwei Koordinaten getrennt durch Leerzeichen ein."); continue; } // 尝试转换为整数,失败则提示 if (!int.TryParse(inputParts[0], out int x) || !int.TryParse(inputParts[1], out int y)) { Console.WriteLine("Bitte gib nur ganze Zahlen für die Koordinaten ein."); continue; } // Prüfen, ob die Indizes innerhalb der Grenzen des Arrays liegen if (x >= 0 && x < width && y >= 0 && y < height) { // Prüfen, ob ein Schiff getroffen wurde if (grid[x, y] == 1) { Console.WriteLine("Treffer!"); grid[x, y] = 2; } else { Console.WriteLine("Daneben."); } } else { Console.WriteLine("Die Koordinaten liegen außerhalb des Spielfelds."); }
额外优化点
你的战舰放置逻辑存在重复坐标的可能(多次生成相同位置导致战舰数量不足5艘),且每次循环创建Random实例会因为系统时钟精度问题导致重复随机数,建议修改为:
// Schiffe platzieren (fünf Schiffe der Größe 1x1) Random random = new Random(); for (int i = 0; i < 5; i++) { int x, y; // 循环直到找到未被占用的位置 do { x = random.Next(0, width); y = random.Next(0, height); } while (grid[x, y] == 1); grid[x, y] = 1; }
内容的提问来源于stack exchange,提问作者timosaiya
相关产品推荐
相关产品推荐

