@Vernal96

Почему программа зацикливается при переборе?

Пишу программу по решению Судоку, реализую методом перебора с возвратом, но при выполнении она начинает зацикливаться. Подскажите пожалуйста что я делаю не так, вот код:
Основной код перебора:
int i, j, k;
            string text;
            int[] arr = new int[81];
            int[,,] arr1 = new int[81, 3, 9];
            //прием данных        
            i = 0;
            foreach (Control control in Controls)
            {
                TextBox tb = control as TextBox;
                if (tb != null)
                {
                    if (tb.Text != String.Empty)
                    {
                        arr[i] = Convert.ToInt32(tb.Text);
                        i++;
                    }
                    else
                    {
                        arr[i] = 0;
                        i++;
                    }
                }
            }
            //перенос данных в рабочий массив
            /*
            arr1[i,0] - здесь найденное решение 
            arr1[i,0,8] - здесь значение задается если цифра задана в условии
            arr1[i,1] - здесь кандидаты
            arr1[i,2] - здесь уже использованные кандидаты
            */
            for (i = 0; i < 81; i++)
            {
                arr1[i, 0, 0] = arr[i];
                if (arr[i] > 0)
                {
                    arr1[i, 0, 8] = arr[i];
                }
                if (arr[i] == 0)
                {
                    for (j = 0; j < 9; j++)
                    {
                        arr1[i, 1, j] = j + 1;
                    }
                }
            }


            //решение
            for (i = 0; i < 81; i++)
            {
                if (arr1[i, 0, 8] == 0) 
                {
                    for (j = 0; j < 9; j++)
                    {
                        arr1[i, 1, j] = j + 1;
                    }
                    constriction(i, arr1); //сокращение кандидатов
                    k = 0;
                    for (j = 0; j < 9; j++)
                    {
                        if (arr1[i, 1, j] > 0)
                        {
                            if (arr1[i, 1, j] == arr1[i, 2, j]) arr1[i, 1, j] = 0;
                            else k++;
                        }
                    }
                    if (k > 0)
                    {
                        for (j = 0; j < 9; j++)
                        {
                            if (arr1[i, 1, j] > 0 && arr1[i,2,j] == 0)
                            {
                                arr1[i, 0, 0] = arr1[i, 1, j];
                                arr1[i, 2, j] = arr1[i, 1, j];
                               break;
                            }
                        }
                    }
                    else
                    {
                        arr1[i, 0, 0] = 0;
                        for (j = 0; j < 9; j++)
                        {
                            arr1[i, 2, j] = 0;
                        }
                        i--;
                        while(arr1[i,0,8] > 0 && i > 0)
                        {
                            i--;
                        }
                        if (i != 0)
                        {
                            i--;
                        }
                    }
                }
            }


Код функции сокращения кандидатов:
int x, j, y;
            //сокращение в строке
            x = i;
            while (x % 9 != 0)
            {
                x--;
            }
            for (j = x; j < x + 9; j++)
            {
                if (j != i)
                {
                    if (arr1[j, 0, 0] > 0) arr1[i, 1, arr1[j, 0, 0] - 1] = 0;
                }
            }
            //сокращение в столбце
            y = i;
            while (y > 8)
            {
                y--;
            }
            for (j = y; j < y + 73; j += 9)
            {
                if (j != i)
                {
                    if (arr1[j, 0, 0] > 0) arr1[i, 1, arr1[j, 0, 0] - 1] = 0;
                }
            }
            //сокращение в сегменте
            x = i - x;
            y = i - y;
            if (x < 3) x = 1;
            if (x > 2 && x < 6) x = 2;
            if (x > 5) x = 3;
            if (y <= 18) y = 1;
            if (y > 18 && y < 54) y = 2;
            if (y >= 54) y = 3;
            x *= y;
            switch (x)
            {
                case 1:
                    {
                        x = 0;
                        break;
                    }
                case 2:
                    {
                        x = 3;
                        break;
                    }
                case 3:
                    {
                        x = 6;
                        break;
                    }
                case 4:
                    {
                        x = 27;
                        break;
                    }
                case 5:
                    {
                        x = 30;
                        break;
                    }
                case 6:
                    {
                        x = 33;
                        break;
                    }
                case 7:
                    {
                        x = 54;
                        break;
                    }
                case 8:
                    {
                        x = 57;
                        break;
                    }
                case 9:
                    {
                        x = 60;
                        break;
                    }
            }
            for (j = x; j < x + 19; j+= 9)
            {
                for (y = j; y < j + 3; y++)
                {
                    if (y != i)
                    {
                        if (arr1[y, 0, 0] > 0) arr1[i, 1, arr1[y, 0, 0] - 1] = 0;
                    }
                }
            }
  • Вопрос задан
  • 774 просмотра
Пригласить эксперта
Ответы на вопрос 2
@Beltoev
Живу в своё удовольствие
Не думаю, что кто-нибудь будет вдаваться в подробности такого не читаемого кода, поэтому предлагаю вам решить проблему самостоятельно, открыв для себя такое чудесное слово, как "Отладчик".

Все очень просто: поставьте после каждого цикла while и for (на всякий случай) точки остановки. Запустите программу и каждую точку, на которой остановится отладчик, просто пропустите клавишей F5. В итоге, как только программа "зациклится", вы будете знать, до какой точки вы не дошли, следовательно, виновен будет цикл, стоящий до этой точки остановки.

Ну, а потом уже ставите точку остановки перед этим циклом и клавишей F10 по шагам разбираетесь,почему условие цикла не выполняется.

UPD:
Присмотрелся к коду:
for (i = 0; i < 81; i++) <-----
            {
...
                        i--; <-----
                        while(arr1[i,0,8] > 0 && i > 0)
                        {
                            i--; <-----
                        }
                        if (i != 0)
                        {
                            i--; <-----
                        }

Уловили? =)
Ответ написан
Adamos
@Adamos
Судоку решается так:
1. проходим по всей таблице и для каждой ячейки определяем, какие цифры в ней могут быть, по уже имеющимся.
2. проходим по всем ячейкам. Если там может быть только одна цифра - заносим эту цифру в ячейки и исключаем ее вариант из всех ячеек, которые "бьет" данная. Выставляем флаг "были изменения".
3. проверяем варианты на всех линиях в поисках единственного места, где может стоять цифра. Если находим такое место - вписываем цифру, "бьем" ячейки, выставляем флаг.
4. если выставлен флаг "были изменения" - возвращаемся в п. 2
5. если поле не заполнено полностью, значит, решения нет.
И никакой перебор с возвратом здесь на хрен не нужен.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы