用c语言实现八数码并且加上注释
时间: 2023-12-24 08:50:37 浏览: 77
八数码问题,用广度优先和深度优先算法实现 并且用mfc实现界面,让结果算法运行过程以动画显示 并附上实验报告.zip
5星 · 资源好评率100%
以下是用C语言实现八数码游戏的代码,已加上注释:
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// 定义八数码结构体
typedef struct EightPuzzle {
int puzzle[3][3]; // 3x3的数组表示八数码
int x, y; // 空白格子的位置坐标
} EightPuzzle;
// 打印八数码
void print_puzzle(EightPuzzle *puzzle) {
printf("\n");
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
printf("%d ", puzzle->puzzle[i][j]);
}
printf("\n");
}
}
// 交换两个数的值
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 初始化八数码
void init_puzzle(EightPuzzle *puzzle) {
// 首先将八数码打乱
int nums[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
for(int i=0; i<9; i++) {
int j = rand() % 9;
swap(&nums[i], &nums[j]);
}
// 将打乱后的数字填入八数码中
int k = 0;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
puzzle->puzzle[i][j] = nums[k++];
// 记录空白格子的位置
if(puzzle->puzzle[i][j] == 0) {
puzzle->x = i;
puzzle->y = j;
}
}
}
}
// 判断八数码是否可解,返回1表示可解,返回0表示不可解
int is_solvable(EightPuzzle *puzzle) {
int inversions = 0; // 记录逆序对数
int nums[9]; // 将八数码转化为一维数组便于计算逆序对数
// 将八数码转化为一维数组
int k = 0;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
nums[k++] = puzzle->puzzle[i][j];
}
}
// 计算逆序对数
for(int i=0; i<8; i++) {
for(int j=i+1; j<9; j++) {
if(nums[i] > nums[j] && nums[i] != 0 && nums[j] != 0) {
inversions++;
}
}
}
// 判断逆序对数的奇偶性
if(inversions % 2 == 0) {
return 1; // 可解
} else {
return 0; // 不可解
}
}
// 判断八数码是否已经到达目标状态
int is_goal(EightPuzzle *puzzle) {
int goal[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 0}}; // 目标状态
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
if(puzzle->puzzle[i][j] != goal[i][j]) {
return 0; // 没有到达目标状态
}
}
}
return 1; // 到达目标状态
}
// 移动空白格子到指定位置
void move_blank(EightPuzzle *puzzle, int x, int y) {
swap(&puzzle->puzzle[puzzle->x][puzzle->y], &puzzle->puzzle[x][y]);
puzzle->x = x;
puzzle->y = y;
}
// 判断指定位置是否可以移动空白格子,返回1表示可以移动,返回0表示不可以移动
int can_move_blank(EightPuzzle *puzzle, int x, int y) {
if(x >= 0 && x < 3 && y >= 0 && y < 3 && puzzle->puzzle[x][y] == 0) {
return 1;
} else {
return 0;
}
}
// 复制八数码
void copy_puzzle(EightPuzzle *src, EightPuzzle *dest) {
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
dest->puzzle[i][j] = src->puzzle[i][j];
}
}
dest->x = src->x;
dest->y = src->y;
}
// 搜索解决八数码问题
int solve_puzzle(EightPuzzle *puzzle, int depth, int max_depth, int prev_move) {
// 判断是否已经到达目标状态或者已经达到最大深度
if(is_goal(puzzle)) {
return 1;
}
if(depth == max_depth) {
return 0;
}
// 尝试上下左右四个方向移动空白格子
EightPuzzle new_puzzle;
int result = 0;
if(can_move_blank(puzzle, puzzle->x-1, puzzle->y) && prev_move != 2) { // 上
copy_puzzle(puzzle, &new_puzzle);
move_blank(&new_puzzle, puzzle->x-1, puzzle->y);
result = solve_puzzle(&new_puzzle, depth+1, max_depth, 1);
if(result) {
return 1;
}
}
if(can_move_blank(puzzle, puzzle->x+1, puzzle->y) && prev_move != 1) { // 下
copy_puzzle(puzzle, &new_puzzle);
move_blank(&new_puzzle, puzzle->x+1, puzzle->y);
result = solve_puzzle(&new_puzzle, depth+1, max_depth, 2);
if(result) {
return 1;
}
}
if(can_move_blank(puzzle, puzzle->x, puzzle->y-1) && prev_move != 4) { // 左
copy_puzzle(puzzle, &new_puzzle);
move_blank(&new_puzzle, puzzle->x, puzzle->y-1);
result = solve_puzzle(&new_puzzle, depth+1, max_depth, 3);
if(result) {
return 1;
}
}
if(can_move_blank(puzzle, puzzle->x, puzzle->y+1) && prev_move != 3) { // 右
copy_puzzle(puzzle, &new_puzzle);
move_blank(&new_puzzle, puzzle->x, puzzle->y+1);
result = solve_puzzle(&new_puzzle, depth+1, max_depth, 4);
if(result) {
return 1;
}
}
return 0;
}
int main() {
EightPuzzle puzzle;
init_puzzle(&puzzle);
print_puzzle(&puzzle);
// 判断八数码是否可解
if(!is_solvable(&puzzle)) {
printf("Unsolvable puzzle!\n");
return 0;
}
// 枚举深度,进行搜索
int max_depth = 0;
while(1) {
if(solve_puzzle(&puzzle, 0, max_depth, 0)) {
printf("Solved: %d steps\n", max_depth);
print_puzzle(&puzzle);
break;
}
max_depth++;
}
return 0;
}
```
注释已经尽可能详细地解释了每一步的实现过程,希望能够帮助你理解。
阅读全文