SUDOKU, funkcja generująca wypełnioną planszę

0

Witam,
program ma generować planszą SUDOKU a następnie ją sam rozwiązywać. Oczywiście rozwiązanie może być tylko jedno.
Zaczęłam pisanie programu od tego, że chcę wygenerować najpierw całą poprawnie wypełnioną planszę.
Lecę przez wszystkie pola tablicy dwuwymiarowej, dla każdego losuję z przedziału 1-9, i sprawdzam czy to co wylosowałam jest zgodne z zasadami gry, jeśli tak, to przechodzę do następnego pola, jeśli nie to dodaję do wylosowanej 1, i znowu sprawdzam. Robię to tak długo aż sprawdzę wszystkie możliwości dla tego pola i jeśli okaże się, że nic w tym polu nie pasuje, to cofam się do poprzedniego pola i jego wartość zwiększam o 1 i znowu sprawdzam poprawność, ale już nie 9 razy a 8, żeby znowu nie wrzucił mi tam liczby, która pasuje, ale nie daje możliwości dla następnego pola. Tak ogólnie wygląda algorytm.
Program ładnie się kompiluje, ale wywala się zaraz po włączeniu (chociaż nie zawsze, raz na 20 przypadków drukuje ładną planszę). Najprawdopodobniej wywala się wtedy, kiedy funkcja check() zwróci -1. Bardzo proszę o sugestie jak ten kod ulepszyć.
Tutaj podaję kod:
plik.c

#include "plik.h"
#include <stdio.h>
#include <stdlib.h>
int pion(int i, int j, int plansza[][9], int x)//funkcja ktora sprawdza czy w pionie nasza liczba się nie powtarza
{
    for(int k=0; k<9; k++)
    {
        if(k!=i)
        {
            if(plansza[k][j]==x) return 0;//jesli sie powtarza, to zwraca 0
        }
    }
    return 1;//jesli pasuje w pionie, zwraca 1
}

int poziom(int i, int j, int plansza[][9], int x)//funkcja, ktora sprawdza czy liczba pasuje w poziomie
{
    for(int k=0; k<9; k++)
    {
        if(k!=j)
        {
            if(plansza[i][k]==x) return 0;
        }
    }
    return 1;
}

int blok_i(int i)
{
    if(i<=2) return 0;
    else if(i<=5) return 3;
    else return 6;
}

int blok_j(int j)
{
    if(j<=2) return 0;
    else if(j<=5) return 3;
    else return 6;
}

int blok(int i, int j, int plansza[][9], int x)//funkcja ktora oblicza, czy liczba zgadza się w bloku 3x3
{
    for(int k=blok_i(i); k<blok_i(i)+3; k++)
    {
        for(int l=blok_j(j); l<blok_j(j)+3; l++)
        {
            if(k!=i && l!=j)
            {
                if(plansza[k][l]==x) return 0;
            }
        }
    }
    return 1;
}

int check(int a, int b, int c, int z)//funkcja ktora sprawdza czy liczba pasuje(w pionie, poziomie i bloku), zmienna z potrzebna do funkcji wposującej
{
    if(z<9)
    {
        
        if(a==0 || b==0 || c==0) return 0;//jesli nie pasuje w ktoryms przypadku zwraca 0
        else return 1;//jesli pasuje zwraca 1
    }
    else return -1;//jesli z przekroczylo 9
}

int wpisz(int i, int j, int plansza[][9], int x, int z)//funkcja wpisująca
{
    if(i<9)//sprawdzam czy współrzędne nie przekroczyły zakresu tablicy
    {
        if(j<9)
        {
            if(check(pion(i, j, plansza, x), poziom(i, j, plansza, x), blok(i, j, plansza, x), z)==1)//jesli liczba pasuje
            {
                plansza[i][j]=x;// to przypisz wartosc
            }
            else 
            {
                if(check(pion(i, j, plansza, x), poziom(i, j, plansza, x), blok(i, j, plansza, x), z)==0)//jesli sie nie zgadza, ale jeszcze mozna sprawdzac
                {
                    if(x==9)//sprawdzam czy wartosc jest rowna 9
                    {
                        return wpisz(i, j, plansza, 1, z+1);//uruchom od wiekszej wartosci
                    }
                    else return wpisz(i, j, plansza, x+1, z+1);//uruchom od wiekszej wartosci
                }
                else //jak funkcja powie ze juz skonczyla sprawdzac i nie znalazla dobrej wartosci<---tutaj program najprawdopodobniej się wywala
                {
                    if(j==0)//jesli pole jest skrajne z lewej strony
                    {
                        int a=plansza[i-1][8];//wartosc poprzedniego pola jest taka
                        if(a==9)//jesli jest rowna 9
                        {
                            return wpisz(i-1, 8, plansza, 1, 1);//to większa to będzie 1, uruchom wpisywanie dla poprzedniego pola, dla wartosci wiekszej o 1
                        }
                        else return wpisz(i-1, 8, plansza, a+1, 1);//w innym przypadku po prostu zwiększ wartosc
                    }
                    else 
                    {
                        int a=plansza[i][j-1];//jesli pole nie jest skrajne to po prostu weź poprzednie
                        if(a==9)//jesli wartosc poprzedniego pola jest rowna 9
                        {
                            return wpisz(i, j-1, plansza, 1, 1);//to uruchom dla jedynki
                        }
                        else return wpisz(i, j-1, plansza, a+1, 1);//w innym przypadku weź o jeden większy
                    }
                }
            }
            return wpisz(i, j+1, plansza, rand()%9 +1, 0);//uruchom nowe losowanie dla nastepnej wartosci
        }
        return wpisz(i+1, 0, plansza, rand()%9+1, 0);//uruchom dla nastepnej wartosci w nowym rzędzie
    }
    return 0;
}

Z góry dziękuję za pomoc
Pozdrawiam!

0
  1. W tych ifach można się pogubić :-P
  2. Proszę mnie nie bić jak piszę głupoty (dopiero początkujący)
  3. Napisałaś (if z<9)czyli wiemy co się stanie jeśli z będzie większe lub mniejsze od 9. Ale co będzie gdy z == 9? :-) (tak jest w kilku miejscach - a w sudoku jest 9 pól)
  4. Nie próbowałem się temu programowi dokładnie przyglądać (mało czasu akurat) ale wydaje mi się że jeśli zaczynasz od lewego górnego rogu sudoku uzupełniać, to program postępuje ciągle tak samo i w efekcie za każdym razem otrzymujemy to samo sudoku (spróbuj coś z random) :-P

1 użytkowników online, w tym zalogowanych: 0, gości: 1