game.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include "sudoku.h"
  5. int allowbits[Brdsize] = {
  6. 0x00100,
  7. 0x00200,
  8. 0x00400,
  9. 0x00800,
  10. 0x01000,
  11. 0x02000,
  12. 0x04000,
  13. 0x08000,
  14. 0x10000
  15. };
  16. int boxind[Brdsize][Brdsize] = {
  17. {0,1,2,9,10,11,18,19,20},
  18. {3,4,5,12,13,14,21,22,23},
  19. {6,7,8,15,16,17,24,25,26},
  20. {27,28,29,36,37,38,45,46,47},
  21. {30,31,32,39,40,41,48,49,50},
  22. {33,34,35,42,43,44,51,52,53},
  23. {54,55,56,63,64,65,72,73,74},
  24. {57,58,59,66,67,68,75,76,77},
  25. {60,61,62,69,70,71,78,79,80},
  26. };
  27. int colind[Brdsize][Brdsize] = {
  28. {0,9,18,27,36,45,54,63,72},
  29. {1,10,19,28,37,46,55,64,73},
  30. {2,11,20,29,38,47,56,65,74},
  31. {3,12,21,30,39,48,57,66,75},
  32. {4,13,22,31,40,49,58,67,76},
  33. {5,14,23,32,41,50,59,68,77},
  34. {6,15,24,33,42,51,60,69,78},
  35. {7,16,25,34,43,52,61,70,79},
  36. {8,17,26,35,44,53,62,71,80},
  37. };
  38. int rowind[Brdsize][Brdsize] = {
  39. {0,1,2,3,4,5,6,7,8},
  40. {9,10,11,12,13,14,15,16,17},
  41. {18,19,20,21,22,23,24,25,26},
  42. {27,28,29,30,31,32,33,34,35},
  43. {36,37,38,39,40,41,42,43,44},
  44. {45,46,47,48,49,50,51,52,53},
  45. {54,55,56,57,58,59,60,61,62},
  46. {63,64,65,66,67,68,69,70,71},
  47. {72,73,74,75,76,77,78,79,80},
  48. };
  49. static int maxlevel;
  50. static int solved;
  51. void
  52. printbrd(int *board)
  53. {
  54. int i;
  55. for(i = 0; i < Psize; i++) {
  56. if(i > 0 && i % Brdsize == 0)
  57. print("\n");
  58. print("%2.2d ", board[i] & Digit);
  59. }
  60. print("\n");
  61. }
  62. int
  63. getrow(int cell)
  64. {
  65. return cell/9;
  66. }
  67. int
  68. getcol(int cell)
  69. {
  70. return cell%9;
  71. }
  72. int
  73. getbox(int cell)
  74. {
  75. int row = getrow(cell);
  76. int col = getcol(cell);
  77. return 3*(row/3)+ col/3;
  78. }
  79. void
  80. setdigit(int cc, int num)
  81. {
  82. board[cc] = (board[cc] & ~Digit) | num;
  83. }
  84. int
  85. boxcheck(int *board)
  86. {
  87. int i,j,d,sum,last,last2;
  88. for (i = 0; i < 9; i++) {
  89. for (d = 0;d < 9; d++) {
  90. sum=0;
  91. last=-1;
  92. last2=-1;
  93. for (j = 0; j < 9; j++) {
  94. if (board[boxind[i][j]] & allowbits[d]) {
  95. sum++;
  96. last2=last;
  97. last=boxind[i][j];
  98. } else
  99. sum += ((board[boxind[i][j]] & Solve)==(d << 4)) ? 1: 0;
  100. }
  101. if (sum==0)
  102. return(0);
  103. if ((sum==1)&&(last>=0))
  104. if (!setallowed(board,last,d))
  105. return(0);
  106. if((sum == 2) && (last >= 0) && ( last2 >= 0) &&
  107. (getrow(last) == getrow(last2))) {
  108. for (j = 0; j < 9; j++) {
  109. int c = rowind[getrow(last)][j];
  110. if ((c != last)&&(c != last2)) {
  111. if (board[c] & allowbits[d]) {
  112. board[c] &= ~allowbits[d];
  113. if ((board[c] & Allow)==0)
  114. return(0);
  115. }
  116. }
  117. }
  118. }
  119. if((sum == 2) && (last >= 0) && (last2 >= 0) &&
  120. (getcol(last) == getcol(last2))) {
  121. for (j = 0;j <9;j++) {
  122. int c = colind[getcol(last)][j];
  123. if ((c != last) && (c != last2)) {
  124. if (board[c] & allowbits[d]) {
  125. board[c] &= ~allowbits[d];
  126. if ((board[c] & Allow) == 0)
  127. return(0);
  128. }
  129. }
  130. }
  131. }
  132. }
  133. }
  134. return(1);
  135. }
  136. int
  137. rowcheck(int *board)
  138. {
  139. int i,j,d,sum,last;
  140. for (i = 0; i < 9; i++) {
  141. for (d = 0; d < 9; d++) {
  142. sum = 0;
  143. last = -1;
  144. for (j = 0; j <9 ; j++) {
  145. if (board[rowind[i][j]] & allowbits[d]) {
  146. sum++;
  147. last = j;
  148. } else
  149. sum += ((board[rowind[i][j]] & Solve) == (d << 4)) ? 1: 0;
  150. }
  151. if (sum == 0)
  152. return(0);
  153. if ((sum == 1) && (last >= 0)) {
  154. if (!setallowed(board, rowind[i][last], d))
  155. return(0);
  156. }
  157. }
  158. }
  159. return(1);
  160. }
  161. int
  162. colcheck(int *board)
  163. {
  164. int i,j,d,sum,last;
  165. for (i = 0; i < 9; i++) {
  166. for (d = 0; d < 9; d++) {
  167. sum = 0;
  168. last = -1;
  169. for (j = 0;j < 9;j++) {
  170. if (board[colind[i][j]] & allowbits[d]) {
  171. sum++;
  172. last = j;
  173. } else
  174. sum += ((board[colind[i][j]] & Solve) == (d << 4)) ? 1: 0;
  175. }
  176. if (sum == 0)
  177. return(0);
  178. if ((sum == 1) && (last >= 0)) {
  179. if (!setallowed(board, colind[i][last], d))
  180. return(0);
  181. }
  182. }
  183. }
  184. return(1);
  185. }
  186. int
  187. setallowed(int *board, int cc, int num)
  188. {
  189. int j, d;
  190. int row, col, box;
  191. board[cc] &= ~Allow;
  192. board[cc] = (board[cc] & ~Solve) | (num << 4);
  193. row = getrow(cc);
  194. for (j = 0; j < 9; j++) {
  195. if (board[rowind[row][j]] & allowbits[num]) {
  196. board[rowind[row][j]] &= ~allowbits[num];
  197. if ((board[rowind[row][j]] & Allow) == 0)
  198. return(0);
  199. }
  200. }
  201. col = getcol(cc);
  202. for (j = 0; j < 9; j++) {
  203. if (board[colind[col][j]] & allowbits[num]) {
  204. board[colind[col][j]] &= ~allowbits[num];
  205. if ((board[colind[col][j]] & Allow) == 0)
  206. return(0);
  207. }
  208. }
  209. box = getbox(cc);
  210. for (j = 0;j < 9;j++) {
  211. if (board[boxind[box][j]] & allowbits[num]) {
  212. board[boxind[box][j]] &= ~allowbits[num];
  213. if ((board[boxind[box][j]] & Allow)==0)
  214. return(0);
  215. }
  216. }
  217. for (j = 0;j < 81; j++)
  218. for (d = 0; d < 9; d++)
  219. if ((board[j] & Allow) == allowbits[d])
  220. if (!setallowed(board, j, d))
  221. return(0);
  222. if (!boxcheck(board)||!rowcheck(board)||!colcheck(board))
  223. return(0);
  224. for (j = 0; j < 81; j++)
  225. for (d = 0; d < 9; d++)
  226. if ((board[j] & Allow) == allowbits[d])
  227. if (!setallowed(board, j, d))
  228. return(0);
  229. return(1);
  230. }
  231. int
  232. chksolved(int *board)
  233. {
  234. int i;
  235. for (i = 0; i < Psize; i++)
  236. if ((board[i] & Allow) != 0)
  237. return 0;
  238. solved = 1;
  239. return solved;
  240. }
  241. int
  242. findmove(int *board)
  243. {
  244. int i, d;
  245. int s;
  246. s = nrand(Psize);
  247. for (i=(s+1)%81;i!=s;i=(i+1)%81) {
  248. if (!(board[i] & Allow)) {
  249. d=(board[i] & Solve) >> 4;
  250. if ((board[i] & Digit)!=d)
  251. return(i);
  252. }
  253. }
  254. return(-1);
  255. }
  256. void
  257. attempt(int *pboard, int level)
  258. {
  259. int tb[Psize];
  260. int i, j, k;
  261. int s, e;
  262. if (level > maxlevel)
  263. maxlevel = level;
  264. if (level > 25)
  265. exits("level"); /* too much */
  266. s = nrand(Psize);
  267. for (i = (s + 1) % Psize; i != s; i = (i + 1) % Psize) {
  268. if ((pboard[i] & Allow) != 0) {
  269. e=nrand(9);
  270. for (j = (e + 1) % 9; j != e; j = (j + 1) % 9) {
  271. if (pboard[i] & allowbits[j]) {
  272. for (k = 0; k < Psize; k++)
  273. tb[k] = pboard[k];
  274. if (setallowed(tb, i, j)) {
  275. tb[i] = (tb[i] & ~Digit) | j;
  276. if (chksolved(tb)) {
  277. for (k = 0;k < Psize; k++)
  278. pboard[k] = tb[k];
  279. return; /* bad! */
  280. }
  281. attempt(tb, level + 1);
  282. if (chksolved(tb)) {
  283. for (k = 0; k < Psize; k++)
  284. pboard[k] = tb[k];
  285. return;
  286. }
  287. tb[i] |= Digit;
  288. if (level > 25)
  289. return;
  290. }
  291. }
  292. }
  293. }
  294. }
  295. }
  296. void
  297. solve(void)
  298. {
  299. int pboard[Psize];
  300. int i, c;
  301. if (!solved) {
  302. for (i = 0; i < Psize; i++)
  303. pboard[i] = Allow | Solve | Digit;
  304. for (i = 0; i < Psize; i++) {
  305. c = board[i] & Digit;
  306. if ((0 <= c) && (c < 9)) {
  307. if (!setallowed(pboard,i,c)) {
  308. print("starting position impossible... failed at cell %d char: %d\n", i, c + 1);
  309. return;
  310. }
  311. }
  312. }
  313. attempt(pboard,0);
  314. for (i = 0; i < Psize; i++)
  315. board[i] = (board[i] & ~Solve) | (pboard[i] & Solve);
  316. }
  317. }
  318. int
  319. checklegal(int cc, int d)
  320. {
  321. int hold = board[cc];
  322. int j, row, col, box;
  323. board[cc] |= Digit;
  324. row = getrow(cc);
  325. for (j = 0; j < Brdsize; j++)
  326. if ((board[rowind[row][j]] & Digit) == d) {
  327. board[cc] = hold;
  328. return(0);
  329. }
  330. col = getcol(cc);
  331. for (j = 0; j < Brdsize; j++)
  332. if ((board[colind[col][j]] & Digit) == d) {
  333. board[cc] = hold;
  334. return(0);
  335. }
  336. box = getbox(cc);
  337. for (j = 0; j < Brdsize; j++)
  338. if ((board[boxind[box][j]] & Digit) == d) {
  339. board[cc] = hold;
  340. return(0);
  341. }
  342. board[cc]=hold;
  343. return(1);
  344. }
  345. void
  346. clearp(void)
  347. {
  348. int i;
  349. for(i = 0; i < Psize; i++) {
  350. board[i] = (Allow | Solve | Digit);
  351. }
  352. solved = 0;
  353. }
  354. void
  355. makep(void)
  356. {
  357. int i,d;
  358. do {
  359. clearp();
  360. maxlevel=0;
  361. for (d = 0; d < Brdsize; d++) {
  362. i = nrand(Psize);
  363. if (board[i] & allowbits[d]) {
  364. setallowed(board, i, d);
  365. board[i] = (board[i] & ~Digit) | d;
  366. }
  367. }
  368. attempt(board, 0);
  369. for (i = 0; i < Psize; i++) {
  370. if ((0 <= (board[i] & Digit)) && ((board[i] & Digit) < 9))
  371. board[i] |= MLock;
  372. setdigit(i, board[i] & Digit);
  373. }
  374. if (!solved) {
  375. fprint(2, "failed to make puzzle\n");
  376. exits("failed to make puzzle");
  377. }
  378. } while (!solved);
  379. }