Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 34, средняя оценка - 4.76
OVERPOWER8
19 / 19 / 1
Регистрация: 29.11.2009
Сообщений: 224
#1

Судоку! - C++

05.01.2010, 16:32. Просмотров 5125. Ответов 3
Метки нет (Все метки)

Почти написал программу для генерирования судоку. Компилируется, работает, однако в 50% случаях генерирует только 3-8 строк и зависает. В остальных случаях генерирует полность, но в квадратах числа повторяются. Подскажите, где ошибка, а то я 100 раз код просмотрел и не заметил.

Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
#include <stdlib.h>
using namespace std;
 
int main()
{
    srand(time(0));
    const int size=9;
    int number;
    int sudoku[size][size];
    int i, j;
    int k, l;
    int chance;
    int i_from, j_from;
    
    bool repeated;
    
    for(i=0; i<size; i++)
    {
        for(j=0; j<size; j++)
        {
            
            chance=rand()%4;
            if(chance==0)
            {
                cout << "#" << " ";
                sudoku[i][j]=0;
                continue;
            }
            
            if(i<3) i_from=0;
            else if(i<6) i_from=3;
            else i_from=6;
            
            if(j<3) j_from=0;
            else if(j<6) j_from=3;
            else j_from=6;
            
            for(;;)
            {
                repeated=false;
                number=rand()%9+1;
                
                for(l=i_from; l<i; l++)
                    for(k=j_from; k<j; k++)
                        if(sudoku[l][k]==number)
                        {
                            repeated=true;
                            break;
                        }
                
                for(l=0; l<i; l++)
                    if(sudoku[l][j]==number)
                    {
                        repeated=true;
                        break;
                    }
                for(k=0; k<j; k++)
                    if(sudoku[i][k]==number)
                    {
                        repeated=true;
                        break;
                    }
                
                if(repeated==true)
                    continue;
                    
                sudoku[i][j]=number;
                break;
            }
            cout << sudoku[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.01.2010, 16:32
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Судоку! (C++):

Генератор судоку - C++
Маленькая проблемка с программой - в одном из 10 случаев программа зависает. Кому не сложно, прошу проверить и исправить. Вот полный...

Судоку: рандомное заполнение массива - C++ Builder
Вот заполнение рандомом масива. Рандомно как то повторяющих елементов много подскажите может кто делал? { for(i=1; i&lt;9; i++){ ...

Таблица для игры Судоку - C++ Builder
У меня задача сделать игру Судоку. Я пробовал рисовать таблицу для значений через StringGrid, но не увидел возможности разбить таблицу 9х9...

Игра судоку (крестики-нолики) - C++ Builder
Люди подскажите пожалуйста. Препод дал задание написать игру судоку ну типа крестики нолики. Поле 9 на 9 . Выигрывает в том случае если 5...

Как составить цикл? Игра судоку. - C++ Builder
Здраствуйте препод задал написать игру судоку(крестики нолики) поле 9 на 9 ячеек. Выйгрыш в том случае когда идет 5 подряд или крестиков...

Судоку в Visual C++ - Visual C++
Все доброго времени суток! Вот стоит передо мною задача сделать игру Судоку (принцип которой даже не понимаю, не то чтоб написать такую....

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
zim22
depict1
276 / 141 / 2
Регистрация: 11.07.2009
Сообщений: 606
05.01.2010, 19:02 #2
открой для себя функции. весь код в функции main - это круто конечно. если врагов запутать.
0
OVERPOWER8
19 / 19 / 1
Регистрация: 29.11.2009
Сообщений: 224
05.01.2010, 22:49  [ТС] #3
Почти что написал, вот код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <time.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
 
const int size = 9;
const int initial_mask = ~((-1) << size);
 
int sudoku[size][size]; // это матрица судоку
// этот массив будет использоваться для пометки проверенных чисел
// лишняя колонка позволяет избежать дополнительной проверки индекса
int check[size][size+1];
 
 
// генерируем ячейку
bool cell( int i, int j )
{
    int chk = check[i][j];  // маска чисел, уже проверенных в этой ячейке
    if( !chk )
        return false;       // на предыдущих проходах уже были проверены все числа
 
    for(;;)
    {
        // генерируем число, новое для этой ячейки
        int number, bit;
        do {
            number = rand() % size;
            bit = 1 << number;
        } while( !(chk & bit) );
        chk &= ~bit;
        ++number;
 
        // проверяем, было ли это число ранее ...
        bool repeated = false;
        // ... в столбце
        for(int l=0; l<i; l++)
            if(sudoku[l][j]==number)
            {
                repeated = true;
                break;
            }
        if( repeated ) {
            // number уже есть в этом стобце
            if( chk == 0 ) return false;    // проверены все числа
            continue;   // пытаемся снова
        }
 
        // ... в строке
        for(int k=0; k<j; k++)
            if(sudoku[i][k]==number)
            {
                repeated = true;
                break;
            }
 
        if( repeated ) {
            // number уже есть в этой строке
            if( chk == 0 ) return false;    // проверены все числа
            continue;   // пытаемся снова
        }
 
        sudoku[i][j] = number;  // нашли подходящее (пока) число
        check[i][j] = chk;      // сохраняем маску проверенных чисел
 
        cout << number << " ";
        return true;
    }
 
}
 
// генерируем строку
bool row( int i )
{
    check[i][0] = initial_mask; // сброс маски для первой ячейки
    int j = 0;
    while( j < size ) {
        if( cell( i, j )) {
            // ячейка заполнена, переходим к следующей
            ++j;
            check[i][j] = initial_mask; // сброс маски для очередной ячейки
                // индекс j здесь не проверяли - помните объявление  int check[size][size+1] ?
        }
        else {
            // увы, не получилось
            // возвращаемся к предыдущей ячейке и ищем для нее какое-то другое число
            // будет использована ранее сохраненная маска check[][]
            if( --j < 0 )
                return false;       // придется вернуться к предыдущей строке
 
            // вывод отладочной информации - отслеживание возвратов
            cout << endl << i << ": ";
            for( int k = 0; k < j; ++k )
                cout << sudoku[i][k] << " ";
        }
    }
    cout << endl;
    return true;
}
 
int main()
{
    time_t kl;
    time( &kl );
    srand(kl);
 
    int i = 0;
    while( i < size ) {
        cout << i << ": ";
        if( row( i ))
            ++i;
        else
            if( --i < 0 ) { cout << endl << "error! << endl"; break; }
    }
    
    int j;
    cout << endl;
    for(i=0; i<size; i++)
    {
        for(j=0; j<9; j++)
            cout << sudoku[i][j] << " ";
        cout << endl;
    }
}
Только один недочет - надо, чтобы в квадратах 3*3 тоже были разные значения.

Т. е. надо как-то вот этот код туда прибахать:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int i_from, j_from;
        
        for(i=0; i<size; i++)
        {
                for(j=0; j<size; j++)
                {
                        
                        if(i<3) i_from=0;
                        else if(i<6) i_from=3;
                        else i_from=6;
                        
                        if(j<3) j_from=0;
                        else if(j<6) j_from=3;
                        else j_from=6;
                        
                        for(;;)
                        {
                                repeated=false;
                                number=rand()%9+1;
                                
                                for(l=i_from; l<i; l++)
                                        for(k=j_from; k<j; k++)
                                                if(sudoku[l][k]==number)
                                                {
                                                        repeated=true;
                                                        break;
                                                }
                        ...
                        }
0
outoftime
║XLR8║
510 / 432 / 33
Регистрация: 25.07.2009
Сообщений: 2,295
06.01.2010, 02:04 #4
Все, сделал!! Ура
http://codepad.org/BY9ezRij - подтверждение что оно пашет)), а вот и сам код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <iostream>
 
int IsSq(int** a, int i, int j, int b)
{
    int di = i/3,
        dj = j/3;
    for (int _b(di*3), ddi = _b; ddi < _b+3; ++ddi)
        for (int __b(dj*3), ddj = __b; ddj < __b+3; ++ddj)
            if (a[ddi][ddj] == b) return 1;
    return 0;
}
 
int IsVer(int** a, int i, int b)
{
    for (int dj = 0; dj < 9; ++dj)
        if (a[i][dj] == b) return 1;
    return 0;
}
 
int IsHor(int** a, int j, int b)
{
    for (int di = 0; di < 9; ++di)
        if (a[di][j] == b) return 1;
    return 0;
}
 
void InitMas(int** a)
{
    for (int i = 0; i < 9; ++i)
        for (int j = 0; j < 9; ++j)
            a[i][j] = -1;
}
 
void Sudoku(int** a)
{
    for (int i = 0; i < 9; ++i)
    {
        for (int j = 0; j < 9; ++j)
        {
            int c = 9;
            for (int h = 1; h < 10; ++h)
                if (IsSq(a,i,j,h) || IsHor(a,j,h) || IsVer(a,i,h) )
                    --c;
            if (!c)
            {
                InitMas(a);
                Sudoku(a);
                return;
            }
            int b = rand()%9+1;
            while (IsSq(a,i,j,b) || IsHor(a,j,b) || IsVer(a,i,b) )
                b = rand()%9+1;
            a[i][j] = b;
        }
    }
}
 
void ShowMas(int** a)
{
    for (int i = 0; i < 9; ++i)
    {
        for (int j = 0; j < 9; ++j)
            printf("%3d",a[i][j]);
        printf("\n\n");
    }
}
 
int main()
{
    int** a = (int **) calloc(9, sizeof(int *));
    for (int i = 0; i < 9; ++i)
        a[i] = (int *) calloc (9, sizeof(int));
    InitMas(a);
    Sudoku(a);
    ShowMas(a);
    getchar();
    return 0;
}
оказывается сервак на http://codepad.org довольно мощный, он буквально за долю секунды сгенерировал ответ, мой же ПК наверное с 20 сек думает)) а, нет, проверил, пашет: 7,531 секунды))
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.01.2010, 02:04
Привет! Вот еще темы с ответами:

Судоку - C++
Добрый день! Очень нужна помощь! Нужен код СУДОКУ на С++, задали на курсовую, ничего не получается. В гугле искала, не нашла

Переделать обычное судоку в судоку чёт-нечёт - Delphi
Здравствуйте. Помогите, пожалуйста, переделать обычное судоку 9х9 в судоку чёт-нечёт. Отличие судоку чёт-нечёт заключается в том, что на...

Судоку - Turbo Pascal
Здравствуйте. Можете помочь или подсказать, в реализации и генерации игры &quot;Судоку&quot;.

Судоку си++ - C++
Подскажите пожалуйста как правильно создать таблицу 9*9 для ввода значений?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
06.01.2010, 02:04
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru