用c语言实现马踏棋盘的动态演示

用的遍历实现了功能,teacher要求要能动态演示,求一个完整代码能用c语言实现马跳的过程的动态演示(最好能简易一些)

解答如下,1s刷新一次

img

#include<windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 8
#define COL 8
#define MAX_STEPS ROW*COL
#define SLEEP_TIME_MS 1000
#define OBJECT #
#define OTHRER -
//栈结构体
typedef struct stack{
    int x_adr;      //纵坐标
    int y_adr;      //横坐标
    int direction;  //方向
}HORSE_CHESS_STACK;

//存储路径棋盘
int chess[ROW+1][COL+1];

//下一步方向
//一号
int dir[8][2] = {{2,-1},{-2,-1},{-2,1},{2,1}, 
                 {1,-2},{-1,-2},{-1,2},{1,2}};

//二号
/* int dir[8][2] = {{1,2},{-1,-2},{-2,1},{2,1},
                  {2,-1},{1,-2},{-1,2},{-2,-1}}; */ 

//栈顶
int top;
HORSE_CHESS_STACK Adr_Stack[MAX_STEPS];

//出栈次数
int out_stack;

//初始化数据
void init(){
    int n = MAX_STEPS;
    while(n--){
        Adr_Stack[n].x_adr = 0;
        Adr_Stack[n].y_adr = 0;
        Adr_Stack[n].direction = -1;
    }
    Adr_Stack[0].x_adr = 0;
    Adr_Stack[0].y_adr = 0;
    Adr_Stack[0].direction = -1;
    
    for(int i = 1;i <= ROW;i++){
        for(int j = 1;j <= COL;j++){
            chess[ROW][COL] = 0;
        }
    }
    
    top = -1;
    out_stack = 0;
}

//debug 打印栈的情况
void print_stack(){
    printf("栈的情况:\n");
    for(int i = 0;i < MAX_STEPS;i++){
        printf("x:%d  y:%d direction = %d\n",Adr_Stack[i].y_adr,Adr_Stack[i].x_adr,Adr_Stack[i].direction);
    }
    printf("\n\n");
}

//入栈
void push_stack(int x_real,int y_real){
    top++;
    Adr_Stack[top].x_adr = x_real;
    Adr_Stack[top].y_adr = y_real;
    Adr_Stack[top].direction = -1;  //初始化走的方向
}

//出栈
void pop_stack(){
    Adr_Stack[top].x_adr = 0;
    Adr_Stack[top].y_adr = 0;
    Adr_Stack[top].direction = -1;  //初始化走的方向
    top--;
}

//标记位置
void mark_chess(int x,int y){
    chess[y][x] = top + 1;
}

//打印路径
void print_chess_board(){
    printf("\nroute:\n");
    for(int i = 1;i <= ROW;i++){
        for(int j = 1;j <= ROW;j++){
            printf("%4d ",chess[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

//打印每一步的位置
int t = 1;
void print_steps(){
    printf("(%d,%d)",Adr_Stack[top].y_adr,Adr_Stack[top].x_adr);
    t++;
    if(t == ROW){
        printf("\n");
        t = 0;
    }
}

void Sleep_T(int T)
{
    Sleep(SLEEP_TIME_MS);
}

char JumpRout[ROW+1][COL+1]={' '};

void display(char t[ROW+1][COL+1])
{
    for(int i = 1;i <= ROW;i++)
    {
        for(int j = 1;j <= ROW;j++)
        {
            if(t[i][j]=='#')
                printf("%c",t[i][j]);
            else if(t[i][j]=' ')
                printf("%c",'-');
        }
        printf("\n");
    }    
}
int pos=1;
void Jump(int t[ROW+1][COL+1])
{
    while(pos<=MAX_STEPS)
    {
        for(int i = 1;i <= ROW;i++)
        {
            for(int j = 1;j <= ROW;j++)
            {
                if(t[i][j]==pos)
                {
                    printf("Adr:(%d,%d)\n",i,j);
                    JumpRout[i][j]='#';
                    display(JumpRout);
                    Sleep(SLEEP_TIME_MS);
                    system("cls");
                    JumpRout[i][j]=' ';
                    pos++;
                    
                }
            }
        }
    }
}

//马踏棋盘(贪心)算法
void run_horse_tanxin(){
    int x_now,y_now;
    while(1){
        
        //已经走完全图
        if(top >= MAX_STEPS - 1){
            system("cls");
            Jump(chess);
            print_chess_board();//打印棋盘
            break;
        }

        //现在位置
        x_now = Adr_Stack[top].x_adr;
        y_now = Adr_Stack[top].y_adr;
    
        //对方向进行排序
        int next[ROW] = {};
        for(int i = 0;i < ROW;i++){
            //下一步坐标
            int x_next = x_now + dir[i][0];
            int y_next = y_now + dir[i][1];
            
            if((x_next > 0 && x_next <= COL) && (y_next > 0 && y_next <= ROW) && chess[y_next][x_next] == 0 ){
                //对下一步的下一步判断是否可以走
                for(int j = 0;j < ROW;j++){
                    int x_next_next = x_next + dir[j][0];
                    int y_next_next = y_next + dir[j][1];

                    //可以走,next 对应下标+1
                    if((x_next_next > 0 && x_next_next <= COL) && (y_next_next > 0 && y_next_next <= ROW) && chess[y_next_next][x_next_next] == 0){
                        next[i]++;
                    }
                }
            }
        }
        
        //依次返回 next 中最小元素的下标,返回后将元素赋值为最大
        int real_next[8] = {0};
        int k = 0;
        int t = ROW + 1;
        for(int i = 0;i < ROW;i++){
            t = ROW + 1;
            for(int j = 0;j < 8;j++){
                if(next[j] < t){
                    real_next[i] = j;
                    t = next[j];
                    k = j;
                }
            }
            next[k] = ROW + 1;
        }

        //走下一步
        int dir_now = 0;
        for(dir_now = Adr_Stack[top].direction + 1;dir_now < ROW;dir_now++){
            int x_real = x_now + dir[real_next[dir_now]][0];
            int y_real = y_now + dir[real_next[dir_now]][1];

            Adr_Stack[top].direction += 1;

            if((x_real <= COL && x_real > 0) && (y_real <= ROW && y_real > 0) && chess[y_real][x_real] == 0){
                //入栈
                push_stack(x_real,y_real);
                //标记棋盘
                mark_chess(x_real,y_real);
                break;
            }
        }

        //如果下一步走不了,则出栈回溯
        if(Adr_Stack[top].direction >= 7){
            printf("\n out:(%d,%d) \n",Adr_Stack[top].y_adr,Adr_Stack[top].x_adr);
            chess[Adr_Stack[top].y_adr][Adr_Stack[top].x_adr] = 0;
            //记录出栈次数
            out_stack++;
            pop_stack();
        }
        
        //打印栈
        /* print_stack(); */
        //打印走了以后所处位置
        print_steps();
    }
}



int main(){
    int st_x,st_y;
    while(1){
        printf("Please input: x  y :");
        //scanf("%d %d",&st_x,&st_y);
        st_x=1,st_y=1;
        if(st_x > 0 && st_x <= ROW && st_y > 0 && st_y <= COL){
            printf("Get x and y success!\n");
            break;
        }
        
        printf("Input wrong!please input x y again:");
    }
    init();
    /* print_stack(); */
    //获得开始时间
    clock_t start = clock();
    
    //将起始位置入栈
    push_stack(st_x,st_y);
    //标记起始位置
    mark_chess(st_x,st_y);
    
    printf("\nroute address:\n");
    printf("(%d,%d)",st_x,st_y);
    
    //开始算法
    run_horse_tanxin();
    
    //计算结束时间
    clock_t finish = clock();
    double run_time = (double)(finish - start) / CLOCKS_PER_SEC;
    
    printf("Running time:%f seconds  \nOut stack times:%d\n",run_time,out_stack);
}

《马踏棋盘(C语言版)——贪心算法详解(栈的应用数据结构)》, 一起来围观吧 https://blog.csdn.net/weixin_43204126/article/details/102728758?utm_source=app&app_version=5.0.1&code=app_1562916241&uLinkId=usr1mkqgl919blen


//马踏棋盘;
#include <stdio.h>  
//棋盘,其中i=0,1,11,12和j=0,1,11,12表示围墙,马可以踏但是不算在计数中;
int M[12][12]={0};  
  
int cnt=0;       //标记马已走的方格数;  
int sum=0;       //标记马走完全程的具体方案数;  
int move[8][2]=   //初始马当前位置向其周围相邻八个日字的 x,y的偏移量,也就是马可以走的位置一共为八个;
{    
    { 2, 1},
    { 1, 2},
    {-1, 2},
    {-2, 1},
    {-2,-1},
    {-1,-2},
    { 1,-2},
    { 2,-1}
};  
  
//输出马踏棋盘的解   
void PrintChess()
{
    for(int i=2;i<10;i++)
    {  
        for(int j=2;j<10;j++)  
            printf("%3d",M[i][j]);   
        printf("\n");
    } 
    printf("\n\n\n");
}
 
//判断马可以走的位置;
void Horse(int x,int y)  //马永远踏的是 x,y位置,而不是 a,b;
{          
    if(cnt==64)  //临界值,马走日字全部踏完,成功求出问题解;
    {            
        sum++;   //解的个数;
        printf("第%d组解:\n",sum);
        PrintChess();  //输出;
        return ;  
    }
 
    for(int i=0;i<8;i++)
    {
        int a=x+move[i][0];     //拿到当前马位置相邻的 8 个日字的 x 坐标;  
        int b=y+move[i][1];     //拿到当前马位置相邻的 8 个日字的 y 坐标;   
        if(M[a][b]==0) //判断当前马位置相邻的日字是否已被访问;
        {                     
            M[a][b]=++cnt;   //标志已被访问;
            Horse(a,b);      //从当前马的位置继续往下访问;  
            cnt--;           //回溯到这里,将计数的值--;
            M[a][b]=0;       //并且将这个位置清空,进行下一次循环或者跳出循环;            
        }  
    }  
}  
 
int main(void)
{    
    printf("***马踏棋盘左右解***\n\n");
    //在8*8的外层再加上两层,确保8*8方格中的每一个格子都有8种不同的日字选择;
    for(int i=0;i<12;i++)
    {  
        for(int j=0;j<12;j++)
        {  
            if(i==0||i==1||i==10||i==11||j==0||j==1||j==10||j==11){  
                M[i][j]=-1; 
            }  
        }  
    }  
 
 
    //从起始位置开始求得所有解; 
    //坐标(2,2)马可以踏,将求得的位置解++;
    M[2][2]=++cnt;  
 
 
    //递归调用当前当前位置附近的 8 个日字,看看是否满足条件;
    //马从坐标(2,2)开始;
    Horse(2,2);  
    return 0;   
}

不知这个实例【马踏棋盘算法介绍和游戏演示】,符不符合你的要求:https://blog.csdn.net/weixin_62226325/article/details/123101417

//马踏棋盘主要要考虑三个因素:

//第一:马走的位置用Move数组表示,以及棋盘的大小不再是88,而是1212;

//第二:只要找到马可以踏的下一个位置,就进行递归,只有一只进行递归,这是一种理想状态;

/第三:也是最不好想的一点,如果在当前位置,准备进行下一个位置,但是没有找到,就需要回溯,回溯需要将计数器--,并且将这个位置赋值为0,表示这个位置没走过,因为回溯本身就在for循环中,所以,循环会自己判断进行下一个位置判定;

//马踏棋盘;
#include <stdio.h>  
//棋盘,其中i=0,1,11,12和j=0,1,11,12表示围墙,马可以踏但是不算在计数中;
int M[12][12]={0};  
  
int cnt=0;       //标记马已走的方格数;  
int sum=0;       //标记马走完全程的具体方案数;  
int move[8][2]=   //初始马当前位置向其周围相邻八个日字的 x,y的偏移量,也就是马可以走的位置一共为八个;
{    
    { 2, 1},
    { 1, 2},
    {-1, 2},
    {-2, 1},
    {-2,-1},
    {-1,-2},
    { 1,-2},
    { 2,-1}
};  
  
//输出马踏棋盘的解   
void PrintChess()
{
    for(int i=2;i<10;i++)
    {  
        for(int j=2;j<10;j++)  
            printf("%3d",M[i][j]);   
        printf("\n");
    } 
    printf("\n\n\n");
}
 
//判断马可以走的位置;
void Horse(int x,int y)  //马永远踏的是 x,y位置,而不是 a,b;
{          
    if(cnt==64)  //临界值,马走日字全部踏完,成功求出问题解;
    {            
        sum++;   //解的个数;
        printf("第%d组解:\n",sum);
        PrintChess();  //输出;
        return ;  
    }
 
    for(int i=0;i<8;i++)
    {
        int a=x+move[i][0];     //拿到当前马位置相邻的 8 个日字的 x 坐标;  
        int b=y+move[i][1];     //拿到当前马位置相邻的 8 个日字的 y 坐标;   
        if(M[a][b]==0) //判断当前马位置相邻的日字是否已被访问;
        {                     
            M[a][b]=++cnt;   //标志已被访问;
            Horse(a,b);      //从当前马的位置继续往下访问;  
            cnt--;           //回溯到这里,将计数的值--;
            M[a][b]=0;       //并且将这个位置清空,进行下一次循环或者跳出循环;            
        }  
    }  
}  
 
int main(void)
{    
    printf("***马踏棋盘左右解***\n\n");
    //在8*8的外层再加上两层,确保8*8方格中的每一个格子都有8种不同的日字选择;
    for(int i=0;i<12;i++)
    {  
        for(int j=0;j<12;j++)
        {  
            if(i==0||i==1||i==10||i==11||j==0||j==1||j==10||j==11){  
                M[i][j]=-1; 
            }  
        }  
    }  
 
 
    //从起始位置开始求得所有解; 
    //坐标(2,2)马可以踏,将求得的位置解++;
    M[2][2]=++cnt;  
 
 
    //递归调用当前当前位置附近的 8 个日字,看看是否满足条件;
    //马从坐标(2,2)开始;
    Horse(2,2);  
    return 0;   
}