问题描述

将马随机放在国际象棋的8×8棋盘的某个方格中,马按走棋规则(马走日字)进行移动。要求每个方格只进入一次,走遍棋盘上全部64个方格。
image.png

运用的算法

  • 递归
  • 回溯
  • 贪心(可选)

    代码

    还可以优化,用贪心算法,每次递归进入当前马能走的最少的点。这样回溯就少了很多步骤

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Globalization;
  5. using System.IO;
  6. using System.Runtime.Serialization.Formatters.Binary;
  7. using System.Text;
  8. namespace ConsoleApp1
  9. {
  10. class Program
  11. {
  12. public static int X;//棋盘x长度
  13. public static int Y;//棋盘y长度
  14. //创建一个数组,标记棋盘的各个位置是否被访问过了
  15. public static bool[] visited;
  16. //使用一个变量标记是否棋盘的所有位置都被访问
  17. public static bool finished;//如果为true,表示成功
  18. static void Main(string[] args)
  19. {
  20. X = 6;
  21. Y = 6;
  22. int row = 2;//初始位置从1开始
  23. int col = 4;
  24. //棋盘
  25. int[,] chessboard=new int[X,Y];
  26. visited = new bool[X * Y];
  27. DateTime st = DateTime.Now;
  28. traversalChessborad(chessboard, row - 1, col - 1, 1);
  29. DateTime et = DateTime.Now;
  30. Console.WriteLine($"计算用时:{(et-st).TotalMilliseconds}毫秒");
  31. //输出棋盘
  32. for(int i = 0; i < chessboard.GetLength(0); i++)
  33. {
  34. for(int j=0;j< chessboard.GetLength(1); j++)
  35. Console.Write(chessboard[i,j]+" ");
  36. Console.WriteLine();
  37. }
  38. }
  39. //完成骑士周游问题算法
  40. //chessboard棋盘
  41. //row 当前位置的行从0开始
  42. //col 当前位置的列从0开始
  43. //step 是第几步,初始位置就是第一步
  44. public static void traversalChessborad(int[,] chessboard,int row,int col,int step)
  45. {
  46. chessboard[row,col] = step;
  47. //标记为已访问,从棋盘上数第几个位置
  48. visited[row * X + col] = true;
  49. //获取当前位置可以走的下一个位置的集合
  50. List<Point> ps = next(new Point(col, row));
  51. //遍历
  52. while (ps.Count != 0)
  53. {
  54. //取出下一个可以走的位置
  55. Point p = ps[0];
  56. ps.Remove(p);
  57. //判断该点是否已经访问过了
  58. if (!visited[p.Y * X + p.X])//说明没有访问过
  59. {
  60. traversalChessborad(chessboard, p.Y, p.X, step+1);//一定要step+1,(用step++或者++step把step自身都加了1,下次回溯到这里时,步骤已经+1了)
  61. }
  62. }
  63. //判断是否完成任务,step和应该走的步数比较,如果没有达到数量,则表示没有完成任务
  64. if (step < X * Y && !finished)
  65. {
  66. chessboard[row, col] = 0;
  67. visited[row * X + col] = false;
  68. }
  69. else
  70. {
  71. finished = true;
  72. }
  73. }
  74. //根据当前的位置,计算马儿还能走哪些位置,放入list中,最多有8个位置
  75. public static List<Point> next(Point cp)
  76. {
  77. List <Point> list = new List<Point>();
  78. int x = 0,y = 0;
  79. //马走日的规则,>=0表示没有索引越界。
  80. if ((x = cp.X - 2) >= 0 && (y = cp.Y - 1) >= 0) //左2上1
  81. list.Add(new Point(x, y));
  82. if ((x = cp.X - 1) >= 0 && (y = cp.Y - 2) >= 0)//左1上2
  83. list.Add(new Point(x, y));
  84. if ((x = cp.X + 1) < X && (y = cp.Y - 2) >= 0)//右1上2
  85. list.Add(new Point(x, y));
  86. if ((x = cp.X + 2) < X && (y = cp.Y - 1) >= 0)//右2上1
  87. list.Add(new Point(x, y));
  88. if ((x = cp.X + 2) < X && (y = cp.Y + 1) < Y)//右2下1
  89. list.Add(new Point(x, y));
  90. if ((x = cp.X + 1) < X && (y = cp.Y + 2) < Y)//右1下2
  91. list.Add(new Point(x, y));
  92. if ((x = cp.X - 1) >= 0 && (y = cp.Y + 2) < Y)//左1下2
  93. list.Add(new Point(x, y));
  94. if ((x = cp.X - 2) >= 0 && (y = cp.Y + 1) < Y)//左2下1
  95. list.Add(new Point(x, y));
  96. return list;
  97. }
  98. }
  99. }