本文旨在探讨在java中向二维字符数组(如用于实现单词搜索板)添加字符串时,如何有效进行边界检查,以避免索引越界错误和字符截断。我们将分析常见的错误模式,并提供一个健壮的解决方案,包括预先检查单词是否能完整放置的逻辑,以及优化字符逐个放置的实现,确保数据操作的安全性与准确性。
在开发涉及二维字符数组(例如,一个简单的单词搜索游戏板)的应用时,一个常见需求是将一个字符串(单词)放置到数组的特定位置。然而,如果未进行充分的边界检查,很容易导致以下问题:
原始代码示例中,尝试在 WordSearch 类中通过 addWord 方法向 char board[][] 添加单词时,就遇到了上述问题。其核心问题在于边界检查逻辑不完善以及循环内部索引更新的副作用。
public class WordSearch {
private static int rows = 5;
private static int columns = 10;
char board[][] = new char [rows][columns];
public WordSearch(){
for(int row=0; row= board[x].length){
continue; // 继续下一字符,但当前字符已丢失
} else if(board[x][y] == '*'){ // 这里的 if/else 结构是冗余的
board[x][y++] = word.charAt(i);
} else {
board[x][y++] = word.charAt(i);
}
}
break;
case 1: // 垂直放置
for(int i=0; i= board[y].length){ // 注意这里使用了 board[y].length,应该是 board.length
continue;
} else if(b
oard[x][y] == '*'){
board[x++][y] = word.charAt(i);
} else {
board[x++][y] = word.charAt(i);
}
}
break;
default:
System.out.println("Give 0 to add word horizontally, or 1 vertically");
}
}
} 上述代码存在几个关键问题:
为了解决上述问题,我们应采取两步策略:
引入一个辅助方法 canPlaceWord,用于在实际修改数组前,判断一个单词是否能在指定方向和起始坐标下完全容纳。
public boolean canPlaceWord(String word, int position, int startX, int startY) {
if (word == null || word.isEmpty()) {
return true; // 空单词总是可以放置的,或者根据业务需求返回 false
}
// 检查起始坐标是否越界
if (startX < 0 || startX >= rows || startY < 0 || startY >= columns) {
return false;
}
int wordLength = word.length();
if (position == 0) { // 水平放置
// 检查单词的结束位置是否在数组边界内
if (startY + wordLength > columns) {
return false;
}
// 可选:检查路径上是否有其他非'*'字符,如果要求不覆盖
for (int i = 0; i < wordLength; i++) {
if (board[startX][startY + i] != '*') {
// 如果需要覆盖现有字符,则移除此检查
// 如果不允许覆盖,则返回 false
// return false;
}
}
} else if (position == 1) { // 垂直放置
// 检查单词的结束位置是否在数组边界内
if (startX + wordLength > rows) {
return false;
}
// 可选:检查路径上是否有其他非'*'字符
for (int i = 0; i < wordLength; i++) {
if (board[startX + i][startY] != '*') {
// return false;
}
}
} else {
return false; // 无效的放置方向
}
return true;
}在 addWord 方法中调用 canPlaceWord 进行预检查,如果通过,则执行精确的字符放置。
public class WordSearch {
private static int rows = 5;
private static int columns = 10;
char board[][] = new char [rows][columns];
public WordSearch(){
for(int row=0; row= rows || startY < 0 || startY >= columns) {
return false;
}
int wordLength = word.length();
if (position == 0) { // 水平放置
// 检查单词结束位置是否超出列边界
if (startY + wordLength > columns) {
return false;
}
// (可选) 如果不允许覆盖非 '*' 字符,可以在这里添加检查
// for (int i = 0; i < wordLength; i++) {
// if (board[startX][startY + i] != '*') {
// return false;
// }
// }
} else if (position == 1) { // 垂直放置
// 检查单词结束位置是否超出行边界
if (startX + wordLength > rows) {
return false;
}
// (可选) 如果不允许覆盖非 '*' 字符,可以在这里添加检查
// for (int i = 0; i < wordLength; i++) {
// if (board[startX + i][startY] != '*') {
// return false;
// }
// }
} else {
return false; // 无效的放置方向
}
return true;
}
/**
* 将单词添加到二维数组中。
* @param word 待添加的单词
* @param position 放置方向 (0: 水平, 1: 垂直)
* @param startX 起始行索引
* @param startY 起始列索引
* @return 如果成功添加则返回 true,否则返回 false
*/
public boolean addWord(String word, int position, int startX, int startY) {
// 首先进行预检查
if (!canPlaceWord(word, position, startX, startY)) {
System.out.println("Error: Word '" + word + "' cannot be placed at (" + startX + "," + startY + ") with position " + position + " due to boundary or existing characters.");
return false;
}
// 预检查通过,开始放置单词
switch(position){
case 0: // 水平放置
for(int i = 0; i < word.length(); i++){
board[startX][startY + i] = word.charAt(i);
}
break;
case 1: // 垂直放置
for(int i = 0; i < word.length(); i++){
board[startX + i][startY] = word.charAt(i);
}
break;
default:
// canPlaceWord 已经处理了无效 position,这里理论上不会执行
System.out.println("Invalid position. Use 0 for horizontal or 1 for vertical.");
return false;
}
return true;
}
public static void main(String[] args) {
WordSearch ws = new WordSearch();
ws.printBoard();
// 尝试放置一个能放下的单词
ws.addWord("schedule", 0, 2, 0); // 从 (2,0) 水平放置 "schedule"
ws.printBoard();
// 尝试放置一个部分越界的单词 (水平)
ws.addWord("ridiculous", 0, 3, 5); // 从 (3,5) 水平放置 "ridiculous" (长度10,列宽10,5+10=15 > 10)
ws.printBoard(); // 应该显示错误信息,板子不变
// 尝试放置一个完全越界的单词 (垂直)
ws.addWord("longword", 1, 3, 2); // 从 (3,2) 垂直放置 "longword" (长度8,行高5,3+8=11 > 5)
ws.printBoard(); // 应该显示错误信息,板子不变
// 尝试放置一个能放下的单词 (垂直)
ws.addWord("relax", 1, 0, 5); // 从 (0,5) 垂直放置 "relax"
ws.printBoard();
// 再次尝试放置一个能放下的单词 (水平)
ws.addWord("test", 0, 4, 6); // 从 (4,6) 水平放置 "test" (长度4,列宽10,6+4=10 <= 10)
ws.printBoard();
}
} 在上述优化后的代码中:
在Java中向二维数组添加字符串时,进行严格而全面的边界检查是确保程序健壮性的关键。通过将“能否放置”的判断逻辑与“实际放置”的执行逻辑分离,并采用预先检查整个单词长度的策略,可以有效地避免 ArrayIndexOutOfBoundsException 和数据截断问题。这种结构不仅提高了代码的可靠性,也使其更易于理解和扩展,是处理类似数组操作时的推荐做法。