Модераторы: Rickert
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Квадратная матрица 9х9, Игра "Судоку" 
:(
    Опции темы
emmanuil
Дата 4.7.2007, 04:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: нет
Всего: 3



Задача такая:
Нужно заполнить квадратную матрицу (9х9, а может и другой размерности) числами от 1 до 9 (или до числа размерности) так, чтобы в строках и в столбцах числа не повторялись.
Кто знает алгоритм, напишите его, буду признателен!

Добавлено через 6 минут и 36 секунд
Модераторам:
Можно продублировать эту тему в форумах Программирование игр, графики и иск. интл., Алгоритмы
PM MAIL   Вверх
SpaceSpace
Дата 4.7.2007, 07:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 366
Регистрация: 10.4.2007
Где: Самара

Репутация: нет
Всего: 10



решалку для судоку делаеш? smile

говорю сразу, если важно время - перебором ни в коем случае не делай.

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

самый большой недостаток:
вероятность, что при наличит решения рандом - алгоритм не попадет за заданное кол-во итераций (200 неапример)
в решение.


--------------------
Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение.
70-565
MCPD Enterprise 3.5 
PM MAIL   Вверх
emmanuil
Дата 4.7.2007, 07:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: нет
Всего: 3



Да решалку.
То что нужно прверять корректность значений это ерунда.
Нужно найти правильное расположение цифр, чтобы все было по условию. Вот, допустим, заполнилась почти вся матрица, кроме последней ячейки, а в эту ячейку ни одно число не подходит, и что тогда? Нужно возвращаться назад, вот с этим то и проблемма
PM MAIL   Вверх
stab
Дата 4.7.2007, 08:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Экс. модератор
Сообщений: 1839
Регистрация: 1.1.2003

Репутация: нет
Всего: 48



Цитата(emmanuil @  4.7.2007,  08:54 Найти цитируемый пост)
Модераторам:
Можно продублировать эту тему в форумах Программирование игр, графики и иск. интл., Алгоритмы 


наверное там ей и место, тебя ведь алгоритм интересует. перенести? а дублировать не надо.


--------------------
6, 6, 6 - the number of the beast.
PM MAIL WWW   Вверх
emmanuil
Дата 4.7.2007, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: нет
Всего: 3



stab, да. Спасибо!
PM MAIL   Вверх
thomas
Дата 4.7.2007, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доцент... почти
***


Профиль
Группа: Завсегдатай
Сообщений: 1385
Регистрация: 3.10.2006
Где: " Сказочное королевство"

Репутация: нет
Всего: 65



emmanuil, 
Вот посмотри самый простой вариант заполнения:
заполняем с лева на право, с верху в низ;
каждая следующая строка начинается со следуещего числа.
Размер роли не играет 9х9, 10х10,13х13 ...

1  2  3  4  5  6  7  8  9 
2  3  4  5  6  7  8  9  1
3  4  5  6  7  8  9  1  2
4  5  6  7  8  9  1  2  3
5  6  7  8  9  1  2  3  4
6  7  8  9  1  2  3  4  5
7  8  9  1  2  3  4  5  6
8  9  1  2  3  4  5  6  7
9  1  2  3  4  5  6  7  8

Это в любом случае начальный вариант, его можно заполнить нячиная с каждого их 4-х углов.
В приведенном выше примере каждая строка и колонка уникальна.
Что бы не нарушать уникальности строк или колонок, мне думается, можно перемещать либо только колонки, либо только строки. (т.е. менять местами, например - 1 с 4, 2 с 5, 3 с 6, 7 с 9, а 8-я на месте)
(от перемены мест слогаемых, сумма не изменяется)

1  2  3  4  5  6  7  8  9      
3  4  5  6  7  8  9  1  2
2  3  4  5  6  7  8  9  1
5  6  7  8  9  1  2  3  4
4  5  6  7  8  9  1  2  3
7  8  9  1  2  3  4  5  6
9  1  2  3  4  5  6  7  8
8  9  1  2  3  4  5  6  7

Получается что заполнив начальный вариант из какого-то угла, мы можем получить другие варианты, только при помощи перемены порядка расположения либо строк, либо колонок. Все.  smile 

Рандом здесь не уместен. Только алгоритм заполнения. 

Удачи.  smile 




Это сообщение отредактировал(а) thomas - 4.7.2007, 09:35


--------------------
Крепко жму горло, искренне ваш Thomas. (С)vingrad
Некоторые сорта флоры буквально за одно мгновение превращают нас в фауну!
Проблемы негров шерифа не волнуют.
PM MAIL   Вверх
emmanuil
Дата 4.7.2007, 09:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: нет
Всего: 3



thomas, спасибо!
Но как быть если некоторые ячейки матрицы уже заполнены и их перемещать нельзя. это игра "судоку", слышал про такую?
PM MAIL   Вверх
thomas
Дата 4.7.2007, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доцент... почти
***


Профиль
Группа: Завсегдатай
Сообщений: 1385
Регистрация: 3.10.2006
Где: " Сказочное королевство"

Репутация: нет
Всего: 65



emmanuil, 
Не, не слышал.  smile 

Но по логике вещей, заполнить матрицу можно только так, как я написал выше. Для каждого размера есть определенное кол-во комбинацый. Ни больше ни меньше.
Значит, уже имеемые позиции отвечают той или иной комбинации. 
Вопрос только в том как определить какая комбинация нужна?

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

ЗЫ А кто знает адрес хоста куда можно картинки заливать, что бы на форум можно было выкладывать?  smile 

Это сообщение отредактировал(а) thomas - 4.7.2007, 09:44


--------------------
Крепко жму горло, искренне ваш Thomas. (С)vingrad
Некоторые сорта флоры буквально за одно мгновение превращают нас в фауну!
Проблемы негров шерифа не волнуют.
PM MAIL   Вверх
SpaceSpace
Дата 4.7.2007, 09:59 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 366
Регистрация: 10.4.2007
Где: Самара

Репутация: нет
Всего: 10



предлагаю тупейший хардкор способ.

Делаеш ПОЛНЫЙ ПЕРЕБОР.
записываеш все варианты на диск (несколько гигов smile)
затем остается лишь найти подходящий 
smile)))))


--------------------
Репутация - самое ценное, что есть у человека. Зарабатывают годы, теряют за мгновение.
70-565
MCPD Enterprise 3.5 
PM MAIL   Вверх
emmanuil
Дата 4.7.2007, 11:04 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: нет
Всего: 3



 *-----------*
 |4.5|1..|..7|
 |..1|..6|..4|
 |.8.|2..|...|
 |---+---+---|
 |...|.7.|56.|
 |7..|.2.|..8|
 |.94|.3.|...|
 |---+---+---|
 |...|..2|.8.|
 |6..|8..|4..|
 |8..|..9|7.6|
 *-----------*

Вот например. И еще нужно чтобы в квадратах 3х3 тоже числа не повторялись
PM MAIL   Вверх
emmanuil
Дата 5.7.2007, 05:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: нет
Всего: 3



Вот весь код, но при некоторых комбинациях прога виснет, из рекурсии не выходит, мож кто увидит в чем дело?
(алг-м нашел гдето в сети, точно не помню где, был на C++, перевел на C#, кое-что переделал)
метод SudokuSolve стартует все.

Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;

namespace Sudoku
{
    public class Sudoku
    {
        /// проверка правильности заполнения
        public bool CheckSudoku(int[,] matrix)
        {
            int[] tempData = new int[9];
            // по строкам
            for (int row = 0; row < 9; row++)
            {
                Array.Clear(tempData, 0, tempData.Length);
                for (int col = 0; col < 9; col++)
                {
                    if (matrix[col, row] != 0)
                    {
                        if (tempData[matrix[col, row] - 1] == 1)
                            return false;
                        tempData[matrix[col, row] - 1] = 1;
                    }
                }
            }
            // по столбцам
            for (int col = 0; col < 9; col++)
            {
                Array.Clear(tempData, 0, tempData.Length);
                for (int row = 0; row < 9; row++)
                {
                    if (matrix[col, row] != 0)
                    {
                        if (tempData[matrix[col, row] - 1] == 1)
                            return false;
                        tempData[matrix[col, row] - 1] = 1;
                    }
                }
            }
            // по мини-матрицам 3х3
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                {
                    Array.Clear(tempData, 0, tempData.Length);
                    for (int col = 0; col < 3; col++)
                        for (int row = 0; row < 3; row++)
                        {
                            if (matrix[j * 3 + col, i * 3 + row] != 0)
                            {
                                if (tempData[matrix[j * 3 + col, i * 3 + row] - 1] == 1)
                                    return false;
                                tempData[matrix[j * 3 + col, i * 3 + row] - 1] = 1;
                            }
                        }
                }

            return true;
        }

        // Ищет клетку с минимально возможным числом кандидатов
        private int FindMinPoint(out SudokuPoint p, int[,] matrix) 
        {
            int variancesCount = 0;
            int minVariances = 10;
            bool hasFree = false;
            p = new SudokuPoint();
            int countZero = 0;

            for (int i = 0; i < 9; i++)
                for (int j = 0; j < 9; j++)
                {
                    //if (i == 1 && j == 8)
                        //MessageBox.Show(matrix[j, i].ToString());
                    if (matrix[j, i] == 0)
                    {
                        hasFree = true;

                        countZero++;

                        variancesCount = 0;
                        for (int variance = 1; variance <= 9; variance++)
                        {
                            matrix[j, i] = variance;
                            if (CheckSudoku(matrix))
                                variancesCount++;
                        }

                        matrix[j, i] = 0;

                        if (variancesCount > 0 && variancesCount < minVariances)
                        {
                            p.Row = i;
                            p.Col = j;
                            p.Variances = variancesCount;
                            minVariances = variancesCount;
                        }
                    }
                }

            //if (countZero < 10)
                //MessageBox.Show(countZero.ToString() + "___" + minVariances.ToString());

            if (hasFree && minVariances < 10)
                return 1; // нашли, куда можно поставить цифру
            if (hasFree)
                return -1; // свободное место есть, но поставить никуда нельзя
            return 0; // нет свободного места
        }

        ulong count = 0;
        ulong exit = 0;
        ulong max = 0;

        private int SudokuSolveRecursive(ref int[,] matrix, Label lbl)
        {
            count++;
            max = count - exit;
            lbl.Text = count.ToString() + "___" + max.ToString() +
                "___" + exit.ToString();

            SudokuPoint pt;
            int result;

            // ищем клетку с наименьшим числом кандидатов:
            result = FindMinPoint(out pt, matrix);
            if (result == 0)
            {
                exit++;
                max = count - exit;
                lbl.Text = count.ToString() + "___" + max.ToString() +
                    "___" + exit.ToString();
                //MessageBox.Show("УРА!!!");
                return 1; // решение найдено
            }
            if (result == -1)
            {
                exit++;
                max = count - exit;
                lbl.Text = count.ToString() + "___" + max.ToString() +
                    "___" + exit.ToString();
                //MessageBox.Show("bad");
                return -1; // тупиковая комбинация
            }

            // сохраняем то, что есть
            int[,] saveData = CopyFromArray(matrix);

            // пытаемся поставить в найденную клетку цифры от 1 до 9
            for (int variance = 1; variance <= 9; variance++)
            {
                matrix[pt.Col, pt.Row] = variance;
                // проверяем, можно ли поставить такую цифру
                if (CheckSudoku(matrix))
                {
                    // запускаем функцию рекурсивно
                    result = SudokuSolveRecursive(ref matrix, lbl);

                    if (result == 1) // решение найдено
                    {
                        exit++;
                        max = count - exit;
                        lbl.Text = count.ToString() + "___" + max.ToString() +
                            "___" + exit.ToString();
                        return 1;
                    }
                    if (result == -1) // тупиковая комбинация
                    {
                        // восстанавливаем массив и берём следующую цифру на то же место
                        matrix = CopyFromArray(saveData);
                    }
                }
            }
            exit++;
            max = count - exit;
            lbl.Text = count.ToString() + "___" + max.ToString() +
                "___" + exit.ToString();
            return -1;
        }

        private int[,] CopyFromArray(int[,] srcMatrix)
        {
            int[,] dstMatrix = new int[9, 9];
            for (int i = 0; i < 9; i++)
                for (int j = 0; j < 9; j++)
                    dstMatrix[i, j] = srcMatrix[i, j];
            return dstMatrix;
        }

        public int SudokuSolve(ref int[,] matrix, Label lbl)
        {
            return SudokuSolveRecursive(ref matrix, lbl);
        }
    }
}

PM MAIL   Вверх
emmanuil
Дата 11.7.2007, 05:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 380
Регистрация: 9.1.2007

Репутация: нет
Всего: 3



Ну что ж, раз больше нет предложений, то благодарю всех за участие!
Но вопрос остался не решенным!
PM MAIL   Вверх
LipatOFF
Дата 12.7.2007, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 38
Регистрация: 6.7.2007

Репутация: нет
Всего: нет



если это еще актуально - могу попробовать написать программу
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Программирование игр, графики и искуственного интеллекта"
Rickert

НА ЗЛОБУ ДНЯ: Дорогие посетители, прошу обратить внимание что новые темы касающиеся новых вопросов создаются кнопкой "Новая тема" а не "Ответить"! Любые оффтопиковые вопросы, заданные в текущих тематических темах будут удалены а их авторы, при рецедиве, забанены.

  • Литературу, связанную с программированием графики, обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы связанные с программированием графики и мультимедии на языках С++ и Delphi
  • Вопросы по реализации алгоритмов рассматриваются здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rickert.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Программирование игр, графики и искусственного интеллекта | Следующая тема »


 




[ Время генерации скрипта: 0.0553 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.