patterncppMinor
Shortest knight path
Viewed 0 times
pathknightshortest
Problem
In preparing a review of this question, I decided to rewrite the code from scratch using a more object oriented approach as I suggested in my review.
To recapitulate the problem statement, we are given an input such as the following:
The two integers are the number of rows and columns respectively, and the lines that follow are the board to be examined. A knight is placed at starting point
The output of the program is the minimum number of valid knight moves to get from
The algorithm terminates when either there are no valid moves left or a path has been found to the destination.
I'm interested in a general review, but in particular, the repeated calls to
knight.cpp
```
#include
#include
#include
#include
class Board
{
public:
Board(int n, int m) :
start{ERR},
finish{ERR},
rows{n},
cols{m},
map{new char[rows*cols]}
{}
virtual ~Board() { delete[] map; }
int mindistance() const {
if (finish == ERR || start == ERR) {
return ERR;
}
return measure(start, finish);
}
friend std::istream& operator>>(std::istream& in, Board &b) {
int a = 0;
for (int i = b.rows; i; --i) {
for (int j = b.cols; j; --j, ++a) {
in >> b.map[a];
switch(b.map[a]) {
To recapitulate the problem statement, we are given an input such as the following:
6 5
. s . . .
. d . . .
. . x . .
. . x . .
. . . . .
. . . . .The two integers are the number of rows and columns respectively, and the lines that follow are the board to be examined. A knight is placed at starting point
s and must travel to the destination at d without landing on any occupied squares (denoted by x). Open squares are marked with . and whitespace must separate each square in the input.The output of the program is the minimum number of valid knight moves to get from
s to d or the word "NO" if there is no path. The search uses a simple breadth first search. Each call to validMoves generates a std::vector of all unvisited squares that can be reached with one move of a knight originating on any of the squares indicated in the input std::vector moves.The algorithm terminates when either there are no valid moves left or a path has been found to the destination.
I'm interested in a general review, but in particular, the repeated calls to
tryMove() seem somewhat inelegant to me, but I didn't come up with anything that I thought was better.knight.cpp
```
#include
#include
#include
#include
class Board
{
public:
Board(int n, int m) :
start{ERR},
finish{ERR},
rows{n},
cols{m},
map{new char[rows*cols]}
{}
virtual ~Board() { delete[] map; }
int mindistance() const {
if (finish == ERR || start == ERR) {
return ERR;
}
return measure(start, finish);
}
friend std::istream& operator>>(std::istream& in, Board &b) {
int a = 0;
for (int i = b.rows; i; --i) {
for (int j = b.cols; j; --j, ++a) {
in >> b.map[a];
switch(b.map[a]) {
Solution
-
A standard way to loop over a regular set of moves is to prepare an array of deltas:
-
It feels that
A standard way to loop over a regular set of moves is to prepare an array of deltas:
using square = std::pair;
std::vector deltas = {
{1, 2}, {1, -2}, {-1, 2}, {-1, -2},
{2, 1}, {2, -1}, {-2, 1}, {-2, -1}
};
for (auto delta: deltas) {
tryMove(x + delta.first, y + delta.second);
}-
It feels that
std::pair generally represents a square better than a single integer.Code Snippets
using square = std::pair<int, int>;
std::vector<square> deltas = {
{1, 2}, {1, -2}, {-1, 2}, {-1, -2},
{2, 1}, {2, -1}, {-2, 1}, {-2, -1}
};
for (auto delta: deltas) {
tryMove(x + delta.first, y + delta.second);
}Context
StackExchange Code Review Q#119901, answer score: 2
Revisions (0)
No revisions yet.