Try   HackMD

6.24 騎士的旅程Knight tour

//https://liuxiaozhu.github.io/algorithm-test/AlgorithmGossip/KnightTour.htm
#include <stdio.h>
#define N 8
int travel(int x, int y);
int board[N][N] = {0}; 
int main(void) {
    travel(5, 6); //起始點
    for(int i=0; i<N; i++) {
        for(int j=0; j<N; j++)
            printf("%3d", board[i][j]);
        putchar('\n');
    }
} 
int travel(int x, int y) {
    // 騎士可走的八個方向
    int ktmove1[N] = {-2, -1, 1, 2, 2, 1, -1, -2};
    int ktmove2[N] = {1, 2, 2, 1, -1, -2, -2, -1};

    // 測試下一步的出路
    int nexti[N] = {0};
    int nextj[N] = {0};

    int i=x, j=y, k, m, l;
    int tmpi, tmpj;
    int count, min, tmp;
    board[i][j] = 1; //起點為1

    for(m = 2; m < 65; m++) { //m步數. 總步數64.
        l = 0;

        // 試探八個方向
        for(k = 0; k < N; k++) {
            tmpi = i + ktmove1[k];
            tmpj = j + ktmove2[k];

            // 如果是邊界了,不可走
            if (tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7) continue;

            // 如果這個方向可走,記錄下來
            if (board[tmpi][tmpj] == 0) {
                nexti[l] = tmpi;
                nextj[l] = tmpj;
                l++; // 可走的方向加一個
            }
        }
        count = l;

        // 如果可走的方向為0個,返回
        if (count == 0) return 0;
        else if (count == 1) {
            // 只有一個可走的方向
            // 所以直接是最少出路的方向
            min = 0;
        }
        else {
            int exists[N]={0}; // 記錄出路的個數
            // 找出下一個位置的出路數
            for(l = 0; l < count; l++) {
                for(k = 0; k < N; k++) {
                    tmpi = nexti[l] + ktmove1[k];
                    tmpj = nextj[l] + ktmove2[k];

                    if (tmpi < 0 || tmpj < 0 || tmpi > 7 || tmpj > 7) continue;
                    if (board[tmpi][tmpj] == 0) exists[l]++;
                }
            }

            tmp = exists[0];
            min = 0;

            // 從可走的方向中尋找最少出路的方向
            for(l = 1; l < count; l++) {
                if(exists[l] < tmp) {
                    tmp = exists[l];
                    min = l;
                }
            }
        }

        // 走最少出路的方向
        i = nexti[min];
        j = nextj[min];
        board[i][j] = m;
    }
    return 1;
} 

方法二

//https://openhome.cc/zh-tw/algorithm/basics/knight-tour/
#include <stdio.h> 
#define N 8
typedef struct {
    int x; 
    int y;
} Step;

Step step(int, int);
void travel(int[][N], Step);
void possible(int[][N], Step, int*);
int count(int*);
Step get(Step, int*, int);
Step hard(int[][N], Step, int*);
int isVisitable(int[][N], Step);

int main() {
    int board[N][N] = {0};
    travel(board, step(5, 6)); //起始點(5,6)
    
    for(int i = 0; i<N; i++) {
        for(int j = 0; j<N; j++)
            printf("%3d", board[i][j]);
        printf("\n");
    }
} 
Step step(int x, int y) { //回傳位置
    Step s = {x, y};
    return s;
}
void travel(int board[][N], Step start) {
    board[start.x][start.y] = 1;
    Step current = start;
    
    for(int s=2; s<65; s++) { //s步數. 總步數64.
        int possibleSteps[N] = {0};
        possible(board, current, possibleSteps); //計算possibleSteps陣列
        
        int c = count(possibleSteps); //計算總共幾個位置可走
        if(c == 0) break; //遊歷失敗
        if(c == 1) //只有一步可走
            current = get(current, possibleSteps, 1);
        //找出下一步出路最少的格子。如果出路值相同,則選第一個遇到的出路。
        //走最少出路的格子,記錄騎士的新位置。
        else
            current = hard(board, current, possibleSteps);
        board[current.x][current.y] = s; //紀錄走的順序
    }
}
void possible(int board[][N], Step current, int* possibleSteps) {
     int dirs[8][2] = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, 
                       	  {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
     for(int i=0; i<N; i++) {
         Step s = step(current.x + dirs[i][0], current.y + dirs[i][1]);
         if(isVisitable(board, s)) possibleSteps[i] = 1;
     }
}
int isVisitable(int board[][N], Step step) {
    return step.x > -1 && step.x < N &&
           step.y > -1 && step.y < N &&
           !board[step.x][step.y];
}
int count(int* possibleSteps) {
    int c=0, i=0;
    for (; i<N; i++) 
    	if (possibleSteps[i]) c++;
    return c;
}
//得到下一步要走的位置
Step get(Step current, int* possibleSteps, int number) {
    //騎士可走的八個方向
    int dirs[8][2] = {{-2, 1}, {-1, 2}, {1, 2},   {2, 1}, 
                      {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
    int c=0, i=0;
    for (; i<N; i++) {
        if (possibleSteps[i]) c++;
        if (c == number) break;
    }
    return step(current.x + dirs[i][0], current.y + dirs[i][1]);
}
Step hard(int board[][N], Step current, int* possibleSteps) {
    int minPossibleSteps[N] = {0};
    possible(board, get(current, possibleSteps, 1), minPossibleSteps);

    int minIndex=0, i=1;
    for(; i < count(possibleSteps); i++) {
        int nextPossibleSteps[N] = {0};
        Step s = get(current, possibleSteps, i+1);
        possible(board, s, nextPossibleSteps);
        if(count(nextPossibleSteps) < count(minPossibleSteps)) {
            minIndex = i;
            for(int j=0; j<N; j++)
                minPossibleSteps[j] = nextPossibleSteps[j];
        }
    }
    return get(current, possibleSteps, minIndex + 1);
}
/*(5,6)
 56 11 58 31 54 13 18 33
 47 30 55 12 59 32 53 14
 10 57 48 63 50 17 34 19
 29 46 41 60 39 62 15 52
 42  9 64 49 16 51 20 35
 25 28 45 40 61 38  1  4
  8 43 26 23  6  3 36 21
 27 24  7 44 37 22  5  2
 
 (5,5)
 63 48  9 50 19 22 11 24
  8 51 64 47 10 25 18 21
 59 62 49 34 43 20 23 12
 52  7 58 61 46 35 26 17
 57 60 53 42 33 44 13 36
  6 41 32 45 54  1 16 27
 31 56 39  4 29 14 37  2
 40  5 30 55 38  3 28 15
 
 (5,4)X
 34 31 10  0 26 29  8  5
 11  0 33 30  9  6 23 28
 32 35  0 25 48 27  4  7
  0 12 59 36 53 24 49 22
 60 43 54 47 58 37 18  3
 13 46 57 52  1 50 21 38
 42 55 44 15 40 19  2 17
 45 14 41 56 51 16 39 20
 
 (5,3)
 29 26 11 62 55 24  9  6
 12 63 28 25 10  7 54 23
 27 30 59 56 61 50  5  8
 64 13 48 43 58 53 22 37
 31 44 57 60 49 38 51  4
 14 47 42  1 52 19 36 21
 41 32 45 16 39 34  3 18
 46 15 40 33  2 17 20 35
 
 (5,2)
 34 61  6 45 36 49  8 47
  5 44 35 62  7 46 27 38
 64 33 60 41 50 37 48  9
 43  4 63 54 59 28 39 26
 32 55 42 51 40 53 10 19
  3 14  1 58 29 20 25 22
 56 31 16 13 52 23 18 11
 15  2 57 30 17 12 21 24
 
 (5,1)
 31 28 13 48 43 26 11  8
 14 53 30 27 12  9 44 25
 29 32 49 54 47 42  7 10
 52 15 56 63 50 45 24 41
 33 62 51 46 55 58 37  6
 16  1 64 57 36 21 40 23
 61 34  3 18 59 38  5 20
  2 17 60 35  4 19 22 39
  
  (5,0)
 14 29 10 41 24 27  8 45
 11 42 13 28  9 44 23 26
 30 15 60 43 40 25 46  7
 59 12 31 52 57 48 39 22
 16 53 58 61 32 51  6 47
  1 64 33 54 49 56 21 38
 34 17 62  3 36 19 50  5
 63  2 35 18 55  4 37 20
 
 (5,-1)X
 23  8 45 40 25 10 29 50
 44 41 24  9 46 51 26 11
  7 22 43 58 39 28 49 30
 42 59 38 47 52 57 12 27
 21  6 61 56 37 48 31  1
 60  3 36 53 62 55 16 13
  5 20  0 34 15 18 63 32
  2 35  4 19 54 33 14 17
*/