C#二维数组地图收币程序报IndexOutOfRangeException错误求助
修复C#地图金币统计代码的数组越界问题
需求说明
编写C#代码统计玩家在二维数组地图中收集的金币数量,程序需按以下控制台输入格式执行:
Line 1: Size of the map Line 2: N = Number of coins Line 3 to 3 + N: Coin coordinates Line 4 + N: Player's origin position Line 5 + N: Number of moves Line 6 + N: Moves (r for right, l for left, s for stay...)
现有代码
static void Main(string[] args) { /* Get data from input file */ var data = new List<String>(); string line; while ((line = Console.ReadLine()) != null) { data.Add(line); } // ADD YOUR CODE HER // map and coins initialisation -------------------------------------------- int mapSize = Convert.ToInt32(data[0]); int[,] map = new int[mapSize,mapSize]; string tmpCoinX = ""; string tmpCoinY = ""; int coinX = 0; int coinY = 0; int coinAmnt = Convert.ToInt32(data[1]); int coinsCollected = 0; bool passed = false; for (int coinline = 2; coinline < 2+coinAmnt; coinline++) { foreach (char character in data[coinline]) { if (character == ',') { passed = true; } else { if (passed == true) { tmpCoinY += character.ToString(); } else { tmpCoinX += character.ToString(); } } } passed = false; coinX = Convert.ToInt32(tmpCoinX); coinY = Convert.ToInt32(tmpCoinY); map[coinY, coinX] = 1; } // player position initialisation ----------------------------------------- string Sx = ""; string Sy = ""; passed = false; foreach(char i in data[3+coinAmnt-1]) { if (i == ',') { passed = true; } else { if (passed == true) { Sy = Sy + i.ToString(); } else { Sx = Sx + i.ToString(); } } } int x = Convert.ToInt32(Sx); int y = Convert.ToInt32(Sy); // imposible cases prevention -------------------------------------------- bool imp = false; // reads the data list and acts accordingly foreach(string i in data) { if (i == "u") { y += 1; } if (i == "l") { x -= 1; } if (i == "r") { x += 1; } if (i == "d") { y -= 1; } if (x >= mapSize || y >= mapSize || x < 0 || y < 0) { imp = true; break; } if (map[y, x] == 1) { coinsCollected += 1; map[y, x] = 0; } } if (imp == true) { Console.WriteLine("out"); } else { Console.Write(coinsCollected); } }
测试用例
4 2 2,1 0,3 0,0 3 u l d
错误信息
An error occurred: Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array. at SelectionCandidat.Program.Main (System.String[] args) [0x000f2] in <cd8ee2cfc068460888190546c241d3d1>:0 [ERROR] FATAL UNHANDLED EXCEPTION: System.IndexOutOfRangeException: Index was outside the bounds of the array. at SelectionCandidat.Program.Main (System.String[] args) [0x000f2] in <cd8ee2cfc068460888190546c241d3d1>:0
修复方案
1. 修复金币坐标临时变量未重置问题
处理每一行金币坐标时,tmpCoinX和tmpCoinY未清空,导致后续坐标字符串累加,转换后数值超出地图范围触发数组越界。修改金币循环部分:
for (int coinline = 2; coinline < 2+coinAmnt; coinline++) { tmpCoinX = ""; // 每次循环重置X坐标字符串 tmpCoinY = ""; // 每次循环重置Y坐标字符串 foreach (char character in data[coinline]) { if (character == ',') { passed = true; } else { if (passed == true) { tmpCoinY += character.ToString(); } else { tmpCoinX += character.ToString(); } } } passed = false; coinX = Convert.ToInt32(tmpCoinX); coinY = Convert.ToInt32(tmpCoinY); map[coinY, coinX] = 1; }
2. 修复移动指令遍历范围错误
原代码遍历所有输入行,将非移动指令(如地图尺寸、金币数量)当作移动处理,逻辑混乱。修改为仅遍历移动指令部分:
// 移除原foreach(data)逻辑,替换为以下代码 bool imp = false; int moveCount = Convert.ToInt32(data[2 + coinAmnt + 1]); int moveStartIndex = 2 + coinAmnt + 2; for (int i = moveStartIndex; i < moveStartIndex + moveCount; i++) { string move = data[i]; if (move == "u") { y += 1; } else if (move == "l") { x -= 1; } else if (move == "r") { x += 1; } else if (move == "d") { y -= 1; } else if (move == "s") { // 停留指令,不做位置变更 } // 移动后立即检查是否越界 if (x >= mapSize || y >= mapSize || x < 0 || y < 0) { imp = true; break; } // 检查是否收集到金币 if (map[y, x] == 1) { coinsCollected += 1; map[y, x] = 0; } }
3. 新增初始位置越界检查
如果玩家初始位置本身在地图外,直接输出"out"并退出:
int x = Convert.ToInt32(Sx); int y = Convert.ToInt32(Sy); // 新增初始位置检查 if (x >= mapSize || y >= mapSize || x < 0 || y < 0) { Console.WriteLine("out"); return; }
4. 优化坐标分割逻辑(可选)
手动遍历字符分割坐标容易出错,用Split方法简化:
// 处理金币坐标替换为: string[] coinCoords = data[coinline].Split(','); coinX = int.Parse(coinCoords[0]); coinY = int.Parse(coinCoords[1]); // 处理玩家初始位置替换为: string[] playerCoords = data[2 + coinAmnt].Split(','); int x = int.Parse(playerCoords[0]); int y = int.Parse(playerCoords[1]);
修复后运行结果
针对提供的测试用例,玩家执行u后位置为(0,1),执行l后x变为-1,触发越界,程序输出out,符合需求。
内容的提问来源于stack exchange,提问作者notPatern
相关产品推荐
相关产品推荐

