0

For knight tour problem, I came up with this answer; however, it just prints one answer. I don't know how to print all answers. I know I should change the output of find tour into void to avoid finishing but I don't know how. Can anyone modify it?

#include <iostream>
using namespace std;

const int ROW_COUNT = 6;
const int COL_COUNT = 6;
const int POSSIBLE_MOVES = 8;

int row_delta[POSSIBLE_MOVES] = {2, 1, -1, -2, -2, -1, 1, 2};
int col_delta[POSSIBLE_MOVES] = {-1, -2, -2, -1, 1, 2, 2, 1};

int board[ROW_COUNT][COL_COUNT];

void print_board() {
    for (int i = 0; i < ROW_COUNT; i++) {
        for (int j = 0; j < COL_COUNT; j++) {
            if (board[i][j] < 10)
                cout << ' ';
            cout << board[i][j] << ' ';
        }
        cout << endl;
    }
    cin.get();
}

bool find_tour(int move_no, int current_row, int current_col) {
    // uncomment the following two lines for debugging:
     //cout << move_no << endl;
     //print_board();

    if (move_no == ROW_COUNT * COL_COUNT)
        return true;

    for (int move = 0; move < POSSIBLE_MOVES; move++) {
        int new_row = current_row + row_delta[move];
        int new_col = current_col + col_delta[move];

        if (new_row < 0 || new_row >= ROW_COUNT || new_col < 0 || new_col >= COL_COUNT)
            continue;

        if (board[new_row][new_col] != 0)
            continue;

        board[new_row][new_col] = move_no + 1;
        if (find_tour(move_no + 1, new_row, new_col))
            return true;
        board[new_row][new_col] = 0;
    }
    return false;
}

void solve(int init_row, int init_col) {
    for (int row = 0; row < ROW_COUNT; row++)
        for (int col = 0; col < COL_COUNT; col++)
            board[row][col] = 0;

    board[init_row][init_col] = 1;
    if (find_tour(1, init_row, init_col))
        print_board();
    else
        cout << "Failed to find a tour!\n";
}

int main() {
    solve(2, 3);
}
false
  • 10,264
  • 13
  • 101
  • 209
mohammad amin
  • 47
  • 2
  • 8
  • Looks like you could use a loop. *For each location on the board*, solve at the given location. – Thomas Matthews Oct 09 '15 at 04:56
  • Search StackOverflow for "c++ knights tour" for more examples. – Thomas Matthews Oct 09 '15 at 04:57
  • @ThomasMatthews Yeah, I already searched. You see, my problem is not how to come up with "one answer" as my code gives one, but it is about finding all the routes. And I didn't get where do you mean I should put the loop. – mohammad amin Oct 09 '15 at 05:11
  • 1
    Your code is close; it needs to use backtracking. Each time find_tour calls find_tour, you should not return if it succeeds. Instead reverse the move and try the other possible moves. You should print_board when "move_no == ROW_COUNT * COL_COUNT)", because that's a solution. – cliffordheath Oct 09 '15 at 05:28
  • @cliffordheath Thanks man! It worked. – mohammad amin Oct 09 '15 at 05:54
  • 1
    Learn how to use a debugger. With the debugger, you can then step through the code and determine the place at which it's doing something wrong. This technique is essential for programming, in particular it is useful in order to get familiar with new code. – Ulrich Eckhardt Oct 09 '15 at 05:58
  • 1
    Also don't wait for this to find all solutions. I left a highly-optimised version of this running for three weeks once (it found many thousands of solutions), and it had backtracked only a tiny part of the way. I suspect the total runtime is longer than the remaining lifespan of the universe. – cliffordheath Oct 09 '15 at 06:27

1 Answers1

2

Following from my comment, this code should work:

#include <iostream>
using namespace std;

const int ROW_COUNT = 6;
const int COL_COUNT = 6;
const int POSSIBLE_MOVES = 8;

int row_delta[POSSIBLE_MOVES] = {2, 1, -1, -2, -2, -1, 1, 2};
int col_delta[POSSIBLE_MOVES] = {-1, -2, -2, -1, 1, 2, 2, 1};

int board[ROW_COUNT][COL_COUNT];

void print_board() {
    for (int i = 0; i < ROW_COUNT; i++) {
        for (int j = 0; j < COL_COUNT; j++) {
            if (board[i][j] < 10)
                cout << ' ';
            cout << board[i][j] << ' ';
        }
        cout << endl;
    }
    cin.get();
}

find_tour(int move_no, int current_row, int current_col) {
    // uncomment the following two lines for debugging:
     //cout << move_no << endl;
     //print_board();

    if (move_no == ROW_COUNT * COL_COUNT)
    {
        print_board();
        return;
    }

    for (int move = 0; move < POSSIBLE_MOVES; move++) {
        int new_row = current_row + row_delta[move];
        int new_col = current_col + col_delta[move];

        if (new_row < 0 || new_row >= ROW_COUNT || new_col < 0 || new_col >= COL_COUNT)
            continue;

        if (board[new_row][new_col] != 0)
            continue;

        board[new_row][new_col] = move_no + 1;
        find_tour(move_no + 1, new_row, new_col);
        board[new_row][new_col] = 0;
    }
}

void solve(int init_row, int init_col) {
    for (int row = 0; row < ROW_COUNT; row++)
        for (int col = 0; col < COL_COUNT; col++)
            board[row][col] = 0;

    board[init_row][init_col] = 1;
    find_tour(1, init_row, init_col);
}

int main() {
    solve(2, 3);
}
cliffordheath
  • 2,536
  • 15
  • 16