共有回帖数  0  个 
	 
	
	
	
     
          
          
               
                  - ◣提高级源码◥ 快速九格宫求解 - Fast 8-puzzle solver.
 
                  - 
						 取消只看楼主											  
                     
                       收藏
                      
                          
                           回复
                      
					  
					                     
 
                
				
			 
				
					 
 
            
				   - 
						
						
							 
									发布这个贴已记念一下,作为两年前的: 
http://post.baidu.com/f?kz=11162185 
所发游戏的一个对应. 
九格宫(8-puzzle)的最优求解确实是一个头疼的问题,大致解法为,为每一个可能移法生成一个树结点,然后对这棵树进行广度优先的搜索,然而这棵树是无限层次的,所以必需对已出现的状态进行删减。 最优解及其研究可以搜索 "8 puzzle"来获得英文的一些资料,这里不想讨论这个问题。 
如果要获得简单解,那么,计算的复杂度可以减少到常量级,最重要的是找到一条通用的解法,这正是代码所展示的一切:
#include stdio.h 
#include stdlib.h 
#include string.h 
char block[10]; 
void moveto(int from, int to) 
{ 
    printf("'%c' 到 %dn", block[from], to); 
    printf("----n%c %c %cn", block[0], block[1], block[2]); 
    printf("%c %c %cn", block[3], block[4], block[5]); 
    printf("%c %c %cn----n", block[6], block[7], block[8]); 
    block[to] = block[from]; 
    block[from] = '0'; 
} 
int clearmove(int d, char *mask) 
{ 
    if (block[d] == '0') return 1; 
    char nmask[10]; 
    strcpy(nmask, mask); 
    nmask[d] = '1'; 
     
    if (d + 3  9 && nmask[d + 3] == '0') { 
        if (clearmove(d + 3, nmask)) { 
            moveto(d, d + 3); 
            return 1; 
        } 
    } 
    if (d - 3 = 0 && nmask[d - 3] == '0') { 
        if (clearmove(d - 3, nmask)) { 
            moveto(d, d - 3); 
            return 1; 
        } 
    } 
    if (d % 3 != 0 && nmask[d - 1] == '0') { 
        if (clearmove(d - 1, nmask)) { 
            moveto(d, d - 1); 
            return 1; 
        } 
    } 
    if (d % 3 != 2 && mask[d + 1] == '0') { 
        if (clearmove(d + 1, nmask)) { 
            moveto(d, d + 1); 
            return 1; 
        } 
    } 
    return 0; 
}
void movex(int from, int to, char *mask) 
{ 
    int f, t; 
    if (from == to) return; 
    if (to == from + 3 || to == from - 3 || 
        (to == from + 1 && to % 3 != 0) || 
        (to == from - 1 && to % 3 != 2)) { 
        char zmask[10]; 
        strcpy(zmask, mask); 
        zmask[from] = '1'; 
        clearmove(to, zmask); 
        moveto(from, to); 
        return; 
    } 
     
    f = from % 3; 
    t = to % 3; 
    if (t  f) { 
        movex(from, from + 1, mask); 
        movex(from + 1, to, mask); 
    } else if (t  f) { 
        movex(from, from - 1, mask); 
        movex(from - 1, to, mask); 
    } else { 
        f = from / 3; 
        t = to / 3; 
        if (t  f) { 
            movex(from, from + 3, mask); 
            movex(from + 3, to, mask); 
        } else if (t  f) { 
            movex(from, from - 3, mask); 
            movex(from - 3, to, mask); 
        } 
    } 
} 
int getpos(char x) 
{ 
    int i; 
    for (i = 0; i  9; ++i)  
        if (block == x) return i; 
    return -1; 
}
void move678() 
{ 
    int from; 
    from = getpos('6'); 
    printf("6归位:n"); 
    movex(from, 6, "000000000"); 
    from = getpos('7'); 
    printf("7归位:n"); 
    movex(from, 7, "000000100"); 
     
    if (block[8] == '8') return; 
    if (block[8] == '0' && block[5] == '8') { 
        moveto(5, 8); 
        return; 
    } 
    printf("8移动到4(中间)n"); 
    from = getpos('8'); 
    movex(from, 4, "000000110"); 
     
    printf("6移到3:n"); 
    movex(6, 3, "000010010"); 
    printf("7移到6:n"); 
    moveto(7, 6); 
    printf("8移到7:n"); 
    moveto(4, 7); 
    printf("678还原:n"); 
    movex(7, 8, "000100100"); 
    moveto(6, 7); 
    moveto(3, 6); 
} 
void moverest() 
{ 
    printf("5到2:n"); 
    movex(getpos('5'), 2, "000000111"); 
    if (block[5] != '4') { 
        if (block[4] == '4' && block[5] == '0') moveto(4, 5); 
        else { 
            printf("4移到1:n"); 
            movex(getpos('4'), 1, "001000111"); 
            printf("位置5移到4:n"); 
            if (block[5] != '0') movex(5, 4, "011000111"); 
            printf("678右移:n"); 
            moveto(8, 5); 
            moveto(7, 8); 
            moveto(6, 7); 
            moveto(3, 6); 
            printf("4移到4:n"); 
            movex(1, 4, "001001011"); 
            printf("678还原:n"); 
            movex(7, 6, "001011001"); 
            moveto(8, 7); 
            moveto(5, 8); 
            moveto(4, 5); 
        } 
    } 
     
    printf("3复原:n"); 
    movex(getpos('3'), 3, "001001111"); 
    printf("4复原:n"); 
    movex(5, 4, "001100111"); 
    printf("5复原:n"); 
    moveto(2, 5); 
     
    moveto(1, 2); 
    moveto(0, 1); 
}
int main(int argc, char **argv) 
{ 
    int j; 
    char buf[20]; 
    scanf("%s", buf); 
    for (j = 0; j  9; ++j) { 
        block[j] = buf[j]; 
    } 
    block[9] = 0; 
    move678(); 
    moverest(); 
    if (block[1] == '2') printf("无解.n"); 
    return 0; 
}
#include stdio.h 
#include stdlib.h 
#include string.h 
char block[10]; 
void moveto(int from, int to) 
{ 
    printf("'%c' 到 %dn", block[from], to); 
    printf("----n%c %c %cn", block[0], block[1], block[2]); 
    printf("%c %c %cn", block[3], block[4], block[5]); 
    printf("%c %c %cn----n", block[6], block[7], block[8]); 
    block[to] = block[from]; 
    block[from] = '0'; 
} 
int clearmove(int d, char *mask) 
{ 
    if (block[d] == '0') return 1; 
    char nmask[10]; 
    strcpy(nmask, mask); 
    nmask[d] = '1'; 
     
    if (d + 3  9 && nmask[d + 3] == '0') { 
        if (clearmove(d + 3, nmask)) { 
            moveto(d, d + 3); 
            return 1; 
        } 
    } 
    if (d - 3 = 0 && nmask[d - 3] == '0') { 
        if (clearmove(d - 3, nmask)) { 
            moveto(d, d - 3); 
            return 1; 
        } 
    } 
    if (d % 3 != 0 && nmask[d - 1] == '0') { 
        if (clearmove(d - 1, nmask)) { 
            moveto(d, d - 1); 
            return 1; 
        } 
    } 
    if (d % 3 != 2 && mask[d + 1] == '0') { 
        if (clearmove(d + 1, nmask)) { 
            moveto(d, d + 1); 
            return 1; 
        } 
   } 
    return 0; 
} 
void movex(int from, int to, char *mask) 
{ 
    int f, t; 
    if (from == to) return; 
    if (to == from + 3 || to == from - 3 || 
        (to == from + 1 && to % 3 != 0) || 
        (to == from - 1 && to % 3 != 2)) { 
        char zmask[10]; 
        strcpy(zmask, mask); 
        zmask[from] = '1'; 
        clearmove(to, zmask); 
        moveto(from, to); 
        return; 
    } 
     
    f = from % 3; 
    t = to % 3; 
    if (t  f) { 
        movex(from, from + 1, mask); 
        movex(from + 1, to, mask); 
    } else if (t  f) { 
        movex(from, from - 1, mask); 
        movex(from - 1, to, mask); 
    } else { 
        f = from / 3; 
        t = to / 3; 
        if (t  f) { 
            movex(from, from + 3, mask); 
            movex(from + 3, to, mask); 
        } else if (t  f) { 
            movex(from, from - 3, mask); 
            movex(from - 3, to, mask); 
        } 
    } 
} 
int getpos(char x) 
{ 
    int i; 
    for (i = 0; i  9; ++i)  
        if (block == x) return i; 
   return -1; 
} 
void move678() 
{ 
    int from; 
    from = getpos('6'); 
    printf("6归位:n"); 
    movex(from, 6, "000000000"); 
    from = getpos('7'); 
    printf("7归位:n"); 
    movex(from, 7, "000000100"); 
     
    if (block[8] == '8') return; 
    if (block[8] == '0' && block[5] == '8') { 
        moveto(5, 8); 
        return; 
    } 
    printf("8移动到4(中间)n"); 
    from = getpos('8'); 
    movex(from, 4, "000000110"); 
     
    printf("6移到3:n"); 
    movex(6, 3, "000010010"); 
    printf("7移到6:n"); 
    moveto(7, 6); 
    printf("8移到7:n"); 
    moveto(4, 7); 
    printf("678还原:n"); 
    movex(7, 8, "000100100"); 
    moveto(6, 7); 
    moveto(3, 6); 
} 
void moverest() 
{ 
    printf("5到2:n"); 
    movex(getpos('5'), 2, "000000111"); 
    if (block[5] != '4') { 
        if (block[4] == '4' && block[5] == '0') moveto(4, 5); 
        else { 
            printf("4移到1:n"); 
            movex(getpos('4'), 1, "001000111"); 
            printf("位置5移到4:n"); 
            if (block[5] != '0') movex(5, 4, "011000111"); 
            printf("678右移:n"); 
            moveto(8, 5); 
            moveto(7, 8); 
            moveto(6, 7); 
            moveto(3, 6); 
            printf("4移到4:n"); 
            movex(1, 4, "001001011"); 
            printf("678还原:n"); 
            movex(7, 6, "001011001"); 
            moveto(8, 7); 
            moveto(5, 8); 
            moveto(4, 5); 
        } 
    } 
     
    printf("3复原:n"); 
    movex(getpos('3'), 3, "001001111"); 
    printf("4复原:n"); 
    movex(5, 4, "001100111"); 
    printf("5复原:n"); 
    moveto(2, 5); 
     
    moveto(1, 2); 
    moveto(0, 1); 
} 
int main(int argc, char **argv) 
{ 
    int j; 
    char buf[20]; 
    scanf("%s", buf); 
    for (j = 0; j  9; ++j) { 
        block[j] = buf[j]; 
    } 
    block[9] = 0; 
    move678(); 
    moverest(); 
    if (block[1] == '2') printf("无解.n"); 
    return 0; 
}
							 
							 
							 
							  
							  
							  楼主 2016-01-28 14:53 回复
						 
						 
           
          
          
         
   
         
      
 
   
             
                  
                  
 
 
 
     
	 
  
	Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号
	
	意见反馈 | 
	关于直线 | 
	版权声明 | 
	会员须知