目录
一、问题描述
- 3*3的方格棋盘上,摆放着1到8这八个数码,有1个方格是空。
- 要求对空格执行空格左移、空格右移、空格上移和空格下移这四个操作使得棋盘从初始状态(图左)到目标状态(图右)。
二、迟来的代码
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> #define N 3 // 阶数 int src[N][N]; // 初始状态 int dest[N][N] = {1, 2, 3, 8, 0, 4, 7, 6, 5}; // 目标状态 // 初始化棋盘 void init() { int i, j, k; int a[N*N] = {1, 2, 3, 8, 0, 4, 7, 6, 5}; int flag[N*N] = {0}; // 用来标记0~8中哪个数字已经出现过 srand(time(0)); for(i = 0; i < N; i++) { for(j = 0; j < N; j++) { // 尝试生成一个0~8间的数字 k = rand()%(N*N); while(1) { // 如果该数字未出现 if(flag[k] == 0) { flag[k] = 1; // 修改标志位 src[i][j] = a[k]; // 初始化对应src的位置 break; } // 重新生成数字 k = rand()%(N*N); } } } } // 打印棋盘状态 void display() { int i, j; for(i = 0; i < N; i++) { for(j = 0; j < N; j++) { // 把0当做空格输出 if(src[i][j]) { printf("%d ", src[i][j]); } else { printf(" "); } } printf("\n"); } } // 寻找出棋盘中的空格键 void findSpace(int *x, int *y) { int i, j; for(i = 0; i < N; i++) { for(j = 0; j < N; j++) { if(src[i][j] == 0) // 找到空格 { *x = i; *y = j; } } } } // 空格左移 void left() { int x, y; findSpace(&x, &y); // 寻找空格坐标 // 空格必须是处于第2列或者第3列,才能左移 if(y >= 1) { src[x][y] = src[x][y-1]; src[x][y-1] = 0; } } // 空格右移 void right() { int x, y; findSpace(&x, &y); // 寻找空格坐标 // 空格必须是处于第1列或者第2列,才能右移 if(y <= 1) { src[x][y] = src[x][y+1]; src[x][y+1] = 0; } } // 空格上移 void up() { int x, y; findSpace(&x, &y); // 寻找空格坐标 // 空格必须是处于第2行或者第3行,才能上移 if(x >= 1) { src[x][y] = src[x-1][y]; src[x-1][y] = 0; } } // 空格下移 void down() { int x, y; findSpace(&x, &y); // 寻找空格坐标 // 空格必须是处于第1行或者第2行,才能下移 if(x <= 1) { src[x][y] = src[x+1][y]; src[x+1][y] = 0; } } // 检查当前棋盘状态是否为目标状态 int checkWin() { int i, j; for(i = 0; i < N; i++) { for(j = 0; j < N; j++) { // 检测到有不同的就立马返回,节省时间 if(src[i][j] != dest[i][j]) { return 0; } } } return 1; } int main() { char ch; init(); printf("下面开始八数码小游戏\n"); while(1) { display(); ch = getch(); switch(ch) { case 72: up(); break; case 80: down(); break; case 75: left(); break; case 77: right(); break; } system("cls"); if(ch == 27) { printf("你已退出\n"); break; } if(checkWin()) { printf("你赢了\n"); break; } } return 0; }
运行截图:(其他例子自己举)
三、简单分析
如果认真且仔细看完代码的程序猿同学,根据注释的讲解,可以说基本上可以看懂了,如果想看如果求解的可以在我的博客里找,里面包含了,广度优先搜索,深度优先搜索,等代价搜索,启发式搜索等解法,记得收藏^_^
此外生成的初始状态可能无解,例如上述的例子,所以需要注意,这也是最刺激的地方^_^