计算数独的小程序-.-

MM中午给了我个数独……俺作了半个小时,眼看时间就要上班了,实在是做不出来了:'(但是自称数独高手的我不能在她面前丢人,思前想后,还是写个程序来吧,节省点时间~

 

大概花了我一个半小时,解决问题……下班后又稍微整理了一下,改成读文件了,但愿对后来人有帮助,不用像我这么狼狈,从头写了:)


#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#define LEN        9
#define SP         3
int g_times = 0;
void init(char data[LEN][LEN], char store[LEN][LEN][LEN])
{
    for(int i = 0; i < LEN; i++)
        for(int j = 0; j < LEN; j++)
            if(data[i][j])
            {
                memset(store[i][j], 0, LEN);
                store[i][j][data[i][j] - 1] = 1;
            }
}
void upstore(char data[LEN][LEN], char store[LEN][LEN][LEN])
{
    for(int i = 0; i < LEN; i++)
    {
        for(int j = 0; j < LEN; j++)
        {
            if(data[i][j] == 0)
                continue;
            /* reset h-line */
            for(int k = 0; k < LEN; k++)
                store[i][k][data[i][j] - 1] = 0;
            /* reset v-line */
            for(int k = 0; k < LEN; k++)
                store[k][j][data[i][j] - 1] = 0;
            /* reset group */
            for(int k = 0; k < SP; k++)
                for(int m = 0; m < SP; m++)
                    store[i / SP * SP + m][j / SP * SP + k][data[i][j] - 1] = 0;
            store[i][j][data[i][j] - 1] = 1;
        }
    }
}
int evolution(char data[LEN][LEN])
{
    char store[LEN][LEN][LEN];
    int t = 0;
    memset(store, 1, LEN * LEN * LEN);
    init(data, store);
    /* evolution the number matrix */
    upstore(data, store);
    /* count the valid one */
    for(int i = 0; i < LEN; i++)
        for(int j = 0; j < LEN; j++)
        {
            int c = 0, p;
            for(int k = 0; k < LEN; k++)
            {
                if(store[i][j][k])
                    p = k;
                c += store[i][j][k];
            }
            if(c == 1)
            {
                t++;
                data[i][j] = p + 1;
            }
            if(c == 0)
                return 0;
        }
    return t;
}
int research(char in[LEN][LEN])
{
    int t = 0, last = -1;
    char data[LEN][LEN];
    char store[LEN][LEN][LEN];
    g_times++;
    memcpy(data, in, LEN * LEN);
    while(t > last)
    {
        last = t;
        t = evolution(data);
    }
    if(t == 0)
        return 0;
    if(t == LEN * LEN)
    {
        memcpy(in, data, LEN * LEN);
        return t;
    }
    memset(store, 1, LEN * LEN * LEN);
    init(data, store);
    upstore(data, store);
    /* t is not LEN * LEN, continue research */
    int min = LEN + 1, li = -1, lj = -1;
    /* find one */
    for(int i = 0; i < LEN; i++)
        for(int j = 0; j < LEN; j++)
        {
            int c = 0, k;
            for(k = 0; k < LEN; k++)
                c += store[i][j][k];
            if(c == 1)/* do not need to research */
                continue;
            if(c < min)
            {
                li = i;
                lj = j;
                min = c;
            }
        }
    if(min == LEN + 1)
        return 0;
    while(min--)
    {
        /* set a possible number */
        int k, p = 0;
        for(k = 0; k < LEN; k++)
            if(store[li][lj][k] == 1)
            {
                if(p == min)
                    break;
                p++;
            }
        data[li][lj] = k + 1;
        /* start research */
        if(LEN * LEN == research(data))
        {
            memcpy(in, data, LEN * LEN);
            return LEN * LEN;
        }
    }
    return 0;
}
void read(char data[LEN][LEN])
{
    FILE* file = fopen(".//in.txt", "r");
    char buffer[(LEN + 1) * 3] = {0};
    if(NULL == file)
        exit(0);
    int i = 0;
    while(fgets(buffer, (LEN + 1) * 3, file))
    {
        int j = 0;
        char* x = strtok(buffer, " ");
        do
        {
            data[i][j++] = atoi(x);
        }
        while(x = strtok(NULL, " "), x);
        i++;
    }
    fclose(file);
}
int main(int argc, char* argv[])
{
    char data[LEN][LEN];
    read(data);
    if(!research(data))
        printf("impossible.\n");
    else
    {
        FILE* file = fopen(".//out.txt", "w+");
        for(int i = 0; i < LEN; i++)
        {
            for(int j = 0; j < LEN; j++)
            {
                fprintf(file, "%d ", data[i][j]);
                printf("%d ", data[i][j]);
            }
            fprintf(file, "\n");
            printf("\n");
        }
        printf("evolution times: %d\n", g_times);
        fprintf(file, "evolution times: %d\n", g_times);
        fclose(file);
    }
    return 0;
}



输入文件:in.txt

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

输出文件:out.txt

1 8 3 5 9 7 6 2 4

5 6 9 4 1 2 3 7 8

2 7 4 8 3 6 9 5 1

7 2 6 9 4 5 1 8 3

3 4 8 2 7 1 5 6 9

9 5 1 6 8 3 7 4 2

4 1 2 7 5 9 8 3 6

6 3 7 1 2 8 4 9 5

8 9 5 3 6 4 2 1 7

evolution times: 35

果然难的变态……居然要猜测35次

 

http://www.sudoku.name/sudoku-solver/cn

 

 

这个上面的解算算法真是有点白痴阿,

0 0 7 0 0 0 0 5 0
0 0 6 0 0 3 0 0 0
0 2 0 0 7 0 0 1 0
0 9 0 0 0 0 3 0 0
4 0 0 0 1 0 0 0 8
0 0 1 9 0 0 0 7 0
0 4 0 0 3 0 0 2 0
0 0 0 7 0 0 6 0 0
0 1 0 0 0 0 8 0 0
居然解算了足足30多秒......

我的解算是0ms......

 

有兴趣的朋友可以稍微改一下程序把上面那个所有的可能情况都打印出来

9 3 7 1 8 4 2 5 6

1 5 6 2 9 3 7 8 4

8 2 4 6 7 5 9 1 3

5 9 8 4 2 7 3 6 1

4 7 2 3 1 6 5 9 8

3 6 1 9 5 8 4 7 2

6 4 5 8 3 9 1 2 7

2 8 9 7 4 1 6 3 5

7 1 3 5 6 2 8 4 9

evolution times: 223


传说中人算需要3天的数独。。

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

很强大,0 秒解出

8 1 2 7 5 3 6 4 9 
9 4 3 6 8 2 1 7 5 
6 7 5 4 9 1 2 8 3 
1 5 4 2 3 7 8 9 6 
3 6 9 8 4 5 7 2 1 
2 8 7 1 6 9 5 3 4 
5 2 1 9 7 4 3 6 8 
4 3 8 5 2 6 9 1 7 
7 9 6 3 1 8 4 5 2 
evolution times: 1762


这个是真变态……1762次啊!!!

这个绝对不是病毒,我自己用visual basic编写的解答数独小程序。。。。不收费哦。。欢迎大家下载使用!! 什么是数独游戏(可以参考百度百科) 数独(すうどく,Sūdoku)是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫内的数字均含1-9,不重复。 独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。 http://baike.baidu.com/subview/961/10842669.htm?fr=aladdin(参考百度百科的内容) 编程的初衷 办公室里忽然开始玩数独了,在百度的文库里下载了几道题,回家玩了几个晚上,挺好玩的,但是苦于没有答案可对,有些题解到最后无解了也不知道是题目错了还是自己解错了。利用出差的闲暇时间,我用visual basic编写了这个小程序。现在和大家分享一下,希望喜欢数独的你可以对对答案。 当然了,有些人说我毁了这个游戏的乐趣。对不起啊,这个东西就是一把双刃剑,看你怎么用了,我的初衷是对答案,不是偷懒。。。 使用注意事项 1)网格里可以用左右上下键控制光标 2)程序库里一共128道题,均来源于网络。您也可以手动输入数独题目求解 3)本程序免费提供给你,如果因此造成您机器的死机等等概不负责!(万亿分之一的概率,但是我怕遇到流氓额我啊!) 4)程序里有我的email地址,有疑问的可以email我,嘿嘿。 5)我要保留我的版权,未经允许不得转载,不得用于商业用途 6)不得将我的程序重新发布并且打包设置权限骗取注册,本来及时免费的,否则法庭见! 7)要源代码的就省省吧。嘻嘻。给你一条鱼,你就不要管钓到的方法了!!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值