weegeee Ответов: 3

Алгоритм решения судоку


Я борюсь с проблемой создания алгоритма, который может решить супер-судоку. Мой судоку 21х9 и состоит из трех судоку 9х9 (строки 1-9 это первый, 7-15 второй и 12-21 третий). Я пытался написать алгоритм, но он не решает судоку должным образом. Я думаю, что что-то не так в функции, которая проверяет, можно ли вставить номер(notValid()Может быть, кто-то заметит, где я допустил ошибку.

Что я уже пробовал:

Вот что я пытался сделать:
#include<stdio.h>
#include<algorithm>

bool checkCol(int workArray[21][9], short begin, short end, short checkingValue, short y){
      for (int i = begin; i < end; ++i){
            if (workArray[i][y] == checkingValue){
                  return false;
            }
      }
      return true;
}

bool notValid(int workArray[21][9], short value, short pointX, short pointY){
      short rows = (pointX / 3) * 3;
      short columns = (pointY / 3) * 3;
      for (int i = 0; i < 9; ++i){
            if (workArray[rows + (i % 3)][columns + (i / 3)] == value){
                  return false;
            }
      }
      for (int i = 0; i < 9; ++i){
            if (workArray[pointX][i] == value){
                  return false;
            }
      }
      if (pointX >= 0 && pointX <= 5){
            if (!checkCol(workArray, 0, 9, value, pointY) && !checkCol(workArray, 6, 15, value, pointY)/* &&
                    !checkCol(workArray, 12, 21, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 6 && pointX <= 8){
            if (!checkCol(workArray, 0, 9, value, pointY) && !checkCol(workArray, 6, 15, value, pointY) /*&&
                    !checkCol(workArray, 12, 21, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 9 && pointX <= 11){
            if (!checkCol(workArray, 6, 15, value, pointY) && !checkCol(workArray, 0, 9, value, pointY) &&
                    !checkCol(workArray, 12, 21, value, pointY)){
                  return false;
            }
      }
      else if (pointX >= 12 && pointX <= 14){
            if (!checkCol(workArray, 12, 21, value, pointY) && !checkCol(workArray, 6, 15, value, pointY)/* &&
                    !checkCol(workArray, 0, 9, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 15 && pointX <= 20){
            if (/*!checkCol(workArray, 6, 15, value, pointY) &&*/ !checkCol(workArray, 12, 21, value, pointY)){
                  return false;
            }
      }
      return true;
}

bool findEmptySpace(int workArray[21][9], short &pointX, short &pointY);

bool solveTheSudoku(int workArray[21][9]){
      short pointX, pointY;
      if (!findEmptySpace(workArray, pointX, pointY)){
            return true;
      }
      for (int i=1; i<=9; ++i){
            if (notValid(workArray, i, pointX, pointY)){
                  workArray[pointX][pointY] = i;
                  if (solveTheSudoku(workArray)){
                        return true;
                  }
                  workArray[pointX][pointY] = 0;
            }
      }
      return false;
}

bool findEmptySpace(int workArray[21][9], short &pointX, short &pointY){
      for (pointX = 20; pointX >= 0; --pointX){
            for (pointY = 8; pointY >= 0; --pointY){
                  if (workArray[pointX][pointY] == 0){
                        return true;
                  }
            }
      }
      return false;
}

void printSudoku(int sudoku[21][9]){
      for (int i = 0; i < 21; ++i){
            for (int j = 0; j < 9; ++j){
                  printf("%d ",sudoku[i][j]);
            }printf("\n");
      }
}

int main(){
      int sudoku[21][9] = {{0, 0, 0, 0, 0, 0, 0, 0, 9},
                           {4, 7, 0, 0, 0, 0, 0, 0, 0},
                           {0, 0, 0, 5, 6, 2, 0, 0, 3},
                           {0, 6, 0, 0, 0, 0, 0, 0, 0},
                           {0, 0, 4, 0, 0, 3, 0, 6, 0},
                           {0, 5, 9, 0, 0, 0, 0, 0, 0},
                           {0, 0, 0, 2, 0, 0, 0, 0, 0},
                           {6, 0, 0, 4, 0, 0, 0, 0, 0},
                           {0, 4, 8, 0, 0, 0, 6, 0, 0},
                           {0, 0, 4, 0, 0, 0, 0, 0, 0},
                           {0, 2, 0, 0, 0, 0, 1, 0, 0},
                           {0, 9, 1, 0, 0, 4, 0, 0, 5},
                           {0, 0, 0, 0, 0, 0, 0, 0, 0},
                           {4, 0, 0, 6, 0, 0, 0, 0, 5},
                           {5, 0, 0, 0, 0, 0, 8, 6, 0},
                           {0, 0, 0, 0, 8, 7, 0, 2, 1},
                           {0, 1, 0, 0, 0, 3, 0, 8, 4},
                           {0, 2, 0, 0, 0, 0, 3, 0, 0},
                           {8, 0, 0, 3, 0, 0, 6, 4, 2},
                           {0, 4, 0, 7, 0, 0, 5, 0, 8},
                           {3, 0, 0, 4, 2, 0, 0, 7, 0}};
      //int arrayTmp[21][9];
      //std::copy(sudoku, sudoku+21, arrayTmp);
      if (solveTheSudoku(sudoku)){
            printSudoku(sudoku);
      }
      else{
            printf("No solution find\n");
            printSudoku(sudoku);
      }
      return 0;
}

enhzflep

Как бы то ни было, здесь, в CodeProject, есть статья, в которой используется веб-камера для поиска изображений головоломки судоку. После обнаружения код решает головоломку и накладывает решение поверх живого видеопотока.
Возможно, вы получите некоторый пробег от этой статьи. Вы можете найти его здесь: Веб-Камера Реального Времени Sudoku Solver

Patrice T

Это только 3 судоку или есть связь между ними ?

weegeee

Да, они связаны. Эти три судоку накладываются друг на друга и вместе образуют одно супер-судоку.

Patrice T

Дайте подробную информацию о том, как они пересекаются.
Воспользуйся Улучшить вопрос чтобы обновить ваш вопрос.
Чтобы каждый мог обратить внимание на эту информацию.

Patrice T

Можете ли вы объяснить, как должен работать ваш код?
Ваш фактический код удивительно короток.

weegeee

Он использует обратный путь. Начиная с низа, он пытается решить судоку. Если есть пустое место, я проверяю, подходит ли номер, и ввожу его, если не подходит, я возвращаюсь к предыдущему введенному номеру.

[no name]

EDIT: я решил эту проблему и должен был удалить свой код, чтобы избежать плагиата
Это тот самый код, который мы все собираемся украсть? Упражнение бессмысленно, потому что у Google есть кэшированная копия, и вы увидите, что CP имеет управление версиями.

#include<stdio.h>
#include<algorithm>
 
bool checkCol(int workArray[21][9], short begin, short end, short checkingValue, short y){
      for (int i = begin; i < end; ++i){
            if (workArray[i][y] == checkingValue){
                  return false;
            }
      }
      return true;
}
 
bool notValid(int workArray[21][9], short value, short pointX, short pointY){
      short rows = (pointX / 3) * 3;
      short columns = (pointY / 3) * 3;
      for (int i = 0; i < 9; ++i){
            if (workArray[rows + (i % 3)][columns + (i / 3)] == value){
                  return false;
            }
      }
      for (int i = 0; i < 9; ++i){
            if (workArray[pointX][i] == value){
                  return false;
            }
      }
      if (pointX >= 0 && pointX <= 5){
            if (!checkCol(workArray, 0, 9, value, pointY) && !checkCol(workArray, 6, 15, value, pointY)/* &&
                    !checkCol(workArray, 12, 21, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 6 && pointX <= 8){
            if (!checkCol(workArray, 0, 9, value, pointY) && !checkCol(workArray, 6, 15, value, pointY) /*&&
                    !checkCol(workArray, 12, 21, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 9 && pointX <= 11){
            if (!checkCol(workArray, 6, 15, value, pointY) && !checkCol(workArray, 0, 9, value, pointY) &&
                    !checkCol(workArray, 12, 21, value, pointY)){
                  return false;
            }
      }
      else if (pointX >= 12 && pointX <= 14){
            if (!checkCol(workArray, 12, 21, value, pointY) && !checkCol(workArray, 6, 15, value, pointY)/* &&
                    !checkCol(workArray, 0, 9, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 15 && pointX <= 20){
            if (/*!checkCol(workArray, 6, 15, value, pointY) &&*/ !checkCol(workArray, 12, 21, value, pointY)){
                  return false;
            }
      }
      return true;
}
 
bool findEmptySpace(int workArray[21][9], short &pointX, short &pointY);
 
bool solveTheSudoku(int workArray[21][9]){
      short pointX, pointY;
      if (!findEmptySpace(workArray, pointX, pointY)){
            return true;
      }
      for (int i=1; i<=9; ++i){
            if (notValid(workArray, i, pointX, pointY)){
                  workArray[pointX][pointY] = i;
                  if (solveTheSudoku(workArray)){
                        return true;
                  }
                  workArray[pointX][pointY] = 0;
            }
      }
      return false;
}
 
bool findEmptySpace(int workArray[21][9], short &pointX, short &pointY){
      for (pointX = 20; pointX >= 0; --pointX){
            for (pointY = 8; pointY >= 0; --pointY){
                  if (workArray[pointX][pointY] == 0){
                        return true;
                  }
            }
      }
      return false;
}
 
void printSudoku(int sudoku[21][9]){
      for (int i = 0; i < 21; ++i){
            for (int j = 0; j < 9; ++j){
                  printf("%d ",sudoku[i][j]);
            }printf("\n");
      }
}
 
int main(){
      int sudoku[21][9] = {{0, 0, 0, 0, 0, 0, 0, 0, 9},
                           {4, 7, 0, 0, 0, 0, 0, 0, 0},
                           {0, 0, 0, 5, 6, 2, 0, 0, 3},
                           {0, 6, 0, 0, 0, 0, 0, 0, 0},
                           {0, 0, 4, 0, 0, 3, 0

3 Ответов

Рейтинг:
1

OriginalGriff

Просто сбросьте свой код на нас и скажите :" Я думаю, что что - то не так в функции, которая проверяет, можно ли вставить число", - это не поможет-мы понятия не имеем, какой алгоритм вы пытаетесь использовать или как ваш код должен работать.

Разработка-это не случай "написать его, скомпилировать, исправить ошибки компилятора, скомпилировать, отправить" - просто компиляция не означает, что ваш код правильный! :смеяться:
Подумайте о процессе разработки как о написании письма: успешная компиляция означает, что вы написали письмо на правильном языке - например, на английском, а не на немецком, - а не то, что письмо содержало сообщение, которое вы хотели отправить.

Итак, теперь вы входите во вторую стадию разработки (на самом деле это четвертая или пятая, но к более ранним стадиям вы придете позже): тестирование и отладка.

Начните с рассмотрения того, что он делает и чем это отличается от того, что вы хотели. Это важно, потому что это дает вам информацию о том, почему он это делает. Например, если программа предназначена для того, чтобы позволить пользователю ввести число, а он удваивает его и печатает ответ, то если ввод / вывод был таким:

Input   Expected output    Actual output
  1            2                 1
  2            4                 4
  3            6                 9
  4            8                16
Тогда совершенно очевидно, что проблема заключается в бите, который удваивает его-он не прибавляет себя к себе или умножает его на 2, он умножает его на себя и возвращает квадрат входного сигнала.
Таким образом, вы можете посмотреть на код, и очевидно, что он где-то здесь:
private int Double(int value)
   {
   return value * value;
   }

Как только у вас появится идея, что может пойти не так, начните использовать отладчик, чтобы выяснить почему. Поставить точку останова на строке:
myaverage.DisplayAverage();

и запустите свое приложение. Подумайте о том, что должна делать каждая строка кода перед ее выполнением, и сравните это с тем, что она на самом деле делала, когда вы использовали кнопку "шаг вперед" для выполнения каждой строки по очереди. Он сделал то, что вы ожидали? Если да, то переходите к следующей строке.
Если нет, то почему? Чем это отличается?

Это навык, и его стоит развивать, поскольку он помогает вам как в реальном мире, так и в развитии. И, как и все навыки, он совершенствуется только при использовании!

Так что попробуйте: научитесь использовать отладчик на относительно тривиальном примере, подобном этому, прежде чем вы столкнетесь с ошибкой в 200 000 строк кода, написанного кем-то другим в тот день, когда он покинул компанию!


Рейтинг:
1

Patrice T

Цитата:
Эти меньшие судоку накладываются друг на друга: строки 1-9-это первое судоку, но строки 7-9 также являются частью второго судоку (всего 7-15 строк). Аналогия в случае третьего судоку, три последние строки (12-15) являются частями третьего судоку (строки 12-21).

Как я понимаю, у вас есть 5 3 судоку, которые находятся в строках 0-8, 3-11, 6-14, 9-17, 12-20.

Когда вы не понимаете, что делает ваш код или почему он делает то, что делает, ответ таков: отладчик.
Используйте отладчик, чтобы увидеть, что делает ваш код. Просто установите точку останова и посмотрите, как работает ваш код, отладчик позволяет вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения, это невероятный инструмент обучения.

Отладчик-Википедия, свободная энциклопедия[^]

Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]
Базовая отладка с помощью Visual Studio 2010-YouTube[^]
Отладчик здесь для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.
В отладчике нет никакой магии, он не находит ошибок, он просто помогает вам. Когда код не делает того, что ожидается, вы близки к ошибке.

[Обновление]
Цитата:
Он использует обратный путь. Начиная с низа, он пытается решить судоку. Если есть пустое место, я проверяю, подходит ли номер, и ввожу его, если не подходит, я возвращаюсь к предыдущему введенному номеру.

Это грубая силовая атака, она крайне неэффективна. Человеческий алгоритм решения гораздо эффективнее.


weegeee

Прежде всего, я хочу, чтобы мой алгоритм работал правильно, но у меня все еще есть проблема с правильными значениями в Столбцах (числа дублируются).

Patrice T

Воспользуйся Улучшить вопрос чтобы обновить ваш вопрос.
Чтобы каждый мог обратить внимание на эту информацию.

Рейтинг:
1

Kornfeld Eliyahu Peter

Попробовать это:

#include<stdio.h>
#include<algorithm>

bool checkCol(int workArray[21][9], short begin, short end, short checkingValue, short y){
      for (int i = begin; i < end; ++i){
            if (workArray[i][y] == checkingValue){
                  return false;
            }
      }
      return true;
}

bool notValid(int workArray[21][9], short value, short pointX, short pointY){
      short rows = (pointX / 3) * 3;
      short columns = (pointY / 3) * 3;
      for (int i = 0; i < 9; ++i){
            if (workArray[rows + (i % 3)][columns + (i / 3)] == value){
                  return false;
            }
      }
      for (int i = 0; i < 9; ++i){
            if (workArray[pointX][i] == value){
                  return false;
            }
      }
      if (pointX >= 0 && pointX <= 5){
            if (!checkCol(workArray, 0, 9, value, pointY) && !checkCol(workArray, 6, 15, value, pointY)/* &&
                    !checkCol(workArray, 12, 21, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 6 && pointX <= 8){
            if (!checkCol(workArray, 0, 9, value, pointY) && !checkCol(workArray, 6, 15, value, pointY) /*&&
                    !checkCol(workArray, 12, 21, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 9 && pointX <= 11){
            if (!checkCol(workArray, 6, 15, value, pointY) && !checkCol(workArray, 0, 9, value, pointY) &&
                    !checkCol(workArray, 12, 21, value, pointY)){
                  return false;
            }
      }
      else if (pointX >= 12 && pointX <= 14){
            if (!checkCol(workArray, 12, 21, value, pointY) && !checkCol(workArray, 6, 15, value, pointY)/* &&
                    !checkCol(workArray, 0, 9, value, pointY)*/){
                  return false;
            }
      }
      else if (pointX >= 15 && pointX <= 20){
            if (/*!checkCol(workArray, 6, 15, value, pointY) &&*/ !checkCol(workArray, 12, 21, value, pointY)){
                  return false;
            }
      }
      return true;
}

bool findEmptySpace(int workArray[21][9], short &pointX, short &pointY);

bool solveTheSudoku(int workArray[21][9]){
      short pointX, pointY;
      if (!findEmptySpace(workArray, pointX, pointY)){
            return true;
      }
      for (int i=1; i<=9; ++i){
            if (notValid(workArray, i, pointX, pointY)){
                  workArray[pointX][pointY] = i;
                  if (solveTheSudoku(workArray)){
                        return true;
                  }
                  workArray[pointX][pointY] = 0;
            }
      }
      return false;
}

bool findEmptySpace(int workArray[21][9], short &pointX, short &pointY){
      for (pointX = 20; pointX >= 0; --pointX){
            for (pointY = 8; pointY >= 0; --pointY){
                  if (workArray[pointX][pointY] == 0){
                        return true;
                  }
            }
      }
      return false;
}

void printSudoku(int sudoku[21][9]){
      for (int i = 0; i < 21; ++i){
            for (int j = 0; j < 9; ++j){
                  printf("%d ",sudoku[i][j]);
            }printf("\n");
      }
}

int main(){
      int sudoku[21][9] = {{0, 0, 0, 0, 0, 0, 0, 0, 9},
                           {4, 7, 0, 0, 0, 0, 0, 0, 0},
                           {0, 0, 0, 5, 6, 2, 0, 0, 3},
                           {0, 6, 0, 0, 0, 0, 0, 0, 0},
                           {0, 0, 4, 0, 0, 3, 0, 6, 0},
                           {0, 5, 9, 0, 0, 0, 0, 0, 0},
                           {0, 0, 0, 2, 0, 0, 0, 0, 0},
                           {6, 0, 0, 4, 0, 0, 0, 0, 0},
                           {0, 4, 8, 0, 0, 0, 6, 0, 0},
                           {0, 0, 4, 0, 0, 0, 0, 0, 0},
                           {0, 2, 0, 0, 0, 0, 1, 0, 0},
                           {0, 9, 1, 0, 0, 4, 0, 0, 5},
                           {0, 0, 0, 0, 0, 0, 0, 0, 0},
                           {4, 0, 0, 6, 0, 0, 0, 0, 5},
                           {5, 0, 0, 0, 0, 0, 8, 6, 0},
                           {0, 0, 0, 0, 8, 7, 0, 2, 1},
                           {0, 1, 0, 0, 0, 3, 0, 8, 4},
                           {0, 2, 0, 0, 0, 0, 3, 0, 0},
                           {8, 0, 0, 3, 0, 0, 6, 4, 2},
                           {0, 4, 0, 7, 0, 0, 5, 0, 8},
                           {3, 0, 0, 4, 2, 0, 0, 7, 0}};
      //int arrayTmp[21][9];
      //std::copy(sudoku, sudoku+21, arrayTmp);
      if (solveTheSudoku(sudoku)){
            printSudoku(sudoku);
      }
      else{
            printf("No solution find\n");
            printSudoku(sudoku);
      }
      return 0;
}