• 数据结构栈的使用——马踏棋盘


    题目

    设计一个国际象棋的马踏遍棋盘的演示程序。

    将马随机放在国际象棋棋盘8×8棋盘 map[8][8]的某个方格中,马按照走棋规则进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格。编制程序,求出马的行走路线,并按求出的行走路线,将数字1,2,.......,64依次填入一个8×8的方阵,输出之。可自行指定一个马的初始位置(x,y)。下面图中显示了马位于方格位置中8个可移动的位置。

    每次在多个可走位置中选择其中一个进行试探,其余未曾试探过的可走位置必须用适当的结构妥善管理,以备试探失败时“回溯”(悔棋)使用。

     结构体的定义:

    1. #define MAX 64
    2. typedef struct //存储马可以踏成功的位置
    3. {
    4. int x,y;
    5. }postion;
    6. typedef struct Zhan //栈就是存储已经成功踏入的点
    7. {
    8. postion a[MAX]; //存位置
    9. int top; //栈顶位置
    10. }Zhan; //结构体别名

    栈需要进行初始化,初始化函数的代码如下:

    1. void InitZhan(Zhan *s) //栈的初始化
    2. {
    3. s->top=-1;
    4. }

    压栈和退栈的操作与简单栈的操作相同代码如下所示:

    1. int Push(Zhan *s,postion x) //存数据的函数
    2. {
    3. if(s->top==MAX-1) //判断栈有没有存满也就是马有没有把棋盘踏完
    4. return 0;
    5. else //没有踏完
    6. {
    7. s->top++; //栈顶先加
    8. s->a[s->top]=x; // 存入栈里
    9. return 1;
    10. }
    11. }
    12. int Pop(Zhan *s) //如果马已经无路可走就退回上一步,然后继续判断其他的路
    13. {
    14. if(s->top==-1) //栈有没有空
    15. return 0;
    16. else //没空的时候就让栈顶减1
    17. {
    18. s->top--;
    19. return 1;
    20. }
    21. }

    在马进行踏迷宫的时候需要有一个函数判断我们存储数据的栈中的元素是否已经全部退出完成,其中的代码如下所示:

    1. int IsEmpty(Zhan *s) //栈有没有空的一个函数
    2. {
    3. if(s->top==-1)
    4. return 1;
    5. return 0;
    6. }

    在找马可以走的位置还需要有一个得到栈顶位置的函数,其中代码如下:

    1. postion Gettop(Zhan *s) //找到栈顶的位置在哪
    2. {
    3. postion x;
    4. x=s->a[s->top];
    5. return x;
    6. }

    在该程序中需要定义两个[8][8]的数组初始值为0,一个用来存储马在其中踏的第几次,另一个则用来判断马有没有将其走过。和马可以走的八个位置的数组,还需定义一个标记变量,用来判断马有没有踏完棋盘。(其中全为全局变量,还需定义一个栈)

    定义如下所示:

    1. int map[8][8]={0}; //初始化棋盘
    2. int book[8][8]={0}; //存储有没有走
    3. int next[8][2]={-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1}; //
    4. int flag=0; //一个变量判断有没有走完
    5. Zhan s; //先定义一个栈

    然后下来就是该程序的核心代码,也就是马该怎么走,该函数包含三个参数,两个用来存储马的坐标位置,第三个参数用来存储马走了第几步。在函数中首先判断马有没有将棋盘走完,如果走完了则在其中将判断变量值设置为1,且定义一个次数变量,加一个循环其停止条件则是该栈为空,当栈一直不为空时则让一个结构体存储栈顶的数据,然后进行退栈操作随后将map中的栈顶位置存储为最后一个位置,依次类推存储马走的位置。然后当栈为空时退出循环打印马走的棋盘。如果马没有将棋盘走完则让马的当前位置判断周围的八个点是否可以走,如果可以走则标记该点已走过然后将数据存入栈中,如果走不了则继续进行循环直到八个点都不可以走之后则将栈元素退出然后标记值设置为0,再次调用该函数让马继续走。

    核心代码如下所示:

    1. void Run(int x,int y,int step) //马走的函数
    2. {
    3. if(step==64) //判断棋盘走没走完,走完就输出地图
    4. {
    5. flag=1; //走完变量为1
    6. int Count=0; //走的次数
    7. while(!IsEmpty(&s)) //判断栈有没有空
    8. {
    9. postion n =Gettop(&s); // 让n获得栈顶的位置
    10. Pop(&s); //退出一个位置,为了得到下一个位置所以得到栈顶后需要退出栈顶的元素
    11. map[n.x][n.y]=64-(Count++); //将栈退出的次数存入地图中
    12. }
    13. for(int i=0;i<8;i++) //打印棋盘
    14. {
    15. for(int j=0;j<8;j++)
    16. {
    17. cout<" "; //相当于C语言的printf
    18. }
    19. cout<//相当于\n
    20. }
    21. return ;
    22. }
    23. for(int i=0;i<8;i++) //马当前可以走的8个位置
    24. {
    25. int x1=x+next[i][0]; //找到马走的下一步的x位置
    26. int y1=y+next[i][1]; //找到马走的下一步的y位置
    27. if(x1<0||x1>7||y1<0||y1>7||book[x1][y1]==1) //判断马的下一步有没有超过棋盘的位置,如果超过了则继续返回循环
    28. {
    29. continue;
    30. }
    31. if(book[x1][y1]==0) //判断马的下一步走了没走
    32. {
    33. book[x1][y1]=1; //马已经走了这一步
    34. postion p; //存x,y的结构体 ,把马当前的位置存在p中
    35. p.x=x1;
    36. p.y=y1;
    37. Push(&s,p); //把结构体p放在栈中
    38. Run(x1,y1,step+1); //递归下一步,
    39. if(flag) return ; // 如果已经走完直接出函数
    40. book[x1][y1]=0; //把当前马的位置设置为0,也就是没有走
    41. Pop(&s); //把存储进去的位置退出来
    42. }
    43. }
    44. return ;
    45. }

    整体的完整代码如下所示:

    1. #include //include
    2. #include //开辟空间的头文件malloc
    3. #include //不写
    4. using namespace std; //可以不写
    5. #define MAX 64
    6. typedef struct //存储马可以踏成功的位置
    7. {
    8. int x,y;
    9. }postion;
    10. typedef struct Zhan //栈就是存储已经成功踏入的点
    11. {
    12. postion a[MAX]; //存位置
    13. int top; //栈顶位置
    14. }Zhan; //结构体别名
    15. void InitZhan(Zhan *s) //栈的初始化
    16. {
    17. s->top=-1;
    18. }
    19. int Push(Zhan *s,postion x) //存数据的函数
    20. {
    21. if(s->top==MAX-1) //判断栈有没有存满也就是马有没有把棋盘踏完
    22. return 0;
    23. else //没有踏完
    24. {
    25. s->top++; //栈顶先加
    26. s->a[s->top]=x; // 存入栈里
    27. return 1;
    28. }
    29. }
    30. int Pop(Zhan *s) //如果马已经无路可走就退回上一步,然后继续判断其他的路
    31. {
    32. if(s->top==-1) //栈有没有空
    33. return 0;
    34. else //没空的时候就让栈顶减1
    35. {
    36. s->top--;
    37. return 1;
    38. }
    39. }
    40. int IsEmpty(Zhan *s) //栈有没有空的一个函数
    41. {
    42. if(s->top==-1)
    43. return 1;
    44. return 0;
    45. }
    46. postion Gettop(Zhan *s) //找到栈顶的位置在哪
    47. {
    48. postion x;
    49. x=s->a[s->top];
    50. return x;
    51. }
    52. int map[8][8]={0}; //初始化棋盘
    53. int book[8][8]={0}; //存储有没有走
    54. int next[8][2]={-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1}; //
    55. int flag=0; //一个变量判断有没有走完
    56. Zhan s; //先定义一个栈
    57. void Run(int x,int y,int step) //马走的函数
    58. {
    59. if(step==64) //判断棋盘走没走完,走完就输出地图
    60. {
    61. flag=1; //走完变量为1
    62. int Count=0; //走的次数
    63. while(!IsEmpty(&s)) //判断栈有没有空
    64. {
    65. postion n =Gettop(&s); // 让n获得栈顶的位置
    66. Pop(&s); //退出一个位置,为了得到下一个位置所以得到栈顶后需要退出栈顶的元素
    67. map[n.x][n.y]=64-(Count++); //将栈退出的次数存入地图中
    68. }
    69. for(int i=0;i<8;i++) //打印棋盘
    70. {
    71. for(int j=0;j<8;j++)
    72. {
    73. cout<" "; //相当于C语言的printf
    74. }
    75. cout<//相当于\n
    76. }
    77. return ;
    78. }
    79. for(int i=0;i<8;i++) //马当前可以走的8个位置
    80. {
    81. int x1=x+next[i][0]; //找到马走的下一步的x位置
    82. int y1=y+next[i][1]; //找到马走的下一步的y位置
    83. if(x1<0||x1>7||y1<0||y1>7||book[x1][y1]==1) //判断马的下一步有没有超过棋盘的位置,如果超过了则继续返回循环
    84. {
    85. continue;
    86. }
    87. if(book[x1][y1]==0) //判断马的下一步走了没走
    88. {
    89. book[x1][y1]=1; //马已经走了这一步
    90. postion p; //存x,y的结构体 ,把马当前的位置存在p中
    91. p.x=x1;
    92. p.y=y1;
    93. Push(&s,p); //把结构体p放在栈中
    94. Run(x1,y1,step+1); //递归下一步,
    95. if(flag) return ; // 如果已经走完直接出函数
    96. book[x1][y1]=0; //把当前马的位置设置为0,也就是没有走
    97. Pop(&s); //把存储进去的位置退出来
    98. }
    99. }
    100. return ;
    101. }
    102. int main()
    103. {
    104. InitZhan(&s); //初始化
    105. int x,y;
    106. cout<<"请输入马的初始位置->"; //printf
    107. cin>>x>>y; //相当于c语言的scanf
    108. map[x][y]=1; //先存储初始位置
    109. book[x][y]=1; //马已经走过存1
    110. Run(x,y,1); //运行初始位置时马走的步
    111. return 0;
    112. }

    最终运行的结果如下图所示:

     输入其他值可能会导致运行变慢因为马踏的时候可能会存在很多次回溯所以运行的时间会变的很长,甚至有些位置可能不会踏完棋盘。

  • 相关阅读:
    不用order by 选出第二个人
    MyBatis 篇
    【git】github 如何同步别人的仓库
    倒置字符串
    ubuntu安装ROS rosdep init rosdep update报错,完美解决方案!
    2022年R1快开门式压力容器操作考试模拟100题及答案
    mysql关联查询
    由置灰引出的css滤镜filter是什么东西?
    Python中正整数
    基于QT实现的图书室管理系统
  • 原文地址:https://blog.csdn.net/m0_61886762/article/details/127098778