Help solve the problem with threads

I am learning to program in Java, there is a problem with the problem / * Crossword

  1. Given a two-dimensional array that contains the letters of the English alphabet in lowercase.
  2. The detectAllWords method should find all the words from words in the crossword array.
  3. The element (startX, startY) must match the first letter of the word, and the element(endX, endX) must match the last letter. text is the word itself, located between the start and end elements
  4. All the words are in array.
  5. Words can be arranged horizontally, vertically, and diagonally in both normal and reverse order.
  6. The main method is not involved in testing */

The logic of my solution is as follows: for each step of freedom, I create a task to be executed by a thread. Each individual thread deals only with its own degree of freedom. Next, I just collect the result of the threads. BUT in reality, there is an error, a failure of logic with threads, I sit for 2 days and can not determine the location of the error, I guess that the error occurs when threads share access to the resource.

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', 'e', 'm', 'o', 'h'},
            {'p', 'o', 'e', 'e', 'j', 'j'}
    };
    List<Word> result = detectAllWords(crossword, "home");
    for (Word word : result)
        System.out.println(word);

    /*

Expected result home - (5, 3) - (2, 0) same - (1, 1) - (4, 1) */ }

public static List<Word> detectAllWords(int[][] crossword, String... words) {

    Crossword crosswordHelper = new Crossword(crossword, words);

    return crosswordHelper.doCrossword();
}

public static class Crossword
{

    private int[][] crossword;
    private String[] words;

    public Crossword(int[][] crossword, String[] words) {
        this.crossword = crossword;
        this.words = words;
    }

    public class Coordinate
    {
        private char letter;
        private int row;
        private int column;

        public Coordinate(char letter, int row, int column) {
            this.letter = letter;
            this.row = row;
            this.column = column;
        }

        public char getLetter()
        {
            return letter;
        }

        public int getRow()
        {
            return row;
        }

        public int getColumn()
        {
            return column;
        }

        @Override
        public String toString()
        {
            return String.format("char=%c, row=%d, column=%d", letter, row, column);
        }

        public synchronized boolean inHorizontalLeftRange(Coordinate otherCoordinate) {

            return (otherCoordinate.getRow() == row && ((otherCoordinate.getColumn() - 1) == column)) ? true : false;

        }

        public synchronized boolean inHorizontalRightRange(Coordinate otherCoordinate) {

            return (otherCoordinate.getRow() == row && ((otherCoordinate.getColumn() + 1) == column)) ? true : false;

        }

        public synchronized boolean inVerticalUpRange(Coordinate otherCoordinate) {

            return (otherCoordinate.getColumn() == column && ((otherCoordinate.getRow() + 1) == row)) ? true : false;

        }

        public synchronized boolean inVerticalDownRange(Coordinate otherCoordinate) {

            return (otherCoordinate.getColumn() == column && ((otherCoordinate.getRow() - 1) == row)) ? true : false;

        }

        public synchronized boolean inDiagonalUpRightRange(Coordinate otherCoordinate) {

            return  ((row + 1) == otherCoordinate.getRow() && (column + 1) == otherCoordinate.getColumn()) ? true : false;

        }

        public synchronized boolean inDiagonalUpLeftRange(Coordinate otherCoordinate) {

            return ((row + 1) == otherCoordinate.getRow() && (column - 1) == otherCoordinate.getColumn()) ? true : false;

        }

        public synchronized boolean inDiagonalDownRightRange(Coordinate otherCoordinate) {

            return ((row - 1) == otherCoordinate.getRow() && (column + 1) == otherCoordinate.getColumn()) ? true : false;

        }

        public synchronized boolean inDiagonalDownLeftRange(Coordinate otherCoordinate) {

            return ((row - 1) == otherCoordinate.getRow() && (column - 1) == otherCoordinate.getColumn()) ? true : false;

        }

    }

    public class CoordinateFabric
    {
        private String word;

        public CoordinateFabric(String word) {
            this.word = word;
        }

        public List<Coordinate> findHeadLettersCoordinates() {

            List<Coordinate> result = new ArrayList<Coordinate>();

            char[] chars = word.toCharArray();
            char c = chars[0];

            for (int row = 0; row < crossword.length; row++) {
                for (int column = 0; column < crossword[row].length; column++) {
                    char tempChar = (char)crossword[row][column];

                    if (tempChar == c)
                        result.add(new Coordinate(c, row, column));
                }
            }

            return result;

        }

        public List<Coordinate> findAllLettersCoordinates() {

            List<Coordinate> result = new ArrayList<Coordinate>();
            char[] chars = word.toCharArray();

            for (int i = 0; i < chars.length; i++) {
                char c = chars[i];
                for (int row = 0; row < crossword.length; row++) {
                    for (int column = 0; column < crossword[row].length; column++) {
                        char tempChar = (char)crossword[row][column];

                        if (tempChar == c)
                            result.add(new Coordinate(c, row, column));

                    }
                }
            }

            return result;

        }

        public List<Word> startFabric() throws InterruptedException {

            // Думаю проблема к доступу к данному ресурсу но не уверен!
           final List<Word> listOfFoundWords = new ArrayList<>();

            List<String> directions = new ArrayList<>();
            directions.add("inHorizontalLeftRange");
            directions.add("inHorizontalRightRange");
            directions.add("inVerticalUpRange");
            directions.add("inVerticalDownRange");
            directions.add("inDiagonalUpRightRange");
            directions.add("inDiagonalUpLeftRange");
            directions.add("inDiagonalDownRightRange");
            directions.add("inDiagonalDownLeftRange");

            class DirectionThread extends Thread {

                private String methodName;
                private List<Coordinate> allCoordinates;
                private List<Coordinate> headCoordinates;

                public DirectionThread(String methodName, List<Coordinate> headCoordinates, List<Coordinate> allCoordinates) {
                    this.methodName = methodName;
                    this.headCoordinates = headCoordinates;
                    this.allCoordinates = allCoordinates;
                    start();
                }

                @Override
                public void run()
                {
                    for (Coordinate head : headCoordinates) {

                        // BUILDING WORD FROM FIRST LETTER
                        List<Coordinate> container = new ArrayList<>();
                        container.add(head);

                        // THEN WE APPEND ANOTHER WORDS
                        for (Coordinate coordinate : allCoordinates) {
                            Coordinate nextCoordinate = container.get(container.size()-1);
                            try
                            {
                                Method method = Coordinate.class.getMethod(methodName.toString(), Coordinate.class);
                                boolean inRange = (boolean) method.invoke(nextCoordinate, coordinate);
                                if (inRange)
                                    container.add(coordinate);

                            } catch (Exception ex) {
                                ex.printStackTrace();
                                break;
                            }
                        }

                        if (container.size() == word.length())
                        {
                            Word resultWord = new Word(word);
                            Coordinate firstCoordinate = container.get(0);
                            resultWord.setStartPoint(firstCoordinate.getColumn() , firstCoordinate.getRow());

                            Coordinate lastCoordinate = container.get(container.size()-1);
                            resultWord.setEndPoint(lastCoordinate.getColumn(), lastCoordinate.getRow());

                            // Другое поведение программы, если расскоментировать код вывода на консоль,
                            // Не могу понят почему!
                            //System.out.println("one more word " + resultWord);
                            listOfFoundWords.add(resultWord);

                        }

                    }// headCoordinates

                }

            }

            List<Coordinate> headCoordinates = findHeadLettersCoordinates();
            List<Coordinate> allCoordinates = findAllLettersCoordinates();

            // STARTING ALL THREAD AUTOMATICALLY
            List<Thread> crosswordSpiders = new ArrayList<>();
            for (String direct : directions) {
                crosswordSpiders.add(new DirectionThread(direct, headCoordinates, allCoordinates));
            }

            // GATHERING THREAD RESULTS (listOfFoundWords)
            for (Thread thread : crosswordSpiders)
                thread.join();

            return listOfFoundWords;

        }

    }

    public List<Word> findSolutionForWord(String word) {

        CoordinateFabric coordinateFabric = new CoordinateFabric(word);
        List<Word> crosswordFoundWords = null;

        try {
            // STARTING OUR FABRIC
            crosswordFoundWords = coordinateFabric.startFabric();
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }

        // RETURNING ALL FOUND WORDS
        return crosswordFoundWords;
    }

    public List<Word> doCrossword() {

        List<Word> detectedWords = new ArrayList<>();

        for (String textWord : words) {
            List<Word> listOfWords = findSolutionForWord(textWord);
            for (Word word : listOfWords)
                detectedWords.add(word);

        }

        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);
    }
}

}

Author: Deleted, 2014-04-04

1 answers

Yes seems to be the correct answer, you only search for home, the program correctly finds two home:
home - (5, 3) - (2, 3), home - (5, 3) - (2, 0).
"same" is not even passed to detectAllWords. And if you add it, there will be a result:
home - (5, 3) - (2, 3) home - (5, 3) - (2, 0) same - (1, 1) - (4, 1)

 1
Author: Russtam, 2014-04-04 11:04:51