码迷,mamicode.com
首页 > 编程语言 > 详细

【算法设计与分析基础】关灯游戏

时间:2015-08-02 13:46:02      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:关灯游戏   算法   高斯消元   java   

① R.java  用于存储一些全局变量

package lightoff;


public class R {
	/*
 	public static int lightCondition[][] = {
		{1,0,0,1,1},
		{1,0,0,1,1},
		{1,0,0,1,1},
		{1,0,0,1,1},
	};
	 */
	public static int lightCondition[][] = {
		{1,1,1,1},
		{1,1,1,1},
		{1,1,1,1},
		{1,1,1,1},
	};
	
	//灯面板有 n x m 个灯
	public static int n = lightCondition.length;//行
	public static int m = lightCondition[0].length;//列
			
	public static int rect_Height = 30;//形成的矩阵的高
	public static int rect_Width = 30;//形成的矩阵的宽
	public static int[][] lightswitch=new int[n][m];//哪些开关按过
	public static int frame_Height = 240+ n * rect_Height;//窗口的高度
	public static int frame_Width = 240 + m * rect_Width;//窗口的宽度
	public static Gauss g ;//高斯消元算法类
	public static LightPanel lP = new LightPanel();//n x m 灯面板
	public static ButtonPanel bP = new ButtonPanel();//按钮面板
	public static SurfaceView sv;//关灯游戏界面
	public static Demo d;//演示界面
	public static double g_sleeptime = 0.3;//生成开关影响表的暂停时间
	public static double l_sleeptime = 0.1;//转化成上三角矩阵的暂停时间
	public static double r_sleeptime = 0.5;//结果分析的暂停时间
	public static boolean demo = true;//是否需要演示。如果不需要请把这里设为false

	//矩阵面板左上角顶点的坐标
	public static int rect_x = 50;
	public static int rect_y = 50;
	/**
	 * 重绘 n x m 面板
	 * @param _n 行
	 * @param _m 列
	 */
	public static void rewriteLightCondition(int _n,int _m){
		n=_n;
		m=_m;
		if(n>21){
			rect_Height = rect_Width = 20;
		}
		else{
			rect_Height = rect_Width = 30;
		}
		frame_Height = 240+ n * rect_Height;//窗口的高度
		frame_Width = 240 + m * rect_Width;
		lightCondition=new int[n][m];
		lightswitch=new int[n][m];
		
		int i,j;
		for(i=-1;++i<n;){
			for(j=-1;++j<m;){
				lightCondition[i][j]=1;//(int)(Math.random()*100)%2;
			}
		}
		sv.setSize();
		
	}
	/**
	 * 暂停一段时间
	 * @param i 单位秒
	 */
	public static void sleep(double i){
		try {
			Thread.sleep((int)(i*(double)1000));
		} catch (InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		};
	}
}


②  GameBegin.java   main函数所在位置,创建图形界面。

package lightoff;

import java.lang.reflect.InvocationTargetException;

public class GameBegin {
	public static void main(String[] args){
		try {
			javax.swing.SwingUtilities.invokeAndWait(new Runnable(){
				public void run(){
				     R.sv = new SurfaceView();
				}
			});
		} catch (InvocationTargetException | InterruptedException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
	}
}


③ Gauss.java  关灯游戏的算法文件,类似高斯消元法。

package lightoff;

class BreakPoint{
	int r;//断点所在的行
	int c;//当前是0还是1
	public BreakPoint(){
		r = -1;
		c = -1;
	}
}

public class Gauss {
	int num = R.n * R.m;
	int[] ls = new int[num];
	int[][] gauss = new int[num][num];
	int[] answer =  new int[num];
	BreakPoint[] bp = new BreakPoint[num];
	boolean exist = false;
	int n = 0;
	/**
	 * 建立开关影响的表,做高斯消元求解
	 */
	public Gauss(){
		
	}
	public void setgauss(){
		if(R.demo){
		    R.d.step_next(0);
		    R.d.settitle("根据开关的影响建立高斯消元表");
		}
         /////////// 1. 开关的影响:建立高斯消元表  /////////////
		int i,j,col;
		//遍历 n x m 面板
		for(i=-1;++i<R.n;){
			for(j=-1;++j<R.m;){
				col = i*R.m+j;
				ls[col] = R.lightCondition[i][j];//高斯消元表最右边的常数
				//一个开关造成的影响最多五个点,最少三个点
				//第一个点:自己
				gauss[col][col] = 1;
				//第二个点:左边的点
				if(inthePanel(i,j-1)){
					gauss[i*R.m+j-1][col] = 1;
				}
				//第三个点:下边的点
				if(inthePanel(i-1,j)){
					gauss[(i-1)*R.m+j][col] = 1;
				}
				//第四个点:上边的点
				if(inthePanel(i+1,j)){
					gauss[(i+1)*R.m+j][col] = 1;
				}
				//第五个点:右边的点
				if(inthePanel(i,j+1)){
					gauss[i*R.m+j+1][col] = 1;
				}
				if(R.demo){
				    R.d.setcol(col);
				    R.d.rd();
				    R.sleep(R.g_sleeptime);
				}
				
			}
		}
	}
	/**
	 * 判断该坐标是否在灯面板内
	 * @param x 行坐标
	 * @param y 列坐标
	 * @return 布尔类型
	 */
	boolean inthePanel(int x, int y){//x是行,y是列
		return x >= 0 && y >= 0 && x < R.n && y < R.m;
	}
	/**
	 * 进行异或运算
	 * @param a 数字1
	 * @param b 数字2
	 * @return a 异或 b
	 */
	int xor(int a,int b){
		return a^b;
	}
	/**
	 * 交换两个数字
	 * @param x1 第一个数字的行坐标
	 * @param x2 第二个数字的行坐标
	 * @param y 它们有个共同的列坐标
	 */
	void swap(int x1,int x2,int y){
		gauss[x1][y]^=gauss[x2][y];
		gauss[x2][y]^=gauss[x1][y];
		gauss[x1][y]^=gauss[x2][y];
	}
	/**
	 * 交换两行
	 * @param r1 其中一行
	 * @param r2 另外一行
	 */
	void swap(int r1,int r2){
		int i;
		for(i=-1;++i<num;){
			swap(r1,r2,i);
		}
		ls[r1]^=ls[r2];
		ls[r2]^=ls[r1];
		ls[r1]^=ls[r2];
	}
	/**
	 * r1行与r2行异或以后赋给r2行
	 * @param r1 某一行
	 * @param r2 另外一行
	 */
	void add(int r1,int r2){
		int i;
		for(i=-1;++i<num;){
		    	gauss[r2][i]=xor(gauss[r1][i],gauss[r2][i]);
		}
		ls[r2]=xor(ls[r1],ls[r2]);
	}
	void ga(){
		if(R.demo){
		    R.d.step_next(1);
		    R.d.settitle("转化成上三角形矩阵");
		}
		int i,j;
		for(i=-1;++i<num;){
			if(R.demo){
			    R.d.col_rd(i);
			}
			j = i;
			if(gauss[i][i]==0){
				for(;++j<num;){
					if(gauss[j][i]==1){
						swap(i,j);
						if(R.demo){
						    //////以下两行表示把过程绘制在一个面板里面/////
						    R.d.swap_rd(i,j);
						    R.d.rd();
						    R.sleep(R.l_sleeptime);
						    //////////////////////////////////////
						}
						break;
					}
				}
			}
			for(;++j<num;){
				if(gauss[j][i]==1){
					add(i,j);
					if(R.demo){
				        //////以下两行表示把过程绘制在一个面板里面/////
					    R.d.add_rd(i,j);
					    R.d.rd();
					    R.sleep(R.l_sleeptime);
                        //////////////////////////////////////
					}
				}
			}
			if(R.demo){
	     	    //////以下三行表示把过程绘制在一个面板里面/////
			    R.d.swap_rd(-1,-1);
			    R.d.add_rd(-1,-1);
			    R.d.rd();
			    R.sleep(R.l_sleeptime);
                //////////////////////////////////////
			}
		}
	}
	/**
	 * 对值进行分析(X表示0或1都可以)
	 * 0 0 0 => X
	 * 0 0 1 => 无解
	 * 0 1 0 => 无解
	 * 0 1 1 => X
	 * 1 0 0 => 0
	 * 1 0 1 => 1
	 * 1 1 0 => 1
	 * 1 1 1 => 0
	 * @param a gauss表中对角线上的值
	 * @param b gauss表中对角线 右边一行的值乘以对应的answer 之和 % 2
	 * @param c 该行上的常数列
	 * @param i 该行行数
	 * @return 分析后的值
	 */
	int analyze(int a,int b,int c,int i){
		int col = 0;
		if(R.demo){
			R.d.setabc(a, b, c);
		}
		if(a==1){
			return Math.abs(b-c);
		}
		else if(a==0){
			if(b==c){
				// 在 X 这里设置个断点
				col = getbp(i);
				if(col == -1){
					bp[n] = new BreakPoint();
					bp[n].r = i;
					bp[n].c = 0;
					n++;
					return 0;
				}
				return col;
				
			}
			else{
				return -1;
			}
		}
		return 0;
	}
	boolean Solve(){
		if(R.demo){
			R.d.setfVisible(true);
		    R.d.step_next(2);
		    R.d.settitle("结果分析(与反向替换类似)");
		}
		int i,j,sum;
		for(i=num;--i>=0;){
			if(R.demo){
			    R.d.setrow(i);
			}
			sum=0;
			for(j=num;--j>i;){
				sum+=gauss[i][j]*answer[j];
			}
			answer[i]=analyze(gauss[i][i],sum%2,ls[i],i);
			if(R.demo){
	     		R.d.rd();
			    R.sleep(R.r_sleeptime);
			}
			if(answer[i]==-1){
				return false;
			}
		}
		exist = true;
		R.bP.next = true;
		if(R.demo){
			R.d.setVisible(false);
		    R.d.setfVisible(false);
		}
		return true;
	}
	public boolean check(){
		int i,j,sum;
		for(i=-1;++i<num;){
			sum=0;
			for(j=-1;++j<num;){
				sum+=gauss[i][j]*answer[j];
			}
			if(sum%2!=ls[i]){
				return false;
			}
		}
		return true;
	}
	public boolean breakpoint_next(){
		if(n==0)return false;
		int i;
		for(i=n;--i>=0;){
			if(bp[i].c==0){
				bp[i].c ^= 1;
				break;
			}
			bp[i].c ^= 1;
		}
		return true;
	}
	public int getbp(int r){
		int i;
		for(i=-1;++i<n;){
			if(bp[i].r == r){
				return bp[i].c;
			}
		}
		return -1;
	}
	void displayBreakPoint(){
		int i;
		for(i=-1;++i<n;){
			System.out.print(bp[i].c+ " ");
		}
		System.out.println();
	}
	void displayanswer(){
		int i,j;
		for(i=-1;++i<R.n;){
			for(j=-1;++j<R.m;){
				R.lightswitch[i][j] = answer[i*R.m+j];
			}
		}
	}
	/**
	 * 输出 灯影响 的表
	 */
	void displays(){//输出高斯消元表
		int i,j;
		for(i=-1;++i<num;){
			for(j=-1;++j<num-1;){
				System.out.print(gauss[i][j]+" ");
			}
			System.out.println(gauss[i][j]+" "+ls[i]);
		}
		System.out.println();
	}
}


④ LightPanel.java  关灯面板文件,在主窗口中显示在下方的n x n 个绿色(开灯)或灰色(关灯)面板

package lightoff;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JPanel;

public class LightPanel extends JPanel implements MouseListener{
	private int light_x;//鼠标点击到的灯_列
	private int light_y;//速表点击到的灯_行
	public int n = 0;//第几个答案
	public LightPanel(){
		//this.setSize(R.frame_Width,(int)((double)R.frame_Height*0.8));
		this.setBackground(new Color(255,255,255));
		this.addMouseListener(this);
	}
	public void redraw(){
		this.repaint();
	}
	public void paint(Graphics g) {  
		super.paint(g); 
		int i,j;
		int num =(R.g!=null && R.g.exist)?(int)Math.pow(2,R.g.n):1;
		g.setColor(new Color(0,0,0));
		g.setFont(new Font("Georgia",Font.PLAIN,20));
		g.drawString(String.valueOf((n)%(num)+1)+"\\"+String.valueOf(num),  R.rect_x, R.rect_y-3);
		for(i=-1;++i<R.n;){//行
			for(j=-1;++j<R.m;){//列
				((Graphics2D)g).setStroke(new   BasicStroke(1.0f));
				///////   1.    绘制边框线   ///////////
				g.setColor(Color.white);
				g.drawRect(R.rect_x + j * R.rect_Width,
						   R.rect_y + i * R.rect_Height, 
						   R.rect_Width,
						   R.rect_Height);
			    ///////    2.    填充矩形    ///////////
				if(R.lightCondition[i][j]==0){
			         g.setColor(new Color(0x32,0x32,0x32));
				}
				else if(R.lightCondition[i][j]==1){
					g.setColor(new Color(0,0xC8,00));
				}
			    g.fillRect(R.rect_x+j*R.rect_Width+1, 
			    		R.rect_y+i*R.rect_Height+1, 
			    		   R.rect_Width-1,
			    		   R.rect_Height-1);
			    ////////// 3.  看哪些开关被按下,按下的开关画圆 ////////
			    if(R.lightswitch[i][j]==1){
			    	((Graphics2D)g).setStroke(new   BasicStroke(1.5f));
			    	g.setColor(new Color(255,255,255));
			    	int oval_x = (R.rect_x+j*R.rect_Width)+(int)((double)R.rect_Width*0.4);//行
			    	int oval_y = (R.rect_y+i*R.rect_Height)+(int)((double)R.rect_Height*0.4);//列
			    	g.drawOval(oval_x,oval_y ,(int)((double)R.rect_Height*0.2) ,(int)((double)R.rect_Width*0.2 ));
			    }
			}
       }
  }
	boolean isLight(double x,double y){
		double i = (y-R.rect_x)/R.rect_Height;//行
		double j = (x-R.rect_y)/R.rect_Width;//列
		if( i>=0 && i< R.n && j>=0 && j< R.m){
			this.light_x = (int)i;
			this.light_y = (int)j;
			return true;
		}
		return false;
	}
	
	void isinLightPanel(int i,int j){
		if(i>=0 && i<R.n && j>=0 && j<R.m){
			R.lightCondition[i][j] = R.lightCondition[i][j] ^ 1;
		}
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO 自动生成的方法存根

	}
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO 自动生成的方法存根
		int x = e.getX();
		int y = e.getY();
		int i = 0,j = 0;
		if(e.getButton()==e.BUTTON1 && isLight(x,y)){
			//开关被按下
			//开关被按下
			R.lightswitch[light_x][light_y] = R.lightswitch[light_x][light_y] ^ 1;
			//第一个点,自身
			R.lightCondition[light_x][light_y] = R.lightCondition[light_x][light_y] ^ 1;
			//第二个点,上方的点
			isinLightPanel(light_x,light_y-1);
			//第三个点,左边的点
			isinLightPanel(light_x-1,light_y);
			//第四个点,下边的点
			isinLightPanel(light_x,light_y+1);
			//第五个点,右边的点
			isinLightPanel(light_x+1,light_y);
			redraw();
		}
		else if(e.getButton()==e.BUTTON3 && isLight(x,y)){
			R.lightCondition[light_x][light_y] = R.lightCondition[light_x][light_y] ^ 1;
			redraw();
		}
		
		
	}
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void mouseExited(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
}

⑤ SurfaceView.java  主窗口文件。

package lightoff;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class SurfaceView extends JFrame implements ActionListener{
	Frame_Setting fs = new Frame_Setting();
	Help h = new Help();
	public SurfaceView(){
		//////////  1.设置窗口大小                   /////////
	//	System.out.println(R.frame_Width+" "+R.frame_Height);
		this.setBounds(300,0,R.frame_Width,R.frame_Height);
		this.setTitle("LightOFF Game");
		//////////  2.设置按下X键后关闭窗口   /////////
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLayout(null);
		this.setResizable(true);
		//////////  3.添加菜单组件                //////////
		JMenuBar JMB = new JMenuBar();
		this.setJMenuBar(JMB);
		JMenu JM_File = new JMenu("File");
		JMenu JM_Help = new JMenu("Help");
		JMB.add(JM_File);
		JMB.add(JM_Help);
		JMenuItem JI_set = new JMenuItem("setting");
		JMenuItem JI_help = new JMenuItem("help"); 
		JM_File.add(JI_set);
		JM_Help.add(JI_help);
		JI_set.addActionListener(this);
		JI_help.addActionListener(this);
		JMenuItem JI_Demo = new JMenuItem("");
		if(R.demo){
			JI_Demo.setText("Demo √");
		}
		else{
			JI_Demo.setText("Demo");
		}
		JI_Demo.addActionListener(this);
		JM_File.add(JI_Demo);
		//////////  4.添加按钮面板和灯面板  //////////
		
		R.bP.setBounds(0,0,R.frame_Width,R.bP.bt.Box_Height+10);
		this.add(R.bP);
		R.lP.setBounds(0,R.bP.getHeight(),R.frame_Width,(int)((double)R.frame_Height*0.9));
		this.add(R.lP);
		setVisible(true);
	}
	public void setSize(){
		this.setSize(R.frame_Width,R.frame_Height);
		R.bP.setSize(R.frame_Width,R.bP.bt.Box_Height+10);
		R.lP.setSize(R.frame_Width,(int)((double)R.frame_Height*0.9));
	}
	@Override
	public void actionPerformed(ActionEvent e){
		if(e.getActionCommand().equals("setting")){
			fs.setVisible(true);
		}
		else if(e.getActionCommand().equals("Demo √")){
			R.demo = false;
			((JMenuItem)e.getSource()).setText("Demo");
		}
		else if(e.getActionCommand().equals("Demo")){
			R.demo = true;
			((JMenuItem)e.getSource()).setText("Demo √");
		}
		else if(e.getActionCommand().equals("help")){
			h.setVisible(true);
		}
	}
}

class Frame_Setting extends JFrame implements ActionListener{
	String[] rowandcol ={"1","2","3","4","5","6","7","8","9","10",
			     "11","12","13","14","15","16","17","18","19","20",
			     "21","22","23","24","25","26","27","28","29","30",
			     "31","32"};
	String[] pausetime = {"0.1","0.2","0.3","0.4","0.5","0.6","0.7","0.8","0.9","1.0"};
	JComboBox jCB;
	JComboBox jCB1;
	JComboBox jCB2;
	public Frame_Setting(){
		int i;
		this.setTitle("Setting");
		this.setBounds(0,0,200,190);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		this.setLayout(null);
		this.setResizable(false);
		//////////// 1. 设置行与列    //////////
		//行和列的标签
		JLabel label_row = new JLabel("行:");
		label_row.setBounds(20,30,30,30);
		JLabel label_col = new JLabel("列:");
		label_col.setBounds(20,60,30,30);
		JLabel label_pt = new JLabel("暂停时间:");
		label_pt.setBounds(0,85,90,30);
		this.add(label_row);
		this.add(label_col);
		this.add(label_pt);
		//行和列的下拉列表
		jCB = new JComboBox();
		jCB1 = new JComboBox();
		for(i=-1;++i<rowandcol.length;){
			jCB.addItem(rowandcol[i]);
			jCB1.addItem(rowandcol[i]);
		}
		jCB2 = new JComboBox();
		for(i=-1;++i<pausetime.length;){
			jCB2.addItem(pausetime[i]);
		}
		jCB.setBounds(60,30,100,20);
		jCB1.setBounds(60,60,100,20);
		jCB2.setBounds(60,90,100,20);

		this.add(jCB);
		this.add(jCB1);
		this.add(jCB2);
		//按钮
		JButton b = new JButton("确定");
		b.setBounds(60,120,60,40);
		b.addActionListener(this);
		this.add(b);
		jCB.setSelectedIndex(3);
		jCB1.setSelectedIndex(3);
		jCB2.setSelectedIndex(2);
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getActionCommand().equals("确定")){
			R.rewriteLightCondition(Integer.parseInt(jCB.getSelectedItem().toString()),
					                Integer.parseInt(jCB1.getSelectedItem().toString()));
			R.g_sleeptime = R.l_sleeptime = R.r_sleeptime = Double.parseDouble(jCB2.getSelectedItem().toString());
			this.setVisible(false);
		}
	}
}

⑥ ButtonPanel.java  按钮面板文件,显示在主窗口上方,带四个按钮next reset get oppo

package lightoff;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class ButtonPanel extends JPanel implements MouseListener{
	BoxText bt = new BoxText("next","华文琥珀",Font.PLAIN,20,0,0);
	BoxText bt1 = new BoxText("reset","华文琥珀",Font.PLAIN,20,bt.Box_Width+10,0);
	BoxText bt2 = new BoxText("get","华文琥珀",Font.PLAIN,20,bt.Box_Width+bt1.Box_Width+20,0);
	BoxText bt3 = new BoxText("oppo","华文琥珀",Font.PLAIN,20,bt.Box_Width+bt1.Box_Width+bt2.Box_Width+30,0);
	boolean next = true;
	public ButtonPanel(){
		this.setBackground(new Color(255,255,255));
		this.addMouseListener(this);
	}
	public void paint(Graphics g){
		super.paint(g);
		bt.draw(g);
		bt1.draw(g);
		bt2.draw(g);
		bt3.draw(g);
	}
	
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		int x = e.getX();
		int y = e.getY();
		if(e.getButton()==e.BUTTON1){
		    /**
		     * 如果点击到了"next"按钮
		     */
		    if(next && R.g!=null && R.g.exist && bt.isClicked(x, y)){
			    if(R.g!=null && R.g.breakpoint_next()){
			    	if(R.demo && !R.d.isShowing()){
			    		R.d.setVisible(true);
			    	}
			    	next = false;
			    	Thread t = new Thread(new Runnable(){
			    		public void run(){
			               if(R.g.Solve()){
				              R.g.displayanswer();
				              R.lP.n++;
				              R.lP.redraw();
			               }
			    		}
			    	});
			    	t.start();
			    }
			}
		    /**
		     * 按到"reset"按钮
		     */
		    if(R.g!= null && bt1.isClicked(x, y)){
		    	R.rewriteLightCondition(R.n, R.m);
		    	R.g.exist = false;
		    	R.lP.redraw();
		    	R.lP.n = 0;
		    	R.sv.setSize();
		    }
		    /**
		     * 按到"get"按钮
		     */
		    if(bt2.isClicked(x, y)){
		    	if(R.demo){
		    	    R.d = new Demo();
		    	    R.d.setVisible(true);
		    	}
		    	Thread t = new Thread(new Runnable(){
		    		public void run(){
		    	        R.g = new Gauss();
		    	        R.g.setgauss();
		    			R.g.ga();
		    			if(R.g.Solve()){
		    				
		    				R.g.displayanswer();  
		    			}
		    			else{
		    				JOptionPane.showMessageDialog(R.sv,"该问题无解","错误",JOptionPane.ERROR_MESSAGE);
		    			}
		    			R.lP.redraw();
		    			R.lP.n = 0;
		    		}
		    	});
		        t.start();
		    }
		    /**
		     * 按到"OPPO"按钮
		     */
		    if(bt3.isClicked(x, y)){
		    	int i,j;
		    	for(i=-1;++i<R.n;){
		    		for(j=-1;++j<R.m;){
		    			R.lightCondition[i][j]^=1;
		    		}
		    	}
		    	R.lP.redraw();
		    }
		}
		
	}
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO 自动生成的方法存根
	}
	@Override
	public void mouseExited(MouseEvent e) {
		// TODO 自动生成的方法存根
	}
}

⑦ Demo.java  算法演示的图形界面。

package lightoff;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Demo extends JFrame{
	int num = R.n * R.m;
	public boolean running = false;
	public boolean noanswer = false;
	private ShowPlay sp = new ShowPlay();
	public Demo(){
		this.setTitle("Demo");
		this.setSize(120 + (num * num + 1) * 2 + 150,
				     num * 30+ 50 + ShowPlay.title_Height);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.setLayout(null);
		sp.setBounds(0,0,this.getWidth(),this.getHeight());
		this.add(sp);
	}
	/*
	 * 记录交换的两行
	 */
	public void swap_rd(int r1,int r2){
		sp.swap[0] = r1;
		sp.swap[1] = r2;
	}
	/*
	 * 记录消元的两行
	 */
	public void add_rd(int r1,int r2){
		sp.add[0] = r1;
		sp.add[1] = r2;
	}
	/*
	 * 记录灯的列数
	 */
	public void col_rd(int col){
		sp.col = col;
	}
	/*
	 * 重绘ShowPlay面板
	 */
	public void rd(){
		sp.repaint();
	}
	/*
	 * 下一步骤
	 */
	public void step_next(int s){
		sp.step = s;
	}
	/*
	 * 设置标题
	 */
	public void settitle(String title){
		sp.title = title;
	}
	/*
	 * 设置行
	 */
	public void setrow(int i){
		sp.row = i;
	}
	/*
	 * 设置三个值a,b,c
	 */
	public void setabc(int a,int b,int c){
		sp.a = a;
		sp.b = b;
		sp.c = c;
	}
	/*
	 * 建立影响表的时候记录当前完成的列数
	 */
	public void setcol(int y){
		sp.y = y;
	}
	public void setfVisible(boolean v){
		sp.f.setVisible(v);
	}
}

class ShowPlay extends JPanel{
	int num = R.n * R.m;//正方形边长
	public int rect_Width = 120;//矩阵的宽度
	public int rect_Height = num * 30+10;//矩阵的高度
	public static int title_Height = 30;//标题的高度
	String title = "";//标题
	int[] swap = new int[2];//记录交换的两行
	int[] add = new int[2];//记录消元的两行
	int row;//灯的行数
	int col;//灯的列数
	int a;//结果分析时候的a值(对角线值)
	int b;//结果分析时候的b值(sum%2)
	int c;//结果分析时候的c值(常数列)
	int y;//建立开关影响表的时候,建立了多少列
	int step = -1;//当前是第几步骤,调用不同的绘制方法
	String fontface = "Georgia";//字体
	int fonttype = Font.PLAIN;//字体字形是常规
	int fontsize = 20;//字体大小
	String gauss1 = "开关影响表,根据开关的影响情况建立表。";
	Frame f = new Frame();
	public ShowPlay(){
		this.setBackground(new Color(255,255,255));
	}
	public void paintGauss(Graphics g){
		int i,j;
		////////////   说明   ///////////////////////////
		g.setFont(new Font("微软雅黑",Font.BOLD,15));
		g.drawString("例如3x3的灯面板", 1, title_Height+20);
		g.drawString("按下第一行",1 , title_Height+30+121);
		g.drawString("第一列的开关",1,title_Height+50+121);
		g.drawString("按下第二行",1 , title_Height+60+242);
		g.drawString("第二列的开关",1,title_Height+80+242);
		g.drawString("总共能建9个表", 1, title_Height+85+220+134);
		g.drawString("(行x列)", 1, title_Height+85+220+134+20);
		g.drawString("然后竖向输出", 1, title_Height+85+220+134+40);
		try {
			g.drawImage(ImageIO.read(new File(new File("").getAbsoluteFile().getAbsoluteFile()+"\\Image\\table1.bmp")), 1,title_Height+25,100,110,this);
			g.drawImage(ImageIO.read(new File(new File("").getAbsoluteFile().getAbsoluteFile()+"\\Image\\table2.bmp")), 1,title_Height+65+110,100,110,this);
			g.drawImage(ImageIO.read(new File(new File("").getAbsoluteFile().getAbsoluteFile()+"\\Image\\table3.bmp")), 1,title_Height+85+220,100,110,this);
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		/////////  1.画最左边的那个长矩阵   //////////////////////
		g.drawRect(0, title_Height, rect_Width, rect_Height);
		g.setFont(new Font(fontface,fonttype,fontsize));//设置字体
		g.setColor(new Color(0xB9,0xC0,0xB6));//设置颜色
		/////////////    根据列数画开关影响表    /////////////
		for(j=-1;++j<y;){
		    for(i=-1;++i<num;){
	            g.drawString(String.valueOf(R.g.gauss[i][j])+" "
   		                   , rect_Width + 10 + j * 30
   		                   , title_Height + 30 + i * 30);
		    }
       }
		/////////////    设置字体和颜色    ////////////////////
	   g.setFont(new Font(fontface,Font.BOLD,fontsize));
	   g.setColor(new Color(255,0,0));
	   for(i=-1;++i<num;){
          g.drawString(String.valueOf(R.g.gauss[i][j])+" "
                     , rect_Width + 10 + j * 30
                     , title_Height + 30 + i * 30);
	   }
	}
	public void paintga(Graphics g){
		int i,j;
		g.drawRect(0, title_Height, rect_Width, rect_Height);
		g.setFont(new Font("微软雅黑",Font.BOLD,15));
		g.drawString("线性代数的知识:", 1, title_Height+20);
		g.drawString("把该表化成上三", 1, title_Height+40);
		g.drawString("角形矩阵,采用", 1, title_Height+60);
		g.drawString("高斯消元的方式", 1, title_Height+80);
		g.drawString("用的是异或运算", 1, title_Height+120);
		g.drawString("在setting里面", 1, title_Height+220);
		g.drawString("可以调整演示速度", 1, title_Height+240);
		g.setColor(new Color(255,0,0));
		g.drawString("红色表示交换", 1, title_Height+140);
		g.setColor(new Color(0,0,255));
		g.drawString("蓝色表示消元", 1, title_Height+160);
		g.setColor(new Color(0,255,0));
		g.drawString("绿色表示当前", 1, title_Height+180);
		g.drawString("访问的列", 1, title_Height+200);
		for(i=-1;++i<num;){
			for(j=-1;++j<num;){
				if((i==swap[0]&&j>=col) || (i==swap[1]&&j>=col)){
					g.setFont(new Font(fontface,Font.BOLD,fontsize));
					g.setColor(new Color(255,0,0));
				}
				else if( (i == add[0]&&j>=col) || (i == add[1]&&j>=col)){
					g.setFont(new Font(fontface,Font.BOLD,fontsize));
					g.setColor(new Color(0,0,255));
				}
				else if(j == col){
					g.setFont(new Font(fontface,Font.BOLD,fontsize));
					g.setColor(new Color(0,255,0));					
				}
				else
				{
					g.setFont(new Font(fontface,fonttype,fontsize));
					g.setColor(new Color(0xB9,0xC0,0xB6));
				}
				
			    g.drawString(String.valueOf(R.g.gauss[i][j])+" "
			    		     , rect_Width + 10 + j * 30
			    		     , title_Height + 30 + i * 30);
			}
			g.setColor(new Color(0,255,255));
			g.drawString(String.valueOf(R.g.ls[i]), 
					    rect_Width + 10 + j * 30, 
					    title_Height + 30 + i * 30);
		}
	}
	public void paintSolve(Graphics g){
		int i = 0,j = 0,k;
		g.setColor(new Color(0,0,0));
		g.drawRect(0, title_Height, rect_Width, rect_Height);
		////////////////   输出 a b c ///////////////////////
		g.setColor(new Color(255,0,0));
		g.drawString(String.valueOf(a),5 , title_Height + 30 + row * 30);
		g.setColor(new Color(0,0,255));
		g.drawString(String.valueOf(b),35 , title_Height + 30 + row * 30);
		g.setColor(new Color(0,255,255));
		g.drawString(String.valueOf(c),65 , title_Height + 30 + row * 30);
		////////////////   输出答案      ///////////////////////
		for(k=num;--k>=row;){
			g.setColor(new Color(0,0,0));
			g.drawString(String.valueOf(R.g.answer[k]), 
						 95,
						 title_Height + 30 + k * 30);
		}
		for(i=-1;++i<num;){
			for(j=-1;++j<num;){
				if(i==row && j>=row){
					if(j==row){
						g.setFont(new Font(fontface,Font.BOLD,fontsize));
						g.setColor(new Color(255,0,0));
					}
					else{
						g.setFont(new Font(fontface,Font.BOLD,fontsize));
						g.setColor(new Color(0,0,255));
					}
				}
				else{
					g.setFont(new Font(fontface,fonttype,fontsize));
					g.setColor(new Color(0xB9,0xC0,0xB6));
				}
		        g.drawString(String.valueOf(R.g.gauss[i][j])+" ", 
				             rect_Width + 10 + j * 30, 
				             title_Height + 30 + i * 30);
	        }
			g.setColor(new Color(0,255,255));
			g.drawString(String.valueOf(R.g.ls[i]), 
					    rect_Width + 10 + j * 30, 
					    title_Height + 30 + i * 30);
		}
	}

	public void paint(Graphics g){
		super.paint(g);
		///////////   绘制标题     //////////////////////
		g.setFont(new Font("微软雅黑",Font.BOLD,20));
		g.drawString(title,10,25);
	//	System.out.println(title);
		///////////   当前是第几步骤,调用不同的绘制函数   //////
		switch(step){
		   case 0:
			  paintGauss(g);
			  break;
		   case 1:
		      paintga(g);
		      break;
		   case 2:
			  paintSolve(g);
			  break;
		};
	}
}

class Frame extends JFrame{
	String path = new File("").getAbsolutePath();
	class Panel extends JPanel{
		public void paint(Graphics g){
			super.paint(g);
			g.setColor(new Color(255,255,255));
			g.fillRect(0,0,this.getWidth(),this.getHeight());
			g.setFont(new Font("微软雅黑",Font.BOLD,20));
			g.setColor(new Color(0,0,0));
			g.drawString("对值进行分析(X表示0和1都可以)", 2, 20);
			g.drawString("0 0 0 => X", 2, 40);
			g.drawString("0 0 1 => 无解", 2, 60);
			g.drawString("0 1 0 => 无解", 2, 80);
			g.drawString("0 1 1 => X", 2, 100);
			g.drawString("1 0 0 => 0", 2, 120);
			g.drawString("1 0 1 => 1", 2, 140);
			g.drawString("1 1 0 => 1", 2, 160);
			g.drawString("1 1 1 => 0", 2, 180);
		}
	}
	Panel p = new Panel();
	public Frame(){
		this.setBounds(924,117,312,221);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.add(p);
	}
	
}

⑧ Help.java  ppt图片演示,显示效果不是很好,建议还是看ppt

package lightoff;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Help extends JFrame{
	pptPanel ppt = new pptPanel();
	public Help(){
		this.add(ppt);
		this.setSize(900,721);
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		
	}
}

class pptPanel extends JPanel implements MouseListener {
	private ArrayList<Image> imgName = new ArrayList<Image>();
	private int totalnum = 0;
	private int n = 0;
	public pptPanel(){
		this.addMouseListener(this);
		File f = new File("");
		String path = f.getAbsolutePath()+"\\PPT\\幻灯片";
		int num = 1;
//		System.out.println(path+String.valueOf(num)+".JPG");
		f = new File(path+String.valueOf(num++)+".BMP");
		Image i;
		while(f.exists()){
			try {
				i = ImageIO.read(f);
				imgName.add(i);
//				System.out.println(path+String.valueOf(num)+".JPG");
				f = new File(path+String.valueOf(num++)+".BMP");
			} catch (IOException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
		}
		totalnum = num - 2;
	}
	public void paint(Graphics g){
		super.paint(g);
		g.drawImage(imgName.get(n%totalnum),0,0,this.getWidth(),this.getHeight(),this);
		g.setFont(new Font("Georgia",Font.PLAIN,20));
		g.drawString(String.valueOf(n%totalnum+1)+"\\"+String.valueOf(totalnum), this.getWidth()-70, this.getHeight()-10);
	}
	@Override
	public void mouseClicked(MouseEvent e) {
	//	System.out.println(e.getButton());
		if(e.getButton()==e.BUTTON1){
			n++;
			this.repaint();
		}
		else if(e.getButton()==e.BUTTON3){
			n--;
			if(n==-1){
				n = totalnum-1;
			}
			this.repaint();
		}
		
	}
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void mouseExited(MouseEvent e) {
		// TODO 自动生成的方法存根
		
	}
}

⑨ BoxText.java  自己编写的按钮文件。

package lightoff;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.JLabel;

public class BoxText{
	String text = "";
	String fontface = "";
	int fonttype = 0;
	int fontsize = 0;
	int Box_x = 0;
	int Box_y = 0;
	int Box_Height = 0;
	int Box_Width = 0;
	public BoxText(String text,String fontface,int fonttype,int fontsize,int Box_x,int Box_y){
		///////////  1. 获取值:text: 文本; fontface: 字体; fonttype: 字体类型; fontsize: 字体大小  ///////////////////
		//////////            Box_x,Box_y: 按钮左上角顶点所在位置                                                                                          ///////////////////
		this.text = text;
		this.fontface = fontface;
		this.fonttype = fonttype;
		this.fontsize = fontsize;
		this.Box_x = Box_x;
		this.Box_y = Box_y;
		////////////// 2. 根据字体的高度和宽度,设置箱子的高度和宽度   ///////////////////////
		Font f = new Font(fontface, fonttype, fontsize);
		FontMetrics fm = new JLabel().getFontMetrics(f);
		Box_Height = fm.getHeight() ;
		Box_Width = fm.stringWidth(text) + 20;
	}
	/**
	 * 获取文本左下角顶点的坐标x
	 * @return 文本左下角顶点的坐标x
	 */
	public int getText_x(){
		return Box_x + 10;
	}
	/**
	 * 获取文本左下角顶点的坐标y
	 * @return 文本左下角顶点的坐标y
	 */
	public int getText_y(){
		return Box_y + Box_Height - 5;
	}
	/**
	 * 获取面板paint函数中的Graphics来将该箱子画上去
	 * @param g 某画板的Graphics
	 */
	public void draw(Graphics g){
		g.setColor(new Color(0,0,0));
		g.fillRect(Box_x,Box_y,Box_Width,Box_Height);
		g.setFont(new Font(fontface,fonttype,fontsize));
		g.setColor(new Color(255,255,255));
		g.drawString(text, getText_x(), getText_y());
	}
	/**
	 * 看箱子是否被按下
	 * @param x 鼠标弹起的x坐标
	 * @param y 鼠标谈起的y坐标
	 * @return 布尔类型:是否按下
	 */
	public boolean isClicked(int x,int y){
		return x >= Box_x && y >= Box_y && x <= Box_x+Box_Width && y <= Box_y + Box_Height;
	}
}

程序和算法分析ppt下载地址:http://download.csdn.net/detail/u013580497/8953269




版权声明:本文为博主原创文章,未经博主允许不得转载。

【算法设计与分析基础】关灯游戏

标签:关灯游戏   算法   高斯消元   java   

原文地址:http://blog.csdn.net/u013580497/article/details/47205949

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!