NTUEE113HW 板


LINE

就是呢 王凡班的project不是要用redlib来写吗 然後它的用法还真的是颇有趣... 我个人看了满久之後 大概理解出个大概了 底下这个是教授给我们的资料中 解一个9x9的数独的code 我加了一些可有可无的注解 如果有兴趣又不嫌我嘴炮的 就看看呗~ sudoku.c ---------------------------------------- /* 这个是为了让这个程式比较好懂,所做的一些注解。当然,我的希望只是让 它比较好懂,所以如果我表达能力不佳或者其它因素,让你觉得不是很有帮 助的话,就不要看吧,毕竟我也只是推想出它可能的意思而已。也因为这个 原因,里面很多地方可能都有错,所以请各位选择性的采信呗:) 另外一个想说的是,这是用C写出来的,所以有很多跟C++很像的地方,可是 有些地方又会有很大差别,所以自行小心呗~~不过除了印东西的时候,不用 cout而用fprintf(输出的地方, "要印的字串",变数)外,基本上其它不会太 麻烦(吧)。有关语法的可以去GOOGLE找,找printf这个函数来看应该会有帮 助。 另外,里面很多地方是有关图论的部份,至於图的性质也不是很容易说的 (因为要画图才能解释),所以如果觉得不太好懂的话,那就多讨论吧~~ 最後我个人建议大家,不要用Dev-Cpp 来写程式。既然最後是要在linux上 compile的,那麽用 Dev-Cpp写也不会比用记事本好... 私心推荐Notepad++ 好用~真的~ 2010/05/02,by Helicoid */ //这两行是写C的时候很重要的 //就当作习惯的直接加上去呗 #include <stdio.h> #include <stdlib.h> //下两行顺序不能对调,不然会有满满的错误 #include "redlib.h" #include "redlib.e" char *s[9][9]; int count_print = 0; //redgram是一个资料型别,而这三行的意思等於是 //redgram slot_constraint(redgram d, int i, int j) 其实只是个函数 redgram slot_constraint(d, i, j) redgram d; int i, j; { // 宣告有的没的 int value, h, k, nc, ac, gs; redgram conj; //value从1到9,h从0到8,来看它要做什麽 for(value =1; value <= 9; value++) { for (h = 0; h < 9; h++){ if (h != i) { //底下这个式子是因为,在9x9的数独里,同一行当然不能同时是某个数字啦~ //例如说,当value=3时,第i列j行和 第h列j行是不能同时等於3的 //所以画一个图表示要避开这种事 conj = red_diagram("~(%s==%d && %s==%d)", s[i][j], value, s[h][j], value ); //底下可以暂时不看,反正就是跟输出有关的东西 //倒是有一点值得注意,RED_OUT这个东西似乎跟输出有关 //它的意义大家想想吧(我不知道XD) if ((++count_print) < 100 &&(gs=red_diagram_size(d, &nc, &ac))<30){ fprintf(RED_OUT, "\nMutual exclusion to value:%1d at %s and %s:\nconstraint:\n", value, s[i][j], s[h][j] ); red_print_line(conj); fprintf(RED_OUT, "\n"); red_print_diagram(conj); fprintf(RED_OUT, "input diagram:\n"); red_print_line(d); fprintf(RED_OUT, "\n"); red_print_diagram(d); } //下面这行是重点!!表示把刚刚的"同一行不能同时是某个数字" //这点加到原本的redgram中,而且是AND //(因为正确的图形要同时满足所有的限制!) d = red_and(d, conj); //再来也可以暂时不要看 if (count_print < 100 && gs < 30) { fprintf(RED_OUT, "result diagram:\n"); red_print_line(d); fprintf(RED_OUT, "\n"); red_print_diagram(d); } /* fprintf(RED_OUT,"%s && %s, after one conjunction.\n",s[i][j],s[h][j]); red_print_graph(d); fprintf(RED_OUT, "\n"); fflush(RED_OUT); */ //接下来的概念完全一样,就是说如果同在一个3x3的小正方形内 //那麽数字不能同时等於某个value //稍微看一下,画出一个数独的形状再比一比,应该比较好理解 if ((h/3) == (i/3)) { for (k = 0; k < 9; k++) { if ((k/3)==(j/3) && (k!=j)) { d = red_and(d, red_diagram("~(%s==%d && %s==%d)", s[i][j], value, s[h][k], value ) ); /* fprintf(RED_OUT,"%s && %s, after one conjunction.\n",s[i][j],s[h][k]); red_print_graph(d); fprintf(RED_OUT, "\n"); fflush(RED_OUT); */ } } } } //一样的概念第三次出现(也是最後一次了) //同样的一列里面,任两格是不能同时为相同的数字的~ if (h != j) { d = red_and(d, red_diagram("~(%s==%d && %s==%d)", s[i][j], value, s[i][h], value ) ); /* fprintf(RED_OUT, "%s && %s, after one conjunction.\n", s[i][j], s[i][h]); red_print_graph(d); fprintf(RED_OUT, "\n"); fflush(RED_OUT); */ } } } //复习一下刚刚做了什麽事 //就是,一个正常的数独的限制条件 //1.一行里面有1~9<=>任何两格数字不同 //2.一列里面有1~9<=>任何两格数字不同 //3.一个3x3小方格里面有1~9<=>任何两格数字不同 //重点是都用到了red_and这个函数,他是这个程式的主角 //接下来的我是用猜的啦...不太确定 //把d在堆叠的号码找出来,然後标记一下不要被清掉 h = red_push(d); //清掉用过的垃圾图表(狡兔死走狗烹的道理吧...) red_garbage_collect(RED_GARBAGE_SILENT); //把d给挤出来(?) red_pop(h); //传回加了料之後的图表d return(d); } /* slot_constraint() */ //以上slot_constraint函数告一段落 //这两行只是定义了东西而已 #define FLAG_MULTIPLE 1 #define FLAG_SINGLE 0 //以下为main函数 main(argc, argv) int argc; char **argv; { //宣告有的没的 char a, *start, *condition, *p; redgram sol, cube; int i, j, k, u, v, h, m, c[9][9], lb[9][9], ub[9][9], flag; char stop[30]; FILE *datafile; //argc是用终端机(类似cmd)的时候,输入的变数数目 //例如说,当我们打"程式名 输入档名"时,argc就会是2 //然後argv[0]="程式名" argv[1]="输入档名" //所以... 就会有底下的两个if if (argc < 2) { printf("Input file for sudoko not specified!\n"); exit(0); } datafile = fopen(argv[1], "r"); if (datafile == NULL) { printf("Can't open the data file of sudoko!! \n"); exit(0); } //一些REDLIB所需的架构 //RED_input_file("sample.d"); red_begin_session(RED_SYSTEM_UNTIMED, "sudoku", 2); red_begin_declaration(); /* each process for a row on the board. */ //REDLIB所用的变数要有个名子,所以就跑个for跑出一大堆名子 //(因为REDLIB跟C的变数是不一样的,所以光是给名子就有点麻烦) //後面的 red_declare_variable, //(我觉得)是宣告d00,d01,d02,...,d87,d88都是1到9的离散变数 //(因为数独上面不会有7.4或者 2π之类的东东吧) for (i = 0; i < 9; i++) { for (j = 0; j < 9; j++) { s[i][j] = malloc(4); sprintf(s[i][j], "d%1d%1d", i, j); red_declare_variable(RED_TYPE_DISCRETE, 1, 9, "%s", s[i][j]); } } //REDLIB所需的架构 red_end_declaration(RED_NO_REFINED_GLOBAL_INVARIANCE); /* How to access a variable ? */ //RED_print_variables(); //RED_print_xtions(); //RED_verify(); /* Declaration of the 81 slot variable indices as a 9X9 arrays. * Note this is not for the array of slot variable values. * This is only for the slot variable indices. */ do { /* After the completion of the loop, sol should be the MBDD+CRD * that records the solutions to your input board specification. * Initially, we set sol to TRUE. */ //sol是整个程式的主要图表,一开始我们让它恒真(总不能一开始就错了吧...) sol = red_true(); /* Please fill in the code here to calculate the solution for * the given sudoko puzzle. * The details of the main processing body, that you should fill in, include: 1. Read in the values of those given slots on the board and construct the logic formula with the REDLIB procedures. 2. Iteratively restrict the formula you got in step 1 with all the sudoko rules. Now start filling in the main processing body in the following. |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ for (i = 0; i < 9; i++){ for (j = 0; j < 9; j++){ //读取数字(不过用char的方式存 ) //读到换行就丢了再读 a = getc(datafile); if (a == '\n') a = getc(datafile); //把读到的字元换成字串 sprintf(stop, "%c\0", a); //把字串换成数字,用atoi这个有趣函数 c[i][j] = atoi(stop); if (c[i][j] != 0) { //如果读到非零值,就要加上"某位置=读到的某数"这个限制条件 //一样,用到的是red_and sol = red_and(sol, red_diagram("%s==%d", s[i][j], c[i][j])); //把这个东西拿去做前面的函数 sol = slot_constraint(sol, i, j); } } } //因为我们可以发现,不管那格的数字是不是被决定了 //它都应该要拿去做slot_constraint //所以我们对漏网之鱼拿去做 slot_constraint //(个人认为(纯猜测)如此安排是效率因素) for(i = 0; i < 9; i++) { for(j = 0; j < 9; j++) { if (c[i][j] == 0) sol = slot_constraint(sol, i, j); } } /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| After the main processing body of the loop, * we are now ready to print out the solution board specification. * We do this in two ways. * In the first way, we print the board as a 9X9 char array. * We do this by first invoking the depth-first traversing procedure * red_process_DFS() for MBDD+CRD. * For each node in the MBDD+CRD, red_process_DFS() process the * node with procedure max_rec() and each arc of the node with * procedure arc_noop(). * * In the second way, we print the MBDD+CRD of sol as a single-line * Boolean formula. */ /* red_print_diagram(sol); */ //似乎是要算总解数的样子 //(小声说)但是这个算到的数字跟印出来的都不一样...这条函数似乎... i = red_diagram_discrete_model_count(sol); //印出来呗 switch (i) { case 0: fprintf(RED_OUT, "\nNo solutions!\n"); break; case 1: fprintf(RED_OUT, "\nOnly 1 solution\n"); break; default: fprintf(RED_OUT, "\nTotal %1d solutions!\n", i); break; } //接下来的我不太懂... //不过,可以理解为就是纯粹的印出吧 //既然是印出,参数改一改要印出别的东西应该也是可行的 cube = red_first_cube(sol); for (; cube != red_false(); cube = red_next_cube(sol)) { fprintf(RED_OUT, "\n\nOne solution:\n"); flag = FLAG_SINGLE; for (i = 0; i < 9; i++) { for (j = 0; j < 9; j++) { red_get_cube_discrete_value( cube, s[i][j], &(lb[i][j]), &(ub[i][j]) ); if (lb[i][j] < ub[i][j]) flag = FLAG_MULTIPLE; fprintf(RED_OUT, "%1d", lb[i][j]); } fprintf(RED_OUT, "\n"); } if (flag != FLAG_MULTIPLE) continue; fprintf(RED_OUT, "\n\nOne more solution:\n"); for (i = 0; i < 9; i++) { for (j = 0; j < 9; j++) { fprintf(RED_OUT, "%1d", ub[i][j]); } fprintf(RED_OUT, "\n"); } fprintf(RED_OUT, "\n"); } fprintf(RED_OUT, "\n-----------------------------------------------\n"); // red_print_line(sol); // fprintf(RED_OUT, "\nsolution diagram:\n"); // red_print_diagram(sol); break; } //如果先前抓到档案结束之类的,会跳出吧 //不过说实在的我不清楚这整个do while的运作方式 while( strcmp(fgets(stop, 30, datafile), "end") != 0 && strcmp(fgets(stop, 30, datafile), "END") != 0 ); //结束了~收个尾,记得关档 red_end_session(); fclose(datafile); } /* main() */ //一个满奇怪的地方是,记得最最後面留一行空行 //不然用linux来compile的时候会有意见(不要问我为什麽) --------------------------------------------- 大概是这样吧 我把它修剪成刚好贴在一般看B的宽度了 觉得在这边看不清楚的人(应该是每个人吧= =) 把它复制到文字编辑器里 不然就... http://www.badongo.com/file/22378576 里面有.c档~ 嗯嗯 後来我(以为)有写出教授要的code啦 放了几个输入档还没有错(只是跑很慢,慢到差点以为系计中电脑当了) 那就祝王凡班的各位都写出来呗~ 我该回去写普物报告了@@ --



※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.112.241.41
1F:→ cktigeryang:Dev-C++内建就是用gcc来编译的,跟在linux下是一样的 05/02 17:05
2F:→ cktigeryang:只是平台不一样而已(如果只用standard函式库的话) 05/02 17:07
3F:→ Helicoid:是哦 我都傻傻拿到系工作站compile...XD 05/02 17:20
4F:推 victoret:有神快拜啊!!! 05/02 18:29
5F:推 xup65p4:强者 05/02 19:07
6F:推 schimtag168:快收 05/02 21:27
7F:推 LouisJC:大公无私阿~~ 05/03 11:50
8F:推 johnjohnlin:#1BpV8-fs (Linux) 这好像有讲到结尾换行问题的说 05/04 17:07
9F:→ Helicoid:哦 真的耶~ 感谢楼上~ 05/05 06:25
10F:推 tomap41017:真的太感动了XD 05/05 22:14







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP