fork download
  1. /* 15 puzzle */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <time.h>
  7.  
  8. typedef enum _Boolean { False = 0, True = -1 } Boolean;
  9.  
  10. Boolean confirm(char const *msg) {
  11. char str[256];
  12. for (;;) {
  13. if (msg != NULL) {
  14. printf(msg);
  15. }
  16. printf(" [y/n]? ");
  17. fgets(str, 256, stdin);
  18. str[0] = tolower(str[0]);
  19. if (str[0] == 'y') {
  20. return True;
  21. } else if (str[0] == 'n') {
  22. return False;
  23. }
  24. }
  25. }
  26.  
  27. void initPuzzle(int puzzle[4][4]) {
  28. int i, j, n = 1;
  29. for (i = 0; i < 4; i++) {
  30. for (j = 0; j < 4; j++) {
  31. puzzle[i][j] = n & 0xF;
  32. n++;
  33. }
  34. }
  35. }
  36.  
  37. Boolean checkPuzzle(int const puzzle[4][4]) {
  38. int i, j, n = 1;
  39. for (i = 0; i < 4; i++) {
  40. for (j = 0; j < 4; j++) {
  41. if (puzzle[i][j] != (n & 0xF)) {
  42. return False;
  43. }
  44. n++;
  45. }
  46. }
  47. return True;
  48. }
  49.  
  50. int movePanels(int puzzle[4][4], int const number) {
  51. int xs = -1, ys = -1, xn = -2, yn = -2;
  52. int i, j, m;
  53. for (i = 0; i < 4; i++) {
  54. for (j = 0; j < 4; j++) {
  55. if (puzzle[i][j] == number) {
  56. xn = j;
  57. yn = i;
  58. } else if (puzzle[i][j] == 0) {
  59. xs = j;
  60. ys = i;
  61. }
  62. }
  63. }
  64. if (xs != xn && ys != yn) {
  65. return 0;
  66. }
  67. if (xs > xn) {
  68. for (j = xs; j > xn; j--) {
  69. puzzle[ys][j] = puzzle[ys][j - 1];
  70. }
  71. m = xs - xn;
  72. } else if (xs < xn) {
  73. for (j = xs; j < xn; j++) {
  74. puzzle[ys][j] = puzzle[ys][j + 1];
  75. }
  76. m = xn - xs;
  77. } else if (ys > yn) {
  78. for (i = ys; i > yn; i--) {
  79. puzzle[i][xs] = puzzle[i - 1][xs];
  80. }
  81. m = ys - yn;
  82. } else /* if (ys < yn) */ {
  83. for (i = ys; i < yn; i++) {
  84. puzzle[i][xs] = puzzle[i + 1][xs];
  85. }
  86. m = yn - ys;
  87. }
  88. puzzle[yn][xn] = 0;
  89. return m;
  90. }
  91.  
  92. void shuffle(int puzzle[4][4], int const times) {
  93. int i, j, t;
  94. int xs, ys;
  95. int p, k = 0;
  96.  
  97. for (t = 0; t < times; t++) {
  98.  
  99. for (i = 0; i < 4; i++) {
  100. for (j = 0; j < 4; j++) {
  101. if (puzzle[i][j] == 0) {
  102. xs = j;
  103. ys = i;
  104. goto loopescape;
  105. }
  106. }
  107. }
  108. loopescape:
  109.  
  110. p = rand() % 3;
  111.  
  112. if (k == 0) {
  113. for (i = 0; i < 4; i++) {
  114. if (puzzle[i][xs] == 0) {
  115. continue;
  116. }
  117. if (p == 0) {
  118. movePanels(puzzle, puzzle[i][xs]);
  119. break;
  120. } else {
  121. p--;
  122. }
  123. }
  124. } else {
  125. for (j = 0; j < 4; j++) {
  126. if (puzzle[ys][j] == 0) {
  127. continue;
  128. }
  129. if (p == 0) {
  130. movePanels(puzzle, puzzle[ys][j]);
  131. break;
  132. } else {
  133. p--;
  134. }
  135. }
  136. }
  137. k = !k;
  138. }
  139. }
  140.  
  141. void printPuzzle(int const puzzle[4][4]) {
  142. int i, j;
  143. for (i = 0; i < 4; i++) {
  144. for (j = 0; j < 4; j++) {
  145. if (j > 0) {
  146. putchar(' ');
  147. }
  148. if (puzzle[i][j] > 0) {
  149. printf("%2d", puzzle[i][j]);
  150. } else {
  151. putchar(' ');
  152. putchar('*');
  153. }
  154. }
  155. putchar('\n');
  156. }
  157. }
  158.  
  159. Boolean game(void) {
  160. Boolean complete = False;
  161. int n, p, t, m;
  162. int puzzle[4][4];
  163. char str[256];
  164.  
  165. initPuzzle(puzzle);
  166.  
  167. shuffle(puzzle, 1000);
  168.  
  169. t = 0;
  170.  
  171. for (;;) {
  172.  
  173. loophead:
  174.  
  175. printf("---------------------- %d moves\n", t);
  176. printPuzzle(puzzle);
  177. printf("move number [1-15]? ");
  178. fgets(str, 256, stdin);
  179.  
  180. for (p = 0; isprint(str[p]); p++) {
  181. if (!isdigit(str[p])) {
  182. if (confirm("do you give up") == True) {
  183. puts("gave up");
  184. goto gameend;
  185. } else {
  186. goto loophead;
  187. }
  188. }
  189. }
  190.  
  191. if (strlen(str) > 3) {
  192. puts("illegal number");
  193. continue;
  194. }
  195.  
  196. n = atoi(str);
  197.  
  198. m = movePanels(puzzle, n);
  199.  
  200. if (m == 0) {
  201. if (n > 0 && n < 16) {
  202. puts("cannot move");
  203. } else {
  204. puts("illegal number");
  205. }
  206. continue;
  207. } else {
  208. t += m;
  209. }
  210.  
  211. if (checkPuzzle(puzzle) == True) {
  212. printf("complete (total %d moves)", t);
  213. complete = True;
  214. goto gameend;
  215. }
  216. }
  217. gameend:
  218.  
  219. return complete;
  220. }
  221.  
  222. int main(void) {
  223.  
  224. srand((unsigned)time(NULL));
  225.  
  226. puts("* 15 puzzle *");
  227.  
  228. do {
  229. if (game() == False) {
  230. break;
  231. }
  232. } while (confirm("do you continue") == True);
  233.  
  234. return 0;
  235. }
  236.  
Success #stdin #stdout 0s 2060KB
stdin
1
2
3
4
5
6
7
8
9
10
giveup
yes
stdout
* 15 puzzle *
---------------------- 0 moves
14 10  1  *
 6  9  8  5
 7  2 13 15
 4 11  3 12
move number [1-15]? ---------------------- 1 moves
14 10  *  1
 6  9  8  5
 7  2 13 15
 4 11  3 12
move number [1-15]? cannot move
---------------------- 1 moves
14 10  *  1
 6  9  8  5
 7  2 13 15
 4 11  3 12
move number [1-15]? ---------------------- 4 moves
14 10  8  1
 6  9 13  5
 7  2  3 15
 4 11  * 12
move number [1-15]? ---------------------- 6 moves
14 10  8  1
 6  9 13  5
 7  2  3 15
 *  4 11 12
move number [1-15]? cannot move
---------------------- 6 moves
14 10  8  1
 6  9 13  5
 7  2  3 15
 *  4 11 12
move number [1-15]? ---------------------- 8 moves
14 10  8  1
 *  9 13  5
 6  2  3 15
 7  4 11 12
move number [1-15]? ---------------------- 10 moves
14 10  8  1
 6  9 13  5
 7  2  3 15
 *  4 11 12
move number [1-15]? cannot move
---------------------- 10 moves
14 10  8  1
 6  9 13  5
 7  2  3 15
 *  4 11 12
move number [1-15]? cannot move
---------------------- 10 moves
14 10  8  1
 6  9 13  5
 7  2  3 15
 *  4 11 12
move number [1-15]? cannot move
---------------------- 10 moves
14 10  8  1
 6  9 13  5
 7  2  3 15
 *  4 11 12
move number [1-15]? do you give up [y/n]? gave up