我一直致力于一个需要骑士的项目(我们在开始时有它的坐标)前往目的地(也称为已知坐标)。 我尝试使用递归编写,但我的代码似乎没有做任何事情,我无法找到问题。这是我的代码:
static bool Kelias(int dabX, int dabY, string[] Lenta, int dX, int dY, int indeksas)
{
if (dabX == dX && dabY == dY)
return true;
if (!Lenta[dabY][dabX].Equals('0'))
{
return false;
}
if (indeksas > 0)
{
StringBuilder naujas = new StringBuilder(Lenta[dabY]);
naujas[dabX] = (char)indeksas;
Lenta[dabY] = naujas.ToString();
}
// aukstyn desinen
if (GaliJudeti(dabX + 2, dabY + 1)
&& Kelias(dabX + 2, dabY + 1, Lenta, dX, dY, indeksas + 1))
{
return true;
}
// aukstyn desinen
if (GaliJudeti(dabX + 1, dabY + 2)
&& Kelias(dabX + 1, dabY + 2, Lenta, dX, dY, indeksas + 1))
{
return true;
}
// aukstyn kairen
if (GaliJudeti(dabX - 1, dabY + 2)
&& Kelias(dabX - 1, dabY + 2, Lenta, dX, dY, indeksas + 1))
{
return true;
}
// aukstyn kairen
if (GaliJudeti(dabX - 2, dabY + 1)
&& Kelias(dabX - 2, dabY + 1, Lenta, dX, dY, indeksas + 1))
{
return true;
}
// zemyn kairen
if (GaliJudeti(dabX - 2, dabY - 1)
&& Kelias(dabX - 2, dabY - 1, Lenta, dX, dY, indeksas + 1))
{
return true;
}
// zemyn kairen
if (GaliJudeti(dabX - 1, dabY - 2)
&& Kelias(dabX - 1, dabY - 2, Lenta, dX, dY, indeksas + 1))
{
return true;
}
// zemyn desinen
if (GaliJudeti(dabX + 1, dabY - 2)
&& Kelias(dabX + 1, dabY - 2, Lenta, dX, dY, indeksas + 1))
{
return true;
}
// zemyn desinen
if (GaliJudeti(dabX + 2, dabY - 1)
&& Kelias(dabX + 2, dabY - 1, Lenta, dX, dY, indeksas + 1))
{
return true;
}
indeksas--;
return false;
}
static bool GaliJudeti(int x, int y)
{
if (x >= 0 && y >= 0 && x < 8 && y < 8)
{
return true;
}
return false;
}
关于变量的一些解释以及我尝试做的事情:
dabX,dabY - 是骑士的当前坐标
Lenta - 是我的董事会(这是一个字符串,因为我正在读取txt文件中的起始数据)。
dX,dY - 是目标目的地
indeksas - 跟踪到达目的地所需的移动次数
现在第一个检查我们是否到达目的地。第二个检查我们行进的坐标是否也没有受到阻碍(因为我的电路板是由零组成的,因此我们检查符号是否等于它是否导致它是&#39 ; s并不意味着路径受阻)。然后我们进入骑士可能的运动,这是该方法的主要部分。
另外还有另一个名为GaliJudeti的函数,用于检查我们是否在董事会的范围内(8x8)。
答案 0 :(得分:0)
您的代码看起来必须正常工作。我只是使用你的算法,修改了一下,一切正常。我使用类来使它看起来更普遍,但事实上它们都是一样的。
static bool MoveFirstSolution(Knight knight, Board board, Point destination, int counter, Trace trace)
{
board.Set(knight.X, knight.Y, counter);
if (knight.IsInPoint(destination))
{
//trace is an object to store found path
trace.Counter = counter;
trace.Board = board;
return true;
}
counter++;
Point[] moves = knight.AllPossibleMoves();
foreach (Point point in moves)
{
if (board.Contains(point) && board.IsFree(point))
{
knight.MoveTo(point);
if (MoveFirstSolution(knight, board.GetCopy(), destination, counter, trace))
{
return true;
}
}
}
return false;
}
但是,此功能将找到第一个解决方案并停止。如果您需要最佳解决方案,即使找到答案,也需要继续搜索。这是执行它的功能:
static void Move(Knight knight, Board board, Point destination, int counter, Trace trace)
{
board.Set(knight.X, knight.Y, counter);
if (knight.IsInPoint(destination))
{
if (!trace.IsShorterThen(counter))
{
trace.Counter = counter;
trace.Board = board;
Console.WriteLine("Better trace");
Console.WriteLine("Counter: " + trace.Counter);
Console.WriteLine(trace.Board);
}
return;
}
counter++;
Point[] moves = knight.AllPossibleMoves();
foreach(Point point in moves)
{
if (board.Contains(point) && board.IsFree(point))
{
knight.MoveTo(point);
Move(knight, board.GetCopy(), destination, counter, trace);
}
}
}
每次找到更好的跟踪时,都会覆盖跟踪。但对于8 * 8板,执行需要很长时间。
对于您的代码,我建议您尝试Console.WriteLine()
确保一切正常。也许,你Lenta
没有像你期望的那样被覆盖,这会导致无限递归。尝试跟踪您的函数的每个操作,以找到问题的根源。
这是我的主要功能:
static void Main(string[] args)
{
Knight knight = new Knight(0, 0);
Board board = new Board(8, 8);
Point destination = new Point(0, 4);
Trace bestTrace = new Trace();
MoveFirstSolution(knight, board, destination, 1, bestTrace);
Console.WriteLine("Best trace: " + bestTrace.Counter);
Console.WriteLine(bestTrace.Board);
Console.ReadLine();
}
以及其他必需的类,所以你可以尝试它作为工作示例。
class Trace
{
public Trace()
{
this.Board = null;
this.Counter = -1;
}
public Trace(Board board, int counter)
{
this.Board = board;
this.Counter = counter;
}
public bool IsShorterThen(int counter)
{
return this.Counter > 0 && this.Counter <= counter;
}
public Board Board { get; set; }
public int Counter { get; set; }
}
class Board
{
private int[][] _board;
public Board(int N, int M)
{
this._board = new int[N][];
for (int i = 0; i < N; i++)
{
this._board[i] = new int[M];
for (int j = 0; j < M; j++)
{
this._board[i][j] = 0;
}
}
}
public int N
{
get
{
return this._board.Length;
}
}
public int M
{
get
{
return this._board.Length > 0 ? this._board[0].Length : 0;
}
}
public Board GetEmptyCopy()
{
return new Board(this.N, this.M);
}
public Board GetCopy()
{
Board b = new Board(this.N, this.M);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
b.Set(i, j, this.Get(i, j));
}
}
return b;
}
public bool Contains(int i, int j)
{
return (i >= 0) && (i < this.N) && (j >= 0) && (j < this.M);
}
public bool Contains(Point point)
{
return this.Contains(point.X, point.Y);
}
public bool IsFree(int i, int j)
{
return this._board[i][j] == 0;
}
public bool IsFree(Point point)
{
return this.IsFree(point.X, point.Y);
}
public void Set(int i, int j, int val)
{
this._board[i][j] = val;
}
public int Get(int i, int j)
{
return this._board[i][j];
}
public override string ToString()
{
string str = "";
for (int i = 0; i < this.N; i++)
{
for (int j = 0; j < this.M; j++)
{
str += String.Format("{0, 3}", this._board[i][j]);
}
str += "\r\n";
}
return str;
}
}
class Knight
{
public Knight(int x, int y)
{
this.X = x;
this.Y = y;
}
public int X { get; private set; }
public int Y { get; private set; }
public Point[] AllPossibleMoves()
{
Point[] moves = new Point[8];
moves[0] = new Point(this.X + 1, this.Y + 2);
moves[1] = new Point(this.X + 1, this.Y - 2);
moves[2] = new Point(this.X + 2, this.Y + 1);
moves[3] = new Point(this.X + 2, this.Y - 1);
moves[4] = new Point(this.X - 1, this.Y + 2);
moves[5] = new Point(this.X - 1, this.Y - 2);
moves[6] = new Point(this.X - 2, this.Y + 1);
moves[7] = new Point(this.X - 2, this.Y - 1);
return moves;
}
public bool IsInPoint(int x, int y)
{
return this.X == x && this.Y == y;
}
public bool IsInPoint(Point point)
{
return this.IsInPoint(point.X, point.Y);
}
public void MoveTo(int x, int y)
{
this.X = x;
this.Y = y;
}
public void MoveTo(Point point)
{
this.MoveTo(point.X, point.Y);
}
}
class Point
{
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public int X { get; private set; }
public int Y { get; private set; }
}
希望这有帮助。