Всем доброго времени суток, уважаемые JavaRush'евцы.
Вашему вниманию представляется очередная версия кода, который удовлетворяет всем требованиям и (вроде как даже) прошёл все проверки, что я для него придумал.
Но валидатор keep saying "Это фиаско, братан!".
Собственно, хотелось бы разобраться: дело в ошибке в коде / каком-то непокрытом сценарии.
или же это всего лишь очередная прихоть валидатора (коих участники сообщества, дошедшие до 20-го уровня, уже насмотрелись вдоволь) ?
p.s.
На краткость здесь ни разу не претенедовал. Без комментов решение составило 150 строк.
Некоторые моменты было логично вынести в отдельные классы (ну или функции), чтобы сделать код более компактным, но этого я не стал делать намеренно, т.к. во время выполнения предыдущих задач курса сталкивался с ситуациями, когда валидатор такие решения просто не принимал.
package com.javarush.task.task20.task2027;
import java.util.ArrayList;
import java.util.List;
/*
Кроссворд
*/
public class Solution {
public static void main(String[] args) {
int[][] crossword = new int[][]{
{'f', 'd', 'e', 'r', 'l', 'k'},
{'u', 's', 'a', 'm', 'e', 'o'},
{'l', 'n', 'g', 'r', 'o', 'v'},
{'m', 'l', 'p', 'r', 'r', 'h'},
{'p', 'o', 'e', 'e', 'j', 'j'}
};
detectAllWords(crossword, "home", "same");
/*
Ожидаемый результат
home - (5, 3) - (2, 0)
same - (1, 1) - (4, 1)
*/
}
public static List<Word> detectAllWords(int[][] crossword, String... words) {
int curElemRow = 0, curElemField = 0, startElemRow = 0, startElemField = 0, endElemRow = 0, endElemField = 0;
int crosswordWidth = crossword[0].length, crosswordLength = crossword.length;
int rowCorrector = 0, fieldCorrector = 0;
StringBuilder direction = new StringBuilder();
ArrayList<String> wrongPath = new ArrayList<String>();
List<Word> detectedWords = new ArrayList<Word>();
//Перебираем все слова
for(String s: words){
//Перебираем слово по буквам
//Находим все положения для первой буква в слове и начинаем работать с ними
for (int row = 0; row < crosswordLength; row++) {
for (int field = 0; field < crosswordWidth; field++) {
rowCorrector = 0;
fieldCorrector = 0;
wrongPath.clear();
if((char)crossword[row][field] == s.charAt(0) ) {
startElemRow = curElemRow = row;;
startElemField = curElemField = field;;
direction.setLength(0);
for (int i = 1; i < s.length(); i++) {
//find a direction
if (direction.length() == 0){
if ( !wrongPath.contains("N") && (curElemRow - 1 >= 0) && (char)crossword[curElemRow - 1][curElemField] == s.charAt(i) ) {
direction.append("N");
curElemRow = curElemRow - 1;
rowCorrector--;
} else
if ( !wrongPath.contains("NW") && ((curElemRow - 1 >= 0) && (curElemField - 1 >= 0) ) && ((char) crossword[curElemRow - 1][curElemField - 1] == s.charAt(i)) ) {
direction.append("NW");
curElemRow = curElemRow - 1; curElemField = curElemField - 1;
rowCorrector--; fieldCorrector--;
} else
if ( !wrongPath.contains("W") && ((curElemField - 1 >= 0) ) && ((char) crossword[curElemRow][curElemField - 1] == s.charAt(i)) ) {
direction.append("W");
curElemField = curElemField - 1;
fieldCorrector--;
} else
if ( !wrongPath.contains("SW") && ((curElemField - 1 >= 0) && (curElemRow + 1 < crosswordLength ) ) && ((char) crossword[curElemRow + 1][curElemField - 1] == s.charAt(i)) ) {
direction.append("SW");
curElemRow = curElemRow + 1; curElemField = curElemField - 1;
rowCorrector++; fieldCorrector--;
} else
if ( !wrongPath.contains("S") && ((curElemRow + 1 < crosswordLength ) ) && ((char) crossword[curElemRow + 1][curElemField] == s.charAt(i)) ) {
direction.append("S");
curElemRow = curElemRow + 1;
rowCorrector++;
} else
if ( !wrongPath.contains("SE") && ((curElemRow + 1 < crosswordLength ) && (curElemField +1 < crosswordWidth)) && ((char) crossword[curElemRow + 1][curElemField + 1] == s.charAt(i)) ) {
direction.append("SE");
curElemRow = curElemRow + 1; curElemField = curElemField + 1;
rowCorrector++; fieldCorrector++;
} else
if ( !wrongPath.contains("E") && ((curElemField +1 < crosswordWidth)) && ((char) crossword[curElemRow][curElemField + 1] == s.charAt(i)) ) {
direction.append("E");
curElemField = curElemField + 1;
fieldCorrector++;
} else
if ( !wrongPath.contains("NE") && ( (curElemRow - 1 >= 0) && (curElemField +1 < crosswordWidth)) && ((char) crossword[curElemRow - 1][curElemField + 1] == s.charAt(i)) ) {
direction.append("NE");
curElemField = curElemField + 1; curElemRow = curElemRow - 1;
rowCorrector--; fieldCorrector++;
}
}
//If direction is already known - going to this branch
else if (direction.length() != 0) {
// Check if next step is behind the border of 'crossword' matrix
// if so - then mark current direction as wrong, return back to the position of first letter
// and continue checking other direction
if (curElemRow + rowCorrector == crosswordLength || curElemField + fieldCorrector == crosswordWidth ||
curElemRow + rowCorrector < 0 || curElemField + fieldCorrector < 0)
{ wrongPath.add(direction.toString());
direction.setLength(0);
curElemRow = startElemRow; curElemField = startElemField;
rowCorrector = 0; fieldCorrector = 0;
i = 0;
continue;}
if((char)crossword[curElemRow + rowCorrector][curElemField + fieldCorrector] == s.charAt(i)){
curElemRow = curElemRow + rowCorrector;
curElemField = curElemField + fieldCorrector;
if (i == s.length() - 1){
endElemRow = curElemRow;
endElemField = curElemField;
Word w = new Word(s);
w.setStartPoint(startElemField, startElemRow);
w.setEndPoint(endElemField, endElemRow);
detectedWords.add(w);
}
// this check is added in order to cover the cases when in 'crossword' matrix the are
// 'fake direction' i.e. chain of the letters that equals to the part of entered word
// and at the same time on the matrix there is full word and start from the same point.
// Example (on the original crossword matrix) : nlo.
// If start from 'n' and move to the left, then 'l' will be found but after that - dead end.
// but if move down - whole word will be found.
} else {
wrongPath.add(direction.toString());
direction.setLength(0);
curElemRow = startElemRow; curElemField = startElemField;
rowCorrector = 0; fieldCorrector = 0;
i = 0;
continue;
}
}
}
}
}
}
}
// This part was added to cover the cases when nothing was found.
// (A few people reportrted in the comments under the task that this helped them )
// Tried to pass validation with that check as well as without it.
if (detectedWords.size() == 0) {
Word w = new Word(null);
w.setStartPoint(0,0);
w.setEndPoint(0,0);
detectedWords.add(w);
}
return detectedWords;
}
public static class Word {
private String text;
private int startX;
private int startY;
private int endX;
private int endY;
public Word(String text) {
this.text = text;
}
public void setStartPoint(int i, int j) {
startX = i;
startY = j;
}
public void setEndPoint(int i, int j) {
endX = i;
endY = j;
}
@Override
public String toString() {
return String.format("%s - (%d, %d) - (%d, %d)", text, startX, startY, endX, endY);
}
}
}