1. 程式人生 > 其它 >馬踏棋盤演算法詳解

馬踏棋盤演算法詳解

馬踏棋盤演算法詳解

說明

  1. 馬踏棋盤是指在一個8 * 8的國際棋盤上,從某一位置開始,每次走一個日字,將所有的位置都走一遍
  2. 可以使用遞迴 + 回溯來解決,再加上貪心演算法來優化
  3. 指定某種策略,因為從棋盤的某一位置開始走,它的下一步最多有8個選擇,編寫一個方法,將下一步能走的位置記錄在集合中
  4. 建立一個Boolean陣列記錄當前位置是否走過,如果沒有走過則可以走,否則不能
  5. 從開始的位置開始,遍歷它的下一步可以走的位置的集合,如果當前位置沒有走過,則從當前位置又重新開始走,開始判斷下一次可以走的位置,如果走不通則回溯
  6. 直到所有的位置都訪問過,並且走完相應的步數
  7. 在從集合中選擇下一步時,優先選擇下一步的下一步可選擇的位置較少的位置,體現貪心的思想
  8. 原始碼見下

原始碼及分析

package algorithm.algorithm.horse;

import java.awt.*;
import java.util.ArrayList;
import java.util.Comparator;

/**
 * @author AIMX_INFO
 * @version 1.0
 */
@SuppressWarnings("all")
public class HorseChessBoard {
    //棋盤的列
    public static int X;
    //棋盤的行
    public static int Y;
    //判斷當前位置是否走過
    public static boolean[] visited;
    //判斷是否完成
    public static boolean finished;

    public static void main(String[] args) {
        X = 8;
        Y = 8;
        int row = 2;
        int col = 4;
        visited = new boolean[X * Y];
        int[][] chessboard = new int[X][Y];

        traversalChessBoard(chessboard, row - 1, col - 1, 1);
        show(chessboard);
    }

    //顯示棋盤
    public static void show(int[][] chessboard){
        for (int[] rol : chessboard) {
            for (int step : rol) {
                System.out.print(step + "\t");
            }
            System.out.println();
        }
    }

    /**
     * @param chess 棋盤
     * @param row   從棋盤的哪一行開始
     * @param col   那一列
     * @param step  表示走的第幾步
     */
    public static void traversalChessBoard(int[][] chess, int row, int col, int step) {
        //設定當前位置是第幾步
        chess[row][col] = step;
        //設定當前位置為已經走過
        visited[row * X + col] = true;
        //取出當前位置可以走的下一步的集合
        ArrayList<Point> ps = next(new Point(col, row));
        //使用貪心演算法思想,優先走下一步選擇較少的位置
        ps.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                return next(o1).size() - next(o2).size();
            }
        });
        //然後遍歷下一步所有可以走的點
        while (!ps.isEmpty()) {
            Point p = ps.remove(0);
            if (!visited[p.y * X + p.x]) {
                traversalChessBoard(chess, p.y, p.x, step + 1);
            }
        }
        //噹噹前位置的下一個位置走不通時,判斷是否走完,如果沒有走完,將當前位置置為未走過
        if (step < X * Y && !finished) {
            chess[row][col] = 0;
            visited[row * X + col] = false;
        } else {
            finished = true;
        }

    }

    /**
     * \
     *
     * @param cur 當前位置點的座標
     * @return 返回從當前位置可以走的下一個位置的所有點的集合
     */
    public static ArrayList<Point> next(Point cur) {
        //建立集合儲存可以走的點
        ArrayList<Point> ps = new ArrayList<>();
        //建立一個點
        Point p = new Point();
        if ((p.x = cur.x - 2) >= 0 && (p.y = cur.y - 1) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x - 1) >= 0 && (p.y = cur.y - 2) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 2) < X && (p.y = cur.y - 1) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 1) < X && (p.y = cur.y - 2) >= 0) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 2) < X && (p.y = cur.y + 1) < Y) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x + 1) < X && (p.y = cur.y + 2) < Y) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x - 2) >= 0 && (p.y = cur.y + 1) < Y) {
            ps.add(new Point(p));
        }
        if ((p.x = cur.x - 1) >= 0 && (p.y = cur.y + 2) < Y) {
            ps.add(new Point(p));
        }
        return ps;
    }
}