中級實訓總結報告

yangsy26發表於2020-11-09

實訓總結報告

階段劃分

  1. Stage 1 (熟悉GridWorld基本架構以及Java程式語言)
  2. Stage 2 (完成Par2 - Part5對GridWorld的擴充套件)
  3. Stage 3 (接觸影像處理,學習並DP演算法,BP演算法,認識並設計估價函式)

具體工作

1.1 Stage 1

1.1.1 程式設計工具的學習

Stage 1 主要是學習了Vi,Java,Junit,Ant這四個必要的工具,方便後面實訓工作的進行,具體自學報告已經在階段一中提交過了。

1.1.2 小程式的設計(計算器)

需求分析:
在這裡插入圖片描述
由於我上學期選了JAVA的選修課,所以直接將我之前寫的程式碼複製了。
程式碼展示:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Stack;
 
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
 
public class Calculator extends JApplet implements ActionListener
{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTextField textField = new JTextField("輸入");
	String operator = "";
	String input = "";
	boolean flag =  true;
	
	public void init()//覆寫Applet裡邊的init方法
	{
		Container C = getContentPane();
		JButton b[] = new JButton[16];
		JPanel panel = new JPanel();
		C.add(textField, BorderLayout.NORTH);
		C.add(panel,BorderLayout.CENTER);
		panel.setLayout(new GridLayout(4,4,5,5));
		String name[]={"7","8","9","+","4","5","6","-","1","2","3","*","0","C","=","/"};//設定 按鈕
		for(int i=0;i<16;i++)//新增按鈕
		{
			b[i] = new JButton(name[i]);
			b[i].setBackground(new Color(192,192,192));
			b[i].setForeground(Color.BLUE);//數字鍵 設定為 藍顏色
			if(i%4==3)
				b[i].setForeground(Color.RED);
			b[i].setFont(new Font("宋體",Font.PLAIN,20));//設定字型格式
			panel.add(b[i]);
			b[i].addActionListener(this);
		}
		b[13].setForeground(Color.RED);//非數字鍵,即運算鍵設定為紅顏色
		b[13].setForeground(Color.RED);
	}
	public void actionPerformed(ActionEvent e) 
	{
		int cnt = 0;
		String actionCommand = e.getActionCommand();
		if(actionCommand.equals("+")||actionCommand.equals("-")||actionCommand.equals("*") ||actionCommand.equals("/"))
			input +=" "+actionCommand+" ";//設定輸入,把輸入的樣式改成 需要的樣子
		else if(actionCommand.equals("C"))
			input = "";
		else if(actionCommand.equals("="))//當監聽到等號時,則處理 input
		{
			input+= "="+compute(input);
			textField.setText(input);
			input="";
			cnt = 1;
		}
		else
			input += actionCommand;//數字為了避免多位數的輸入 不需要加空格
		if(cnt==0)
		textField.setText(input);
	}
	private String compute(String input)//即1237 的 樣例
	{
		String str[];
		str = input.split(" ");
		Stack<Double> s = new Stack<Double>();
		double m = Double.parseDouble(str[0]);
		s.push(m);
		for(int i=1;i<str.length;i++)
		{
			if(i%2==1)  
            {  
                if(str[i].compareTo("+")==0)  
                {  
                    double help = Double.parseDouble(str[i+1]);  
                    s.push(help);  
                }  
                  
                if(str[i].compareTo("-")==0)  
                {  
                    double help = Double.parseDouble(str[i+1]);  
                    s.push(-help);  
                }  
                  
                if(str[i].compareTo("*")==0)  
                {  
                    double help = Double.parseDouble(str[i+1]);  
                    double ans = s.peek();//取出棧頂元素  
                    s.pop();//消棧  
                    ans*=help;  
                    s.push(ans);  
                }  
                  
                if(str[i].compareTo("/")==0)  
                {  
                    double help = Double.parseDouble(str[i+1]);  
                    double ans = s.peek();  
                    s.pop();  
                    ans/=help;  
                    s.push(ans);  
                }  
            }  
        }  
        double ans = 0d;  
        while(!s.isEmpty())  
        {  
            ans+=s.peek();  
            s.pop();  
        }  
        String result = String.valueOf(ans);
        return result;
	}
	public static void main(String args[])
	{
		JFrame frame = new JFrame("Calculator");
		Calculator applet = new Calculator();
		frame.getContentPane().add(applet, BorderLayout.CENTER);
		applet.init();//applet的init方法
		applet.start();//執行緒開始
		frame.setSize(450, 450);//設定視窗大小
		frame.setVisible(true);//設定視窗可見
	}
 
}

心得體會:

  1. 學習新的程式語言與程式設計工具的時候不能好高騖遠,需要從簡單的小程式做起,慢慢提升自己的熟練度,並且在不斷地練習中積累相關知識。
  2. 關於Sonar-runner檢驗也是自己需要注意的部分,在編寫Java程式時候,儘量把類內的變數宣告為私有成員,同時建立一個新的方法呼叫私有成員;也要注意避免使用magic number,如果要直接使用某個常量,我們可以先將常量存到一個const 常量裡面,隨後去訪問這個const 常量。

1.1.3 執行GridWorld主體框架

需求分析:
在這裡插入圖片描述

實物展示:
在這裡插入圖片描述

1.2 Stage 2

1.2.1 Part 2

1.2.1.1 Dancing_bug

需求:實現一個bug,運動的軌跡是一箇中心對稱圖形
圖示:
在這裡插入圖片描述

1.2.1.2 Z_bug

需求:實現一個bug,運動軌跡是一個字母Z
圖示:
在這裡插入圖片描述

1.2.1.3 Spiral_bug

需求:實現一個bug,運動軌跡是在一個無界的Grid中完成直線旋轉運動
圖示:
在這裡插入圖片描述
1.2.1.4 Circle_bug

需求:實現一個bug,運動軌跡是一個圓形
圖示:
在這裡插入圖片描述

1.2.2 Part 3

由於Part3 部分已經完成了測試報告與設計報告,所以這裡不再贅述,詳情請點選前方連線

1.2.3 Part 4

由於Part4與Part2實現的功能類似,都是基於GridWorld對Gird中的actor的行為進行擴充,所以這裡不再一一贅述。

1.2.4. Part 5

Part 5是對Grid進行的擴充,分別是使用連結串列,雜湊實現有限Grid以及通過二維陣列維數的擴充套件完成對無限Grid的設計

1.2.4.1 連結串列實現有限Grid

由於所要實現的介面外觀都是相同的,這裡只陳列程式碼部分

    //use the link-list to implement the grid

import info.gridworld.grid.Location;
import info.gridworld.grid.AbstractGrid;
import java.util.ArrayList;

public class SparseBoundedGrid<E> extends AbstractGrid<E>
{	
	//my own array
	private SparseGridNode[] sparseArray;
	private int col;
	private int row;
	
	//constructor
	public SparseBoundedGrid(int rows, int cols) {
		if (rows <= 0) {
			throw new IllegalArgumentException("rows <= 0");
		}
		if (cols <= 0) {
			throw new IllegalArgumentException("cols <= 0");
		}
		this.sparseArray = new SparseGridNode[rows];
		this.row = rows;
		this.col = cols;
	}

	public int getNumRows() {
		return row;
	}	
	
	public int getNumCols() {
		return col;
	}
	
	public boolean isValid(Location loc) {
		return 0 <= loc.getRow() && loc.getRow() < getNumRows() && 0 <= loc.getCol() && loc.getCol() < getNumCols();
	}
	
	//find the position have been occupied
	public ArrayList<Location> getOccupiedLocations() {
		ArrayList<Location> theLocations = new ArrayList<Location>();
		// Look at all grid locations.
		for (int r = 0; r < getNumRows(); r++) {
			if (sparseArray[r] == null) {
				continue;
			} 
			else {
				// If there's an object at this location, put it in the array.
				SparseGridNode sn = sparseArray[r];
				while (sn != null) {
					Location loc = new Location(r, sn.getCol());
					theLocations.add(loc);
					sn = sn.getNext();
				}
			}
		}
		return theLocations;
	}
	
	//get function:find the object to the grid
	public E get(Location loc) {
		if (loc == null) {
			throw new IllegalArgumentException("loc == null");
		}
		if (!isValid(loc)) {
			throw new IllegalArgumentException("Location " + loc + " is not valid");
		}
		
		// find the position is valid or not
		SparseGridNode sn = sparseArray[loc.getRow()];
		while (sn != null) {
			if (sn.getCol() == loc.getCol()) {
				return (E) sn.getOccupant();
			}
			sn = sn.getNext();
		}
		
		// if not find return null
		return null;
	}

	// put funcion:Add the object to the grid.
	public E put(Location loc, E obj) {
		if (loc == null) {
			throw new IllegalArgumentException("loc == null");
		}
		if (!isValid(loc)) { 
			throw new IllegalArgumentException("Location " + loc + " is not valid");
		}
		if (obj == null) {
			throw new NullPointerException("obj == null");
		}
		
		//judge it it is the position is occupied
		E oldOccupant = get(loc);
		SparseGridNode snode = sparseArray[loc.getRow()];
    
		SparseGridNode newSnode = new SparseGridNode(obj, loc.getCol(), snode);
		sparseArray[loc.getRow()] = newSnode;
		return  oldOccupant;
	}

	// Remove the object from the grid.
	public E remove(Location loc) {
		if (loc == null) {
			throw new IllegalArgumentException("loc == null");
		}
		if (!isValid(loc)) {
			throw new IllegalArgumentException("Location " + loc  + " is not valid");
        	}
		E res = get(loc);
		
        //first step to find the actors
        SparseGridNode snode = sparseArray[loc.getRow()];
        if (snode == null) {
            return res;
        }
        
        //first to find the col
        if (snode.getCol() == loc.getCol()) {
            sparseArray[loc.getRow()] = snode.getNext();
            return res;
        }
        SparseGridNode pre = snode;
        
        //find the next position
        while (snode != null) {
            if (snode.getCol() == loc.getCol()) {
                break;
            }
            pre = snode;
            snode = snode.getNext();
        }
        if (pre != null) {
            pre.setNext(snode.getNext());
            snode = null;
        }
        return res;
    }
}

1.2.4.2 雜湊實現有限Grid

// use hash to implement the grid
import info.gridworld.grid.Location;
import info.gridworld.grid.AbstractGrid;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;

public class SparseBoundedGrid2<E> extends AbstractGrid<E> {
    //parameter
	private int row;
    private int col;
    private Map<Location, E> occupantHMap;
    
    //constructor
    public SparseBoundedGrid2(int rows, int cols) {
        if (rows <= 0) {
            throw new IllegalArgumentException("rows <= 0");
        }
        if (cols <= 0) {
            throw new IllegalArgumentException("cols <= 0");
        }
        occupantHMap = new HashMap<Location, E>();
        this.row = rows;
        this.col = cols;
    }

    public int getNumRows() {
        return row;
    }
    public int getNumCols() {
        return col;
    }
    
    //judge if it is valid 
    public boolean isValid(Location loc) {
        return 0 <= loc.getRow() && loc.getRow() < getNumRows()
                && 0 <= loc.getCol() && loc.getCol() < getNumCols();
    }
    // find the occupation
    public ArrayList<Location> getOccupiedLocations() {
        ArrayList<Location> Locations = new ArrayList<Location>();
        for (Location loc : occupantHMap.keySet()) {
            Locations.add(loc);
        }
        return Locations;
    }
    //get function 
    public E get(Location loc) {
        if (loc == null) {
            throw new IllegalArgumentException("loc == null");
        }
        //judege if it is valid
        if (!isValid(loc)) {
            throw new IllegalArgumentException("Location " + loc
                    + " is not valid");
        }
        return occupantHMap.get(loc);
    }
    
    //put  function
    public E put(Location loc, E obj) {
        if (loc == null) {
            throw new IllegalArgumentException("loc == null");
        }
        
        //judge if it is valid 
        if (!isValid(loc)) { 
            throw new IllegalArgumentException("Location " + loc  + " is not valid");
        }
        if (obj == null) {
            throw new NullPointerException("obj == null");
        }
        return occupantHMap.put(loc, obj);
    }
    //remove function 
    public E remove(Location loc) {
        if (loc == null) {
            throw new IllegalArgumentException("loc == null");
        }
        if (!isValid(loc)) {
            throw new IllegalArgumentException("Location " + loc + " is not valid");
        }
        return occupantHMap.remove(loc);
    }
}

1.2.4.4 新GridWorld介面展示

如圖:
在這裡插入圖片描述

1.3 Stage 3

1.3.1 ImageReader

1.3.1.1 需求分析:在這裡插入圖片描述
1.3.1.2程式展示

如圖:
在這裡插入圖片描述
1.3.2 MazeBug(基於深度優先搜尋演算法)

1.3.2.1 需求分析:
在這裡插入圖片描述
在這裡插入圖片描述
1.3.2.2 深度優先演算法介紹:
在這裡插入圖片描述
1.3.3 Jigsaw (基於寬度優先搜尋演算法)

1.3.3.1 需求分析
在這裡插入圖片描述

1.3.3.2 搜尋策略
在這裡插入圖片描述

1.3.3.3 具體任務
在這裡插入圖片描述
1.3.3.4 寬度優先演算法實現

    public boolean BFSearch(JigsawNode bnode, JigsawNode enode) {
    	//list the next node
        ArrayList<JigsawNode> first = new ArrayList<>();
        //list the next node
        ArrayList<JigsawNode> last = new ArrayList<>();
        beginJNode = bnode;
        endJNode = enode;
        //add the first node
        first.add(bnode);
        //直到待訪問列表為空
        while(!first.isEmpty() ){
        	//find the queue's size
            int firstSize = first.size();
            for(int i = 0; i < firstSize;i++) {
                currentJNode = first.get(0);
                //if the now node == final node return true
                if(currentJNode.equals(enode)) {
                    return true;
                }
                
                for(int j = 0; j < 4; j++) {
                	//find the four part of node
                    if(currentJNode.canMove()[j] == 1) {
                        JigsawNode temp = new JigsawNode(currentJNode);
                        temp.move(j);
                        if(!last.contains(temp)) {
                            first.add(temp);
                        }
                    }
                }
                //move the now node to the queue(arraylist)
                last.add(currentJNode);
                first.remove(0);
            }
        }
        // if can't find the final node return false 
        return false;
    }

1.3.3.5 估價函式

思路:尋找出某一個塊與後一塊不是相差1的個數S1,尋找出錯位塊的個數S2,尋找出錯位塊與空白塊之間的曼哈頓距離和S3,調整權重,構造估價函式F(x) = 2 * S1 + 0 * S2 + 4 * S3 ;

   public void estimateValue(JigsawNode jnode) {
        // 後續節點不正確的數碼個數
        int s = 0;
        int dimension = JigsawNode.getDimension();
        for(int index =1 ; index<dimension*dimension; index++){
            if(jnode.getNodesState()[index]+1!=jnode.getNodesState()[index+1]) {
                s++;
            }
        }
        int e = 0;
        for (int index = 1; index <= dimension*dimension; index++) {
            if (jnode.getNodesState()[index] != endJNode.getNodesState()[index] && 
                jnode.getNodesState()[index] != 0) {
                e++;
            }
        }
        // Distance
        int d = 0;
        for (int i = 1; i <= dimension*dimension; i++) {
            if (jnode.getNodesState()[i] != endJNode.getNodesState()[i] &&
                jnode.getNodesState()[i] != 0) {
                int row1 = getRow(i);
                int row2 = getRow(jnode.getNodesState()[i]);
                int col1 = getCol(i);
                int col2 = getCol(jnode.getNodesState()[i]);
                d += (int)(Math.abs(row1-row2)+Math.abs(col1-col2));
            }
        }
        int z = 0;
        for (int i = 1; i < dimension*dimension; i++) {
            if (jnode.getNodesState()[i] != endJNode.getNodesState()[i]) {
                for (int j = 1; j <= dimension*dimension; j++) {
                    if (jnode.getNodesState()[j] == i) {
                        int row1 = getRow(j);
                        int row2 = getRow(jnode.getNodesState()[0]);
                        int col1 = getCol(j);
                        int col2 = getCol(jnode.getNodesState()[0]);
                        z += (int)(Math.abs(row1-row2)+Math.abs(col1-col2));
                        break;
                    }
                }
                break;
            }
        }
        int value = (int)(4*s+8*d+7*z);
        jnode.setEstimatedValue(value);
    }

1.3.3.6 程式執行
![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20201109233233862.png#pic_center

實訓總結

2.1 Stage 1:

詳情連結

2.2 Stage 2

這一階段主要是基於GridWorld對Bug以及Actor物件屬性進行行為擴充,比如讓一個bug走圓形,走中心對稱圖形等,這一部分更多是讓我們熟悉java語言中介面跟繼承的用法,並沒有太多的涉及到演算法上的知識。
在第二階段,熟練的使用eclipse這個軟體,可以很大程度上縮短自己編譯程式的時間,同時也可以很快的完成程式的執行,而不用繁雜的去輸入各種指令,但是eclipse軟體在配置環境,比如加入各種jar型別檔案的時候,如果設定的路徑不對,就會導致各種引入的包型別錯誤。
總體來說,第二階段應該是中級實訓需要完成單個小任務最多的階段,但是難度相對來說並不算太大,只有part5部分的地圖重新構造時候遇到了點問題,其餘都還是可以自主解決的。

2.3 Stage 3

第三階段是中級實訓的重頭戲,這一部分主要是考察我們的演算法掌握能力,比如DFS與BFS演算法,這兩個演算法是比較常用的搜尋演算法,不管是在解決迷宮問題,還是在解決樹的問題,都是比較常用到的。同時影像處理方面,也是需要注意的,對bitmap的使用還需要進一步掌握,同時ava語言自帶的許多API可以順利的幫助我們完成許多繁瑣的任務。至於第三階段的估值函式,應該是整個實訓中第一次接觸的東西,我想這個估值函式以後可能會在演算法的優化程度上得到應用,同時也為我們日後在設計演算法的時候計算演算法功耗提供了一定的幫助。
雖然我在第三階段的實訓的完成過程中,比之其他兩個階段會有很多不完善的地方,但是第三階段給我帶來的新奇體驗是最為明顯的。

相關文章