人工智能编程上机——三种搜索算法显示最短路径与花费时间

三种算法包括DFS、BFS、A*,程序具有可视化界面,拥有打开文件、保存文件的功能,鼠标左键、右键分别选择当前绘制线路的两个端点,鼠标中键选择搜索路径的起点和终点,附上代码。
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main{
	public static void main(String[] args) {
		MainWnd wd = new MainWnd();
	}
	
}


class MainWnd extends JFrame{
	private int X1[],Y1[],X2[],Y2[];//黑线坐标
	private int X1_b[],Y1_b[],X2_b[],Y2_b[];//蓝线坐标
	private int X1_r[],Y1_r[],X2_r[],Y2_r[];//红线坐标
	private int X_s = -1,Y_s = -1,X_e = -1 ,Y_e = -1;
	private int mapp[][];//邻接矩阵
	private int vst[];//遍历标记
	private int dx = 20, dy = 45;//坐标偏移
	private int st = 0,st_b = 0, st_r = 0;//栈顶
	private int start = -1,end = -1;
	JButton btn[]= {new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton(),
			new JButton(),new JButton(),new JButton(),new JButton(),new JButton()};
	JButton Dfs = new JButton("深度优先搜索");
	JButton Bfs = new JButton("宽度优先搜索");
	JButton A_ = new JButton("A*搜索");
	JButton Return = new JButton("重新描绘");
	JButton OPEN = new JButton("打开");
	JButton SAVE = new JButton("保存");
	JLabel Result = new JLabel();//显示答案
	JLabel signature = new JLabel("<html><body><p style='color :orange; font-size:15px; font-family = '宋体''>by:成亦峻<br/>AI Assignment</p></body></html>");
	
	private void Open() {
		FileDialog openDia = new FileDialog(new Frame(), "打开", FileDialog.LOAD);
		openDia.setVisible(true); 
		String address = openDia.getDirectory();
		String name = openDia.getFile();
		File f = new File(address,name);
		BufferedReader reader = null;
		try {
			InputStreamReader isr = new InputStreamReader(new FileInputStream(f) );
			reader = new BufferedReader(isr);
			String msg = "";
			int line_sum = -6;
			while((msg = reader.readLine()) != null) {
				if(line_sum == -6) {
					X_s = Integer.valueOf(msg).intValue();
				}
				else if(line_sum == -5) {
					Y_s = Integer.valueOf(msg).intValue();
				}
				else if(line_sum == -4) {
					X_e = Integer.valueOf(msg).intValue();
				}
				else if(line_sum == -3) {
					Y_e = Integer.valueOf(msg).intValue();
				}
				else if(line_sum == -2) {
					start = Integer.valueOf(msg).intValue();
				}
				else if(line_sum == -1) {
					end = Integer.valueOf(msg).intValue();
				}
				else {
					if(line_sum % 4 == 0) {
						X1[st] = Integer.valueOf(msg).intValue();
					}
					else if(line_sum % 4 == 1) {
						Y1[st] = Integer.valueOf(msg).intValue();
					}
					else if(line_sum % 4 == 2) {
						X2[st] = Integer.valueOf(msg).intValue();
					}
					else {
						Y2[st] = Integer.valueOf(msg).intValue();
						mapp[(X2[st]-dx)/60 + (Y2[st]-dy)/60 * 10][(X1[st]-dx)/60 + (Y1[st]-dy)/60 * 10] = 1;
						mapp[(X1[st]-dx)/60 + (Y1[st]-dy)/60 * 10][(X2[st]-dx)/60 + (Y2[st]-dy)/60 * 10] = 1;
						st ++;
					}
				}
				line_sum ++;
			}
			reader.close();
		}catch(IOException e) {
            e.printStackTrace();
        }
		
	}
	
	private void Save() {	
		FileDialog saveDia = new FileDialog(new Frame(), "保存", FileDialog.SAVE);
		saveDia.setVisible(true);
		String adress = saveDia.getDirectory();
		String name = saveDia.getFile();
		String msg = "";
		msg += X_s + "\r\n" + Y_s + "\r\n" + X_e + "\r\n" + Y_e + "\r\n" + start + "\r\n" +end + "\r\n";
		for(int i = 0;i < st; i ++) {
			msg += X1[i] + "\r\n" + Y1[i] + "\r\n" + X2[i] + "\r\n" + Y2[i] + "\r\n";
		}
		File f = new File(adress,name);
		try {
			FileWriter fw = new FileWriter(f);
			fw.write(msg);
			fw.close();
		}catch(IOException e){
			System.out.println(e.getMessage());
		}
	}
	
	//连线监听
	private MouseListener ML = new MouseListener() {
		public void mouseClicked(MouseEvent e) {
			String now = e.getSource().toString();
			String l = "",r = "";
			int nexti = 0;
			for(int i = 21;;i++) {
				if(now.charAt(i) == ',') {
					nexti = i+1;
					break;
				}
				l += now.charAt(i);
			}
			for(int i = nexti;;i++) {
				if(now.charAt(i) == ',') {
					break;
				}
				r += now.charAt(i);
			}
			int x = Integer.valueOf(l).intValue() + dx;
			int y = Integer.valueOf(r).intValue() + dy;
			int p = e.getButton();
			if(p == 1) {
				X1[st] = x;
				Y1[st] = y;
			}
			else if(p == 3){
				if(X1[st] == -1&& Y1[st] == -1) return;
				X2[st] = x;
				Y2[st] = y;
				mapp[(x-dx)/60 + (y-dy)/60 * 10][(X1[st]-dx)/60 + (Y1[st]-dy)/60 * 10] = 1;
				mapp[(X1[st]-dx)/60 + (Y1[st]-dy)/60 * 10][(x-dx)/60 + (y-dy)/60 * 10] = 1;
				st ++;
			}
			else {
				int Mark = (y-dy)/6 + (x-dx)/60;
				if(start == -1)	{
					start = Mark;
					X_s = x;
					Y_s = y;
				}
				else {
					end = Mark;
					X_e = x;
					Y_e = y;
				}
			}
			
			repaint();
			
			
			
		}
		public void mousePressed(MouseEvent e) {}
		public void mouseReleased(MouseEvent e) {}
		public void mouseEntered(MouseEvent e) {}
		public void mouseExited(MouseEvent e) {}
	};

	//返回监听
	private ActionListener RT = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			st = 0;
			st_b = 0;
			st_r = 0;
			start = -1;
			end = -1;
			X_s = X_e = Y_s = Y_e = -1;
			X1[0] = Y1[0] = -1;
			mapp = null; mapp = new int[100][100];
			Result.setFont(Result.getFont().deriveFont(20.0f));
			Result.setText("<html><body>请连接节点并选取起点与终点<br/>操作方法:<br/>鼠标左键与右键分别选择当前需要连接的两个节点<br/>鼠标中键选择起点和终点<br/>注:任两节点间距离为1,搜索速度为1</body></html>");
			repaint();
		}
	};
	
	//打开文件
	private ActionListener OP = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			st = 0;
			st_b = 0;
			st_r = 0;
			start = -1;
			end = -1;
			X_s = X_e = Y_s = Y_e = -1;
			X1[0] = Y1[0] = -1;
			mapp = null; mapp = new int[100][100];
			Result.setFont(Result.getFont().deriveFont(20.0f));
			Result.setText("<html><body>请连接节点并选取起点与终点<br/>操作方法:<br/>鼠标左键与右键分别选择当前需要连接的两个节点<br/>鼠标中键选择起点和终点<br/>注:任两节点间距离为1,搜索速度为1</body></html>");
			repaint();
			Open();
			repaint();
		}
	};
	
	//保存文件
	private ActionListener SA = new ActionListener() {
		public void actionPerformed(ActionEvent e) {
			Save();
		}
	};
	
	//dfs监听
	private ActionListener DFS = new ActionListener() {
		int min_step = 0x3f3f3f3f,all_time = 0;
		int go_Arr[];
		int st_Arr = 0;
		public void actionPerformed(ActionEvent e) {
			vst = null;
			vst = new int[100];
			st_b = 0;
			st_r = 0;
			go_Arr = null;
			go_Arr = new int[100];
			st_Arr = 0;
			all_time = -1;
			min_step = 0x3f3f3f3f;
			go_Arr[st_Arr] = start;
			st_Arr++;
			dfs(start,0);
			String res = "<html><body>dfs搜索结果如下:<br/>最短距离为:"+min_step+"<br/>搜索所需时间为:"+all_time+"<br/></body></html>"/*"最短距离为:"+min_step+"<br/>搜索花费时间为:"+all_time*/;
			Result.setFont(Result.getFont().deriveFont(24.0f));
			Result.setText(res);
			repaint();
		}
		void dfs(int x,int step) {
			all_time ++;
			if(x == end) {
				min_step = Math.min(step,min_step);
				mark_r();
			}
			if(step >= min_step)	return;
			vst[x] = 1;
			for(int i = 0;i < 100;i++) {
				if(i == x)	continue;
				if(mapp[x][i] == 1) {
					if(vst[i] == 0) {
						vst[i] = 1;
						X1_b[st_b] = (x%10) * 60 + dx;
						Y1_b[st_b] = (x/10) * 60 + dy;
						X2_b[st_b] = (i%10) * 60 + dx;
						Y2_b[st_b] = (i/10) * 60 + dy;
						st_b ++;
						go_Arr[st_Arr++] = i;
						dfs(i,step + 1);
						vst[i] = 0;
						if(st_Arr>0) st_Arr--;
					}
				}
			}
		}
		void mark_r() {
			st_r = 0;
			for(int i=0;i+1<st_Arr;i++) {
				X1_r[st_r] = (go_Arr[i]%10) * 60 + dx;
				Y1_r[st_r] = (go_Arr[i]/10) * 60 + dy;
				X2_r[st_r] = (go_Arr[i+1]%10) * 60 + dx;
				Y2_r[st_r] = (go_Arr[i+1]/10) * 60 + dy;
				st_r ++ ;
			}
		}
	};
	
	//bfs监听
	private ActionListener BFS = new ActionListener() {
		int all_time = 0;
		Queue<Integer> queue;
		boolean ok;
		int Father[],step[];
		public void actionPerformed(ActionEvent e) {
			all_time = 0;
			st_b = st_r = 0;
			vst = null;
			vst = new int[100];
			queue = new LinkedList<Integer>();
			ok = true;
			Father = new int[100];
			step = new int[100];
			queue.offer(start);
			vst[start] = 1;
			bfs();
			
			mark_r();
			String res = "<html><body>bfs搜索结果如下:<br/>最短距离为:"+step[end]+"<br/>搜索所需时间为:"+all_time+"<br/></body></html>"/*"最短距离为:"+min_step+"<br/>搜索花费时间为:"+all_time*/;
			Result.setFont(Result.getFont().deriveFont(24.0f));
			Result.setText(res);
			repaint();
		}
		void bfs() {
			while(!queue.isEmpty() && ok) {
				int x = queue.poll();
				for(int i=0;i<100;i++) {
					if(mapp[x][i] == 1) {
						if(vst[i] == 0) {
							vst[i] = 1;
							all_time ++;
							queue.offer(i);
							Father[i] = x;	step[i] = step[x] + 1;
							X1_b[st_b] = (x%10) * 60 + dx;
							Y1_b[st_b] = (x/10) * 60 + dy;
							X2_b[st_b] = (i%10) * 60 + dx;
							Y2_b[st_b] = (i/10) * 60 + dy;
							st_b ++;
							if(i == end) {
								ok = false;
								break;
							}
						}
					}
				}
			}
		}
		void mark_r() {
			int x1 = end, x2 = Father[end];
			while(x1 != start) {
				X1_r[st_r] = (x1 %10) * 60 + dx;
				Y1_r[st_r] = (x1 /10) * 60 + dy;
				X2_r[st_r] = (x2 %10) * 60 + dx;
				Y2_r[st_r] = (x2 /10) * 60 + dy;
				st_r ++ ;
				x1 = x2;
				x2 = Father[x1];
			}
		}
	};
	
	//A*监听
	private ActionListener A_x = new ActionListener(){
		int all_time = 0;
		Queue<Integer> queue;
		boolean ok;
		int Father[],G[],F[],H[];
		public void actionPerformed(ActionEvent e) {
			all_time = 0;
			st_b = st_r = 0;
			vst = null;
			vst = new int[100];
			queue = new LinkedList<Integer>();
			ok = true;
			Father = new int[100];
			G = new int[100];
			F = new int[100];
			H = new int[100];
			queue.offer(start);
			vst[start] = 1;
			A__();
			
			mark_r();
			String res = "<html><body>A*搜索结果如下:<br/>最短距离为:"+G[end]+"<br/>搜索所需时间为:"+all_time+"<br/>代价为:"+F[end]+"</body></html>";
			Result.setFont(Result.getFont().deriveFont(24.0f));
			Result.setText(res);
			repaint();
		}
		void A__() {
			while(!queue.isEmpty() && ok) {
				int x = queue.poll();
				for(int i=0;i<100;i++) {
					if(mapp[x][i] == 1) {
						if(vst[i] == 0) {
							vst[i] = 1;
							all_time ++;
							queue.offer(i);
							Father[i] = x;	G[i] = G[x] + 1;
							H[i] = H[x] + 1;
							F[i] = H[i] + G[i];
							X1_b[st_b] = (x%10) * 60 + dx;
							Y1_b[st_b] = (x/10) * 60 + dy;
							X2_b[st_b] = (i%10) * 60 + dx;
							Y2_b[st_b] = (i/10) * 60 + dy;
							st_b ++;
							if(i == end) {
								ok = false;
								break;
							}
						}
					}
				}
			}
		}
		void mark_r() {
			int x1 = end, x2 = Father[end];
			while(x1 != start) {
				X1_r[st_r] = (x1 %10) * 60 + dx;
				Y1_r[st_r] = (x1 /10) * 60 + dy;
				X2_r[st_r] = (x2 %10) * 60 + dx;
				Y2_r[st_r] = (x2 /10) * 60 + dy;
				st_r ++ ;
				x1 = x2;
				x2 = Father[x1];
			}
		}
	};
	
	public MainWnd() {
		X1 = new int[100];X2 = new int[100];Y1 = new int[100];Y2 = new int[100];
		X1[0] = Y1[0] = -1;
		X1_b = new int[100];X2_b = new int[100];Y1_b = new int[100];Y2_b = new int[100];
		X1_r = new int[100];X2_r = new int[100];Y1_r = new int[100];Y2_r = new int[100];
		mapp = new int [100][100];
		vst = new int [100];
		setTitle("三种搜索及最短路查找");
		setSize(900,800);
		setVisible(true);
		setLocation(450,180);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container cp = getContentPane();
		cp.setLayout(null);
		int X = 0 , Y = 0;
		for(int i = 0; i < 100; i++) {
			cp.add(btn[i]);
			btn[i].setLocation(X,Y);
			btn[i].setSize(20,20);
			btn[i].addMouseListener(ML);
			Y = Y + 60;
			if((i+1)%10==0) {
				X = X + 60;
				Y = 0;
			}
		}
		
		cp.add(OPEN);OPEN.setLocation(700,30);OPEN.setSize(150,50);OPEN.addActionListener(OP);
		cp.add(SAVE);SAVE.setLocation(700,145);SAVE.setSize(150,50);SAVE.addActionListener(SA);
		cp.add(Dfs);Dfs.setLocation(700,260);Dfs.setSize(150,50);Dfs.addActionListener(DFS);
		cp.add(Bfs);Bfs.setLocation(700,375);Bfs.setSize(150,50);Bfs.addActionListener(BFS);
		cp.add(A_);A_.setLocation(700,490);A_.setSize(150,50);A_.addActionListener(A_x);
		cp.add(Return);Return.setLocation(700,605);Return.setSize(150,50);Return.addActionListener(RT);
		
		OPEN.setFont(OPEN.getFont().deriveFont(16.0f));
		SAVE.setFont(SAVE.getFont().deriveFont(16.0f));
		Dfs.setFont(Result.getFont().deriveFont(16.0f));
		Bfs.setFont(Bfs.getFont().deriveFont(16.0f));
		A_.setFont(A_.getFont().deriveFont(16.0f));
		Return.setFont(Return.getFont().deriveFont(16.0f));
		
		cp.add(Result);Result.setLocation(30,550);Result.setText("<html><body>请连接节点并选取起点与终点<br/>操作方法:<br/>鼠标左键与右键分别选择当前需要连接的两个节点<br/>鼠标中键选择起点和终点<br/>注:任两节点间距离为1,搜索速度为1</body></html>");
		Result.setSize(600,200);
		Result.setFont(Result.getFont().deriveFont(20.0f));
		
		cp.add(signature);
		//signature.setFont(Result.getFont().deriveFont(20.0f));
		signature.setSize(300,100);
		signature.setLocation(700,650);
		
		cp.validate();
	}
	
	public void paint(Graphics g2) {
		super.paint(g2);
		Graphics2D g = (Graphics2D)g2;
		g.setColor(Color.BLACK);
		g.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND));
		
		for(int i = 0;i < st; i++) {
			g.drawLine(X1[i], Y1[i], X2[i], Y2[i]);
			g.fillOval(X1[i] - 9, Y1[i] - 5, 15, 15);
			g.fillOval(X2[i] - 9, Y2[i] - 5, 15, 15);
		}
			
		
		g.setColor(Color.BLUE);
		for(int i = 0;i < st_b; i++) {
			g.drawLine(X1_b[i], Y1_b[i], X2_b[i], Y2_b[i]);
			g.fillOval(X1_b[i] - 9, Y1_b[i] - 5, 15, 15);
			g.fillOval(X2_b[i] - 9, Y2_b[i] - 5, 15, 15);
		}
			
		
		g.setColor(Color.RED);
		for(int i = 0;i < st_r; i++) {
			g.drawLine(X1_r[i], Y1_r[i], X2_r[i], Y2_r[i]);
			g.fillOval(X1_r[i] - 9, Y1_r[i] - 5, 15, 15);
			g.fillOval(X2_r[i] - 9, Y2_r[i] - 5, 15, 15);
		}
			
		
		g.setFont(g.getFont().deriveFont(18.0f));
		if(X_s != 0 &&  Y_s !=-1) {
			g.drawString("start", X_s + 10, Y_s + 20);
			g.fillOval(X_s - 12, Y_s - 8, 22, 22);
			
		}
		if(X_e != 0 && Y_e != -1) {
			g.drawString("end", X_e + 10, Y_e + 20);
			g.fillOval(X_e - 12, Y_e - 8, 22, 22);
		}
	}
	
	
}

其中默认任意直接相连两点间距离为单位距离,则A* 算法估价函数H(n)恒唯一,则G(n)所占比例很大,A* 很接近于BFS,各位也可以将两点间距离改为实际距离然后重新A* 。

若有不足还望指正

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值