首頁 > 軟體

java資料結構和演演算法之馬踏棋盤演演算法

2022-02-14 19:01:21

本文範例為大家分享了java實現演演算法之馬踏棋盤的具體程式碼,供大家參考,具體內容如下

一、馬踏棋盤演演算法介紹

馬踏棋盤演演算法也被稱為騎士周遊問題
將馬隨機放在國際象棋的8×8棋盤Board[0~7][0~7]的某個方格中,馬按走棋規則(馬走日字)進行移動。要求每個方格只進入一次,走遍棋盤上全部64個方格

二、騎士周遊問題的思路分析

1、建立棋盤 chessBoard , 是一個二維陣列
2、將當前位置設定為已經存取,然後根據當前位置,計算馬兒還能走哪些位置,並放入到一個集合中(ArrayList), 最多有8個位置, 每走一步,就使用step+1
3、遍歷ArrayList中存放的所有位置,看看哪個可以走通 , 如果走通,就繼續,走不通,就回溯.
4、判斷馬兒是否完成了任務,使用 step 和應該走的步數比較 , 如果沒有達到數量,則表示沒有完成任務,將整個棋盤置0
5、注意:馬兒不同的走法(策略),會得到不同的結果,效率也會有影響(優化)

三、騎士周遊問題程式碼範例

1、程式碼

package com.rf.data_structure_algorithm.algorithm.horseChessBoard;

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

/**
 * @description: 騎士周遊演演算法範例
 * @author: xz
 */
public class HorseChessBoard {

     static int X;//棋盤的列數
     static int Y;//棋盤的行數
     static boolean visited[]; //標記棋盤的各個位置是否被存取過
     static boolean finished; // 標記是否棋盤的所有位置都被存取 true:成功,false:失敗

    public static void main(String[] args) {
        System.out.println("騎士周遊演演算法,開始執行~~");
        X=8;
        Y=8;
        int row=1;//馬初始位置的行,從編號1開始
        int column=1;//馬初始位置的列,從編號1開始
        //建立棋盤
        int[][] chessboard=new int[X][Y];
        visited=new boolean[X*Y];//初始值都是false
        //測試
        long startTime = System.currentTimeMillis();
        horseChessBoardAlgorithm(chessboard,row-1,column-1,1);
        long endTime = System.currentTimeMillis();
        System.out.println("總共耗時:"+(endTime-startTime)+"毫秒");
        System.out.println("輸出棋盤的最後情況============");
        //輸出棋盤的最後情況
        for(int[] rows : chessboard){
            for(int step : rows){
                System.out.print(step + "t");
            }
            System.out.println();
        }

    }

    /** 
    * @Description: 根據當前位置(Point),計算馬還能走哪些位置(Point)
     *                並放入到一個集合中(ArrayList),最多有8個位置
    * @Param:  curPoint
    * @Author: xz  
    */
    public static ArrayList<Point> next(Point curPoint){
        //建立一個ArrayList
        ArrayList<Point> list =new ArrayList<>();
        //建立一個Point
        Point point=new Point();

        //curPoint.x-2 表示當前位置(curPoint)的列向左移動2列
        //curPoint.x+2 表示當前位置(curPoint)的列向右移動2列
        //curPoint.y-1 表示當前位置(curPoint)的列向上移動1行
        //curPoint.y+1 表示當前位置(curPoint)的列向下移動1行
        // >= 0 表示仍然有空間可走
        if((point.x = curPoint.x-2) >= 0 && (point.y = curPoint.y-1) >= 0 ){//範例圖中指定馬可以走5的位置
            list.add(new Point(point));
        }
        if((point.x = curPoint.x - 1) >=0 && (point.y=curPoint.y-2)>=0) {//範例圖中指定馬可以走6的位置
            list.add(new Point(point));
        }
        if ((point.x = curPoint.x + 1) < X && (point.y = curPoint.y - 2) >= 0) {//範例圖中指定馬可以走7的位置
            list.add(new Point(point));
        }
        if ((point.x = curPoint.x + 2) < X && (point.y = curPoint.y - 1) >= 0) {//範例圖中指定馬可以走0的位置
            list.add(new Point(point));
        }
        if ((point.x = curPoint.x + 2) < X && (point.y = curPoint.y + 1) < Y) {//範例圖中指定馬可以走1的位置
            list.add(new Point(point));
        }
        if ((point.x = curPoint.x + 1) < X && (point.y = curPoint.y + 2) < Y) {//範例圖中指定馬可以走2的位置
            list.add(new Point(point));
        }
        if ((point.x = curPoint.x - 1) >= 0 && (point.y = curPoint.y + 2) < Y) {//範例圖中指定馬可以走3的位置
            list.add(new Point(point));
        }
        if ((point.x = curPoint.x - 2) >= 0 && (point.y = curPoint.y + 1) < Y) {//範例圖中指定馬可以走4的位置
            list.add(new Point(point));
        }
        return list;
    }

    /** 
    * @Description:  騎士周遊演演算法的方法
    * @Param:  chessboard  表示棋盤
    *           row         表示馬兒當前的位置的行 從0開始
    *           column      表示馬兒當前的位置的列  從0開始
    *           step        表示是第幾步 ,初始位置就是第1步
    * @Author: xz  
    */
    public static void horseChessBoardAlgorithm(int[][] chessboard, int row, int column, int step){
        chessboard[row][column] = step;
        visited[row * X + column] = true; //標記該位置已經存取
        //獲取當前位置可以走的下一個位置的集合
        ArrayList<Point> pointList= next(new Point(column, row));
        //對pointList進行排序,排序的規則就是對pointList的所有的Point物件的下一步的位置的數目,進行非遞減排序
        sort(pointList);
        //遍歷 list
        while(!pointList.isEmpty()) {
            Point p = pointList.remove(0);//取出下一個可以走的位置
            //判斷該點是否已經存取過
            if(!visited[p.y * X + p.x]) {//說明還沒有存取過
                horseChessBoardAlgorithm(chessboard, p.y, p.x, step + 1);
            }
        }
        //判斷馬兒是否完成了任務,使用step 和應該走的步數比較 ,
        //如果沒有達到數量,則表示沒有完成任務,將整個棋盤置0
        //說明: step < X * Y  成立的情況有兩種
        //1. 棋盤到目前位置,仍然沒有走完
        //2. 棋盤處於一個回溯過程
        if(step < X * Y && !finished ) {
            chessboard[row][column] = 0;
            visited[row * X + column] = false;
        } else {
            finished = true;
        }
    }

    /**
     * @Description: 根據當前這個一步的所有的下一步的選擇位置,進行非遞減排序, 減少回溯的次數
     * @Param:  ArrayList<Point>
     * @Author: xz
     */
    public static void sort(ArrayList<Point> pointList) {
        pointList.sort(new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                // TODO Auto-generated method stub
                //獲取到o1的下一步的所有位置個數
                int count1 = next(o1).size();
                //獲取到o2的下一步的所有位置個數
                int count2 = next(o2).size();
                if(count1 < count2) {
                    return -1;
                } else if (count1 == count2) {
                    return 0;
                } else {
                    return 1;
                }
            }

        });
    }


}

2、執行main函數,輸出馬在棋盤中走的步驟和位置如下:

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com