본문 바로가기

프로그래밍/C-CPP

[C] 4x4 수도쿠 코드

반응형
// sudoku4x4.cpp : Defines the entry point for the console application.
//
//

#include "stdafx.h"
#include <stdlib.h>
#include <memory.h>
int g_num_solutions = 0;
void find_sudoku_pan(int *pan);

//
// 최초의 판 모양은
//
//  01--
//  23--
//  ----
//  ----

void init_pan(int *pan)
{

    for (int i = 0; i < 16; i++)
        *(pan + i) = -1;

    *(pan + 4 * 0 + 0) = 0; // [0][0]
    *(pan + 4 * 0 + 1) = 1; // [0][1]
    *(pan + 4 * 1 + 0) = 2; // [1][0]
    *(pan + 4 * 1 + 1) = 3; // [1][1]
}

void print_pan(int *pan)
{
    char symbols[5] = "/!#O";

    printf("\nBelow is the %d%s 2x2 sudoku solution.", g_num_solutions,
           (g_num_solutions == 1) ? "st" : (g_num_solutions == 2) ? "nd"
                                       : (g_num_solutions == 3)   ? "rd"
                                                                  : "th");

    for (int i = 0; i < 16; i++)
    {
        if (i % 4 == 0)
            printf("\n");
        printf(" %c", symbols[*(pan + i)]);
    }
    printf("\n===============\n");
}

// pan의 pos번쩨 자리([pos/4][pos%4])에 ele가 들어올 수 있나?

bool is_value_acceptable(int *pan, int ele, int pos)
{
    int row = pos / 4, col = pos % 4;

#if 0     
    print_pan(pan);     
    printf("Is %d in (%d,%d) = %d acceptable? :", ele, row, col, pos);
#endif
    for (int i = 0; i < 4; i++)
    {
        // 열에서 같은 게 있는지?
        if (*(pan + 4 * row + i) == ele)
        {
            // printf("pan[%d][%d] == ele --> false", row, i);
            return false;
        }

        // 행에서 같은 게 있는지?
        if (*(pan + 4 * i + col) == ele)
        {
            // printf("pan[%d][%d] == ele --> false", i, col);
            return false;
        }
    }

    return *(pan + 4 * (2 * (row / 2)) + 2 * (col / 2) + 0) != ele &&
           *(pan + 4 * (2 * (row / 2)) + 2 * (col / 2) + 1) != ele &&
           *(pan + 4 * (2 * (row / 2) + 1) + 2 * (col / 2)) != ele &&
           *(pan + 4 * (2 * (row / 2) + 1) + 2 * (col / 2) + 1) != ele;
}

void branch_pan(int *pan, int ele, int pos)
{
    int *new_pan;
    
    new_pan = (int *)malloc(16 * sizeof(int));
    memcpy(new_pan, pan, 16 * sizeof(int));
    *(new_pan + pos) = ele;
    find_sudoku_pan(new_pan);
}

void find_sudoku_pan(int *pan)
{
    int i;
    for (i = 0; i < 16; i++)
        if (*(pan + i) == -1)
            break;

    if (i == 16)
    {
        g_num_solutions++;
        print_pan(pan);
        free(pan);
        return;
    }

    for (int j = 0; j < 4; j++)
        if (is_value_acceptable(pan, j, i))
            branch_pan(pan, j, i);
}

int main(int argc, char *argv[])
{
    int *pan; // 4x4 수도쿠 판

    pan = (int *)malloc(16 * sizeof(int));

    init_pan(pan);

    //  print_pan(pan);
    find_sudoku_pan(pan);
    return 0;
}

1234(위 소스에서는 0123)이라는 기호는 서로 바뀌어도 상관이 없으므로, 최초의 2x2블럭에 들어가는 수를 고정시켜 놓고 어떤 패턴들이 나올지 궁금했다.

728x90