实训总结报告
阶段划分
- Stage 1 (熟悉GridWorld基本架构以及Java编程语言)
- Stage 2 (完成Par2 - Part5)
- Stage 3 (接触图像处理,学习并DP算法,BP算法,认识并设计估价函数)
报告中所示图片主要见项目网站。
具体工作
1.1 Stage 1
1.1.1 编程工具
Stage 1 主要是学习了Vi,Java,Junit,Ant这四个必要的工具,具体自学报告见Stage1。
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.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
详情请点击前方连接。
1.2.3. 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 需求:
即函数实现后,可以通过一张图分析出该图像的RGB和灰度图像。
1.3.2 MazeBug(DFS)
1.3.2.1 需求:
1.3.2.2 深度优先算法介绍:
1.3.3 Jigsaw (BFS)
1.3.3.1 需求分析
1.3.3.2 搜索策略
1.3.3.3 具体任务
1.3.3.4 BFS实现
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对象属性进行行为扩充,让我们熟悉java语言中接口跟继承的用法,
2.3 Stage 3
这一部分主要是考察我们的算法掌握能力,比如DFS与BFS算法,这两个算法是比较常用的搜索算法。图像处理方面,考核的则是对于JAVA自带的API的适用和掌握。至于第三阶段的估价函数,是实训中自主程度最大的一个部分,在我看来也是比较综合考验的部分.
虽然我在第三阶段的实训的完成过程中,比之其他两个阶段会有很多不完善的地方,但是第三阶段给我带来的新奇体验是最为明显的。