Всем доброго времени суток, уважаемые 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);
        }
    }
}