c语言数独出题程序,我用C语言写解数独程序(一)

我要用C语言写一个解数独题目的程序,从我刚开始接触数独的时候,我就这样告诉自己。记得那是暑假的一天。在家闲来无事,就翻开了以前买的一本

《数独》。从看前面的例题开始,然后自己解第一个题,之后便一发不可收拾。彻彻底底迷上了这9个数字的各种组合变幻。刚好那时有在自学点C语言(说是学习,其实也就是买了几本书看看,上机的时间很少,没条件啊),就想着如果能用C语言写一个解数独的程序那多好啊!那样在同学面前说了N久的“学”编程也能稍稍兑点现了撒。顺便再吹吹牛,得意得意。可是那是自己也就会写

HELLO WORLD

啊(虽然现在也差不多,嘿嘿)。就一直搁浅了这个计划,只是自己天天用笔算,有时候一两个小时都解不出来,但我还是坚持,我喜欢解出题目的成就感,大家是不是都有这样的感觉呢?

直到这个暑假,家里给买了电脑(不容易啊,我盼了N久哩)。就慢慢想着怎么解题了。不过,你知道的。我啥也不会啊,算法,数据结构,都晕着呢。不过我心里还是有一个朦胧的想法,并且相信自己能实现这个想法。关键是跨出那一步。有些事看起来很难,其实只要能跨出第一步,就是成功的一半了。

我跨出了那一步!

我想实现的第一个功能就是数独第一页交给我的解题方法:夹逼法(是不是呢?这个名字书上好像没有明确的定义)。就是3行中有两行都有数字A,然后然后找出没有数字A的那一行再根据列填出数字A.(说的不清楚,呜呜)

还有当我发现一个格子有两个待选的数而现在又不能确定的时候,可以把这两个数字和位置记录下来,等这两个数字其中一个确定,那么另一个也可以确定了。

还有当一行或一列或哪个小九宫格有8个数字的时候,最后一个数字也就可以确定下来了。

还有用夹逼法遍历完9行之后,再遍历9列。方法是把数独翻转90°就可以了。因为这样只要用一个函数来解就可以了。

我只完成了上面这几个功能模块,还好,数独初级的题目能够“秒杀”。

刚看到屏幕输出“解题完成”这几个字的时候,真兴奋,开心。每天熬到半夜总算有些许回报了。

a4c26d1e5885305701be709a3d33442f.png

上面的是题目,下面的解好的题目。不过被顺时针旋转了一下还没转回来的。呵呵。

能帮我写个函数转回来吗?~_~

虽然我算法和数据结构基础都很差。但我还是能依靠自己的小小想象力解决它。

关键是踏出第一步。后续把的程序整理整理。多完成几个模块,它的下一个目标,

“秒杀”中级数独。不过在这之前,我认为我极有必要去好好学点算法和数据结构的知识,

还有多上机敲代码,好记性还不如烂笔头呢.呵呵,我相信我能完成!!!

关于解数独,我觉得关键在于数据。计算机的强项就是操控数据撒

数据的设计

主数组用于保存整个数组的信息:SoDu[10][10] (为计算方便,第一个元素不用,下标刚好可以对应9)

整个题目已经完成的数字数:ach_Number; (为81时就解完题目啦)

保存每个数字填入题目的个数:ach_Times[10] (第一个元素不使用,下标第i个元素值代表数字i已填入多少个。

每行每列每个小九宫格的数据信息:

a) ach_Line [10]; //表示每行已经完成的数字数

b) ach_Row [10]; //没列已经完成的数字数

c) ach_Xiao [10]; //表示每个小九宫格已经完成的数字数

从九行的角度看整个数组题目: ach_LineNum[10][10]; //ach_LineNum[i][j] 若值为1表示第i行的数字 j

已经填入。以此类推,从列的角度来看是 ach_RowNum[10][10];

从每个小九宫格的角度来看是 ach_XiaoNum[10][10].

刚开始我是把这些数据声明成全局变量,但是这不利于函数的抽象,因为需要在多个函数中操作这些变量。所以我把它们并入一个结构体变量,那么只要向函数传递一个指针就可以实现这些数据的操作了。好的,整理一下就是:

struct SoduData{

int SoDu[10][10];

int ach_Times[10];

int ach_Line[10], ach_Row[10] , ach_Xiao[10];

int ach_LineNum[10][10], ach_RowNum[10][10],

ach_XiaoNum[10][10];

int ach_Number;

};

英语不咋地,声明的数据名字奇奇怪怪的。好吧,英语也是重点学习的对象

不过22号有自学考试,我地格填呐。3科全挂都有希望。我都没看的。

临时抱佛脚吧,希望不要挂的太惨。回来之后安心写的程序。C语言!!!

My Name Is 影霖魂

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的用C语言实现的生成有唯一解的数独游戏的程序: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 9 #define COL 9 #define BOX 3 #define EMPTY 0 int board[ROW][COL]; void init_board() { int i, j, k, n; srand(time(NULL)); //设置随机种子 for(i = 0; i < ROW; i++) { for(j = 0; j < COL; j++) { board[i][j] = EMPTY; //初始化为空 } } for(k = 1; k <= 9; k++) //随机填充1~9 { for(n = 1; n <= 10; n++) //每个数字填10次 { i = rand() % ROW; //随机位置 j = rand() % COL; if(board[i][j] == EMPTY && check_valid(i, j, k)) //如果该位置为空且填入该数字不冲突 { board[i][j] = k; //填入该数字 } } } } int check_row(int row, int num) { int j; for(j = 0; j < COL; j++) { if(board[row][j] == num) //如果该行已经有该数字了 return 0; } return 1; } int check_col(int col, int num) { int i; for(i = 0; i < ROW; i++) { if(board[i][col] == num) //如果该已经有该数字了 return 0; } return 1; } int check_box(int row, int col, int num) { int i, j; int r = row - row % BOX; //找到所在宫的左上角坐标 int c = col - col % BOX; for(i = r; i < r + BOX; i++) { for(j = c; j < c + BOX; j++) { if(board[i][j] == num) //如果该宫已经有该数字了 return 0; } } return 1; } int check_valid(int row, int col, int num) { return check_row(row, num) && check_col(col, num) && check_box(row, col, num); //判断该数字是否合法 } int solve_board(int row, int col) { if(row == ROW) //找到一个解 return 1; if(board[row][col] != EMPTY) //该位置已经填过了,跳到下一个位置 { if(col == COL - 1) //该行填完了,跳到下一行的第一个位置 return solve_board(row + 1, 0); else //该行没填完,跳到下一个位置 return solve_board(row, col + 1); } else //该位置没有填过 { int i; for(i = 1; i <= 9; i++) //枚举1~9 { if(check_valid(row, col, i)) //如果该数字合法 { board[row][col] = i; //填入该数字 if(col == COL - 1) //该行填完了,跳到下一行的第一个位置 { if(solve_board(row + 1, 0)) //递归求解下一行 return 1; } else //该行没填完,跳到下一个位置 { if(solve_board(row, col + 1)) //递归求解下一个位置 return 1; } } } board[row][col] = EMPTY; //没有找到合法解,回溯 return 0; } } void remove_numbers(int n) { int i, j; int count = 0; while(count < n) //随机挖去n个数字 { i = rand() % ROW; //随机位置 j = rand() % COL; if(board[i][j] != EMPTY) //如果该位置已经有数字了 { int temp = board[i][j]; //暂时保存该位置的数字 board[i][j] = EMPTY; //挖去该数字 int backup[ROW][COL]; //备份数独 for(int x = 0; x < ROW; x++) { for(int y = 0; y < COL; y++) { backup[x][y] = board[x][y]; } } int count_sol = 0; solve_board(0, 0); //求解数独 for(int x = 0; x < ROW; x++) { for(int y = 0; y < COL; y++) { board[x][y] = backup[x][y]; } } if(count_sol == 1) //如果有唯一解 { count++; //挖去的数字数加1 } else //没有唯一解,还原该位置的数字 { board[i][j] = temp; } } } } void print_board() { int i, j; printf(" -----------------------\n"); for(i = 0; i < ROW; i++) { printf("| "); for(j = 0; j < COL; j++) { if(board[i][j] == EMPTY) printf(". "); else printf("%d ", board[i][j]); if((j+1) % 3 == 0) printf("| "); } printf("\n"); if((i+1) % 3 == 0) printf(" -----------------------\n"); } } int main() { init_board(); //初始化数独 remove_numbers(40); //挖去40个数字 print_board(); //打印数独 return 0; } ``` 程序的主要思路是先随机填充1~9,再用回溯法求解数独,并随机挖去一些数字,直到产生一个唯一解的数独。具体实现细节可以参考代码的注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值