java连连看

一、成品展示:

  • 该连连看主要有以下功能:
1.提示,洗牌(可在设置中设置提示和洗牌次数)
2.可以切换背景,图标
3.重新开始,暂停,进度条
游戏规则:连连看是一款非常经典的游戏,想必绝大多数人都有玩过, 只要将相同花色的两个方块用三根以内的直线连在一起就可以消除,规则十分简单。
大致思路:
 1、绘制棋盘,实现图标的随机放置:
      首先要做出连连看的界面,界面最主要的就是棋盘,棋盘要在周边多出一圈,以便连线时画线。棋盘画好后就要在每个格子中放入图标,图标总共20种,给20种图标分别用标号(1-20)命名,由于棋盘总共有80个格子(10*8),所以每种图标都会出现四次。接下来要让20种图标随机分布在格子中。棋盘对应一个二维数组,遍历这个数组,在每个格子处生成一个1-20的随机数,用于存放该数对应的图标,也将每个格子的状态置为该数,消除后状态置为0。这样,图标就实现了在二维棋盘中随机放置。
2、连通消除:

       首先选中两个图标,再判断这两个图标是否可以消除,消除后对应位置的棋子状态置为0。总共有三种连通方式。第一种是直线连通,包括横向连通和纵向连通,只需判断两个图标中间是否存在状态不为0 的棋子即可,若没有即可连通。第二种是一拐角连通,先通过横纵坐标之间的关系得到拐点处的坐标,再判断两个点到拐点处是否都能直线连通,可以即可连通。第三种是二拐角连通,需要找到两个拐点,通过一个点到其中一个拐点的直线连通和另一个点到这个拐点的一拐角连通是否成立可判断出是否可以进行二拐角连通。

3、其他功能:

洗牌:将剩余的图标存入一个图像类型的集合。遍历剩下位置,随机选取集合中的一个图标放置在该位置,之后删掉集合中该图标,最后重绘界面。

提示:遍历棋盘数组,根据连通规则,找到两个可以连通的图标,用方框圈出两个图标,并实现方框的闪烁。

设置:弹出对话框,设置计时器的时间,洗牌次数和提示次数,更新。

二、代码实现
  • 参数类&棋子类——定义各种全局变量和各种状态
/**
 * 建立参数类
 */
public class Param {
	//-------棋子种数--------
	public static int chessNum = 20;

	//-------设置棋盘的行数和列数(有小图标的)--------
	public static int rows = 8;
	public static int cols = 10;
	
	//-------设置棋子的长和宽-----------
	public static int chessWidth = 48;
	public static int chessHeight = 48;
	
	//-------设置棋盘到边界的距离-----------
	public static int marginWidth = 110 - chessWidth;
	public static int marginHeight = 108 - chessHeight;
	
	//-------设置背景图片--------------
	public static Image imageBackground1 = new ImageIcon("background/1.jpg").getImage();
	public static Image imageBackground2 = new ImageIcon("background/2.jpg").getImage();
	public static Image imageBackground3 = new ImageIcon("background/3.jpg").getImage();
	public static Image imageBackground4 = new ImageIcon("background/4.jpg").getImage();
	public static Image imageBackground5 = new ImageIcon("background/5.jpg").getImage();
	public static Image imageBackground6 = new ImageIcon("background/6.jpg").getImage();
	public static Image imageBackground7 = new ImageIcon("background/7.jpg").getImage();
	public static Image imageBackground8 = new ImageIcon("background/8.jpg").getImage();
	public static Image imageBackground = imageBackground1;
	
	//-------设置左上角图标------------
	public static Image leftPicture = new ImageIcon("pictures/01.jpg").getImage();
	
	//-------设置棋盘上的小图标---------
	public static Image[] chessImage = new Image[chessNum];
	static{
		for(int i = 0; i < chessNum; i++){
			chessImage[i] = new ImageIcon("image/cute_36/" + (i + 1) + ".png").getImage();
		}
	}
	
	//游戏时间  秒
	public static int timeCount = 100;
	//洗牌次数(默认)
	public static int refreshCountConstant = 3;
	//提示次数(默认)
	public static int remarkCountConstant = 3;
	//当前游戏成绩
	public static int score = 0;
	//当前游戏的状态:0没开始;1进行中;2暂停;3游戏结束
	public static int gameStatus = 0;
} 
/**
 * 建立棋子类
 */
public class Chess {

	private int status;// 棋子状态

	public Chess(int status) {
		super();
		this.status = status;
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}
}
  • 主界面&控件定义
JLabel labelStart = new LinkupJLabel("开始");
	JLabel labelRemark = new LinkupJLabel("提示("+remarkCount+")");
	JLabel labelRefresh = new LinkupJLabel("洗牌("+refreshCount+")");
	JLabel labelScore = new JLabel("当前成绩:");
	JLabel labelReStart = new LinkupJLabel("重新开始");
	//定义进度条
	TimerJProgressbar timerJProgressbar = new TimerJProgressbar(this);
	//定义菜单条
	LinkupMenuBar menuBar = new LinkupMenuBar(this);

        // ------设置主窗体--------
	public mainFrame() {
		init();
		//为窗体设置菜单条
		this.setJMenuBar(menuBar);

		this.setTitle("连连看 ^_^");// 窗口标题
		this.setSize(700, 600);// 尺寸
		this.setLocationRelativeTo(null);// 居中
		this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);// 关闭窗口
		this.setResizable(false);// 固定窗口大小
		this.setVisible(true);// 可视化
		this.setIconImage(Param.leftPicture);// 左上角图标
	}
  • 事件监听
private void init() {
		this.setLayout(null);
		
		labelStart.setBounds(20, 20, 80, 25);
		labelReStart.setBounds(20, 55, 80, 25);
		labelRemark.setBounds(110, 20, 80, 25);
		labelRefresh.setBounds(200, 20, 80, 25);
		labelScore.setBounds(300, 20, 150, 25);
		timerJProgressbar.setBounds(460, 20, 200, 23);
		
		this.add(labelStart);
		this.add(labelReStart);
		this.add(labelRemark);
		this.add(labelRefresh);
		this.add(labelScore);
		this.add(timerJProgressbar);

		mapPanel.setBounds(0, 0, 700, 550);
		this.add(mapPanel);
		
		//成绩标签
		labelScore.setForeground(Color.RED);

		// 适配器 简单实现过接口中的方法,可选择性重写方法
		// 抽象类
		labelStart.addMouseListener(new MouseAdapter() {

			//鼠标监听,鼠标进入后 把字体设置变大,离开时还原
			public void mouseEntered(MouseEvent e) {
				labelStart.setFont(new Font("宋体", Font.BOLD, 16));
			    }
			public void mouseExited(MouseEvent e) {
				labelStart.setFont(new Font("宋体", Font.BOLD, 12));
				}
			public void mousePressed(MouseEvent e) {
				
				String text = labelStart.getText();
				if ("开始".equals(text)) {
					Param.gameStatus = 1;
					labelStart.setText("暂停");
					// 启动计时器
					timerJProgressbar.start();
					repaint();
				} else if ("暂停".equals(text)) {
					Param.gameStatus = 2;
					labelStart.setText("继续");
					// 停止计时器
					timerJProgressbar.stop();
					repaint();
				} else if ("继续".equals(text)) {
					Param.gameStatus = 1;
					labelStart.setText("暂停");
					// 启动计时器
					timerJProgressbar.start();
					repaint();
				}
			}
		});

		// 洗牌
		labelRefresh.addMouseListener(new MouseAdapter() {

			@Override
			public void mousePressed(MouseEvent e) {
				// 游戏是否开始?
				if (Param.gameStatus != 1) {
					// 弹出一个消息框
					JOptionPane.showMessageDialog(mainFrame.this,
							"游戏还没开始,请先开始游戏!");
					return;
				}

				// 判断左键
				if (e.getModifiers() != InputEvent.BUTTON1_MASK) {
					return;
				}

				// 按照洗牌次数 来控制洗牌
				if(refreshCount > 0){
					refreshCount--;
					labelRefresh.setText("洗牌(" + refreshCount + ")");
					Core.refreshArr(mapPanel.chess);
					// 界面重新绘制
					repaint();
				}
			}
		});

		// 提示(监听)
		labelRemark.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				// 游戏是否开始?
				if (Param.gameStatus != 1) {
					// 弹出一个消息框
					JOptionPane.showMessageDialog(mainFrame.this,
							"游戏还没开始,请先开始游戏!");
					return;
				}

				// 判断左键
				if (e.getModifiers() != InputEvent.BUTTON1_MASK) {
					return;
				}

				// 找到可以连通的两个点,绘制矩形(闪烁)
				List<Point> list = Core.remarkArr(mapPanel.chess);
				if (list != null) {
					//提示次数设置
					if(remarkCount > 0){
						remarkCount--;
						labelRemark.setText("提示(" + remarkCount + ")");
						remarkDeal(list);
					}
				}

			}
		});
		
		//重新开始
		labelReStart.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				if (e.getModifiers() != InputEvent.BUTTON1_MASK) {
					return;
				}
				restartGame();		
			}
		});

	}

	public void remarkDeal(final List<Point> list) {
		//借助线程实现   闪烁 提示
		new Thread() {

			public void run() {
				// 闪烁三次
				int count = 0;
				while (count < 3) {
					mapPanel.drawMyRect(list.get(0), Color.GREEN);
					mapPanel.drawMyRect(list.get(1), Color.GREEN);
					count++;
					try {
						Thread.sleep(300);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					repaint();
					try {
						Thread.sleep(300);
					} catch (InterruptedException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}

		}.start();

	}
	
	/**
	 * 设置窗体上的成绩标签
	 * @param score
	 */
	public void setScore(int score){
		labelScore.setText("当前成绩:"+score);		
	}
}
  • 核心——连通算法
有以下几种连通方式
1.直线连通:

 

 

2.一拐角连通:
3.二拐角连通:
代码:
//定义静态集合
	private static List<Point> list = new ArrayList<Point>();
	
	//----------判断是否能直线连通的算法-------------
	public static boolean canArrived(Chess[][] arr,Point a,Point b){
		//横向(横坐标相等)a.x == b.x	
		if(a.x == b.x){
			//1、a.y-->b.y
			if(a.y < b.y){
				for(int i = a.y + 1; i < b.y; i++){
					//中间有障碍物,无法连通
					if(arr[a.x][i].getStatus() != 0){
						return false;
					}
				}
				return true;
			}else{
				//2、b.y-->a.y
				for(int i = b.y + 1; i < a.y; i++){
					if(arr[a.x][i].getStatus() != 0){
						return false;
					}
				}
				return true;
			}
		}	
		
		//纵向(纵坐标相等)a.y == b.y
		if(a.y == b.y){
			for(int i = Math.min(a.x, b.x) + 1; i < Math.max(a.x, b.x); i++){
				if(arr[i][a.y].getStatus() != 0){
					return false;
				}
			}
			return true;
		}
		return false;
	}
	
	//------直线连通算法---------------------------	
	public static List<Point> noCorner(Chess[][] arr,Point a,Point b){
		if(canArrived(arr,a,b)){
			list.add(a);
			list.add(b);
			return list;
		}
		return null;
	}
	
	
	//------一拐角连通算法-------------------------
	public static List<Point> oneCorner(Chess[][] arr,Point a,Point b){
		//拐点c:a.x == c.x && b.y == c.y
		Point c = new Point(a.x,b.y);
		if(arr[c.x][c.y].getStatus() == 0 && canArrived(arr,a,c) 
				&& canArrived(arr,c,b)){
			list.add(a);
			list.add(c);
			list.add(b);
			return list;
		}
		
		//拐点d:b.x == c.x && a.y == c.y
		Point d = new Point(b.x,a.y);
		if(arr[d.x][d.y].getStatus() == 0 && canArrived(arr,a,d) 
				&& canArrived(arr,d,b)){
			list.add(a);
			list.add(d);
			list.add(b);
			return list;
		}
		return null;
	}
	
	
	//------二拐角连通算法-------------------------
	public static List<Point> twoCorner(Chess[][] arr,Point a,Point b){
		//横向(横坐标不变,纵坐标变)
		for(int i = 0; i < arr[0].length; i++){
			Point c = new Point(a.x,i);
			if(arr[c.x][c.y].getStatus() == 0 && canArrived(arr,a,c) 
					&& oneCorner(arr,c,b) != null){
				list.add(0,a);
				return list;
			}
		}
	
		//纵向(纵坐标不变,横坐标变)
		for(int i = 0; i < arr.length; i++){
			Point d = new Point(i,a.y);
			if(arr[d.x][d.y].getStatus() == 0 && canArrived(arr,a,d) 
					&& oneCorner(arr,d,b) != null){
				list.add(0,a);
				return list;
			}
		}

		return null;
	}
	
	//-----连通总的判断算法(集合为空则不连通)---------
		public static List<Point> checkLinked(Chess[][] arr,Point a,Point b){
			//判断两个点是否图标状态一致 不一致则不能连通
			if(arr[a.x][a.y].getStatus() != arr[b.x][b.y].getStatus()){
				return null;
			}
			list.clear();//每次判断前先清空集合
			//直线连通
			if(noCorner(arr,a,b) != null){
				return list;
			}
			//一拐角连通
			if(oneCorner(arr,a,b) != null){
				return list;
			}
			//二拐角连通
			if(twoCorner(arr,a,b) != null){
				return list;
			}
			return null;
		}
  • 获取两个图标位置,实现连通并重绘界面
public class MapPanel extends JPanel implements MouseListener{
	//定义两个点 存放数组下标
	Point firstPoint;
	Point secondPoint;
	
	mainFrame Frame;
	
	Chess[][] chess = null;
	//---构造函数中初始化数组并注册监听器,把窗体作为参数传递到面板中----
	public MapPanel(mainFrame Frame){
		this.Frame = Frame;
		initChess();//初始化棋盘
		this.addMouseListener(this);
		this.setCursor(new Cursor(Cursor.HAND_CURSOR));
	}
	
	//---------棋盘状态函数(状态值1-20)---------
	public void initChess(){
		//一定要重新创建数组
		chess =  new Chess[Param.rows + 2][Param.cols + 2];
		Random random = new Random();
		for(int i = 1; i <= Param.chessNum; i++){
			int count = 0;
			while(count < 4){
				//随机选取一个没有设置过状态的位置,设置为当前的状态值
				int x = random.nextInt(Param.rows) + 1;//横坐标0-7 --> 1-8[9](0和9设置状态为0)
				int y = random.nextInt(Param.cols) + 1;//纵坐标0-9 --> 1-10[11](0和11设置状态为0)
				if(chess[x][y] == null){
					chess[x][y] = new Chess(i);
					count++;
				}
			}
		}
		//外围设置为0
		for(int i = 0; i < chess.length; i++){
			chess[i][0] = new Chess(0);
			chess[i][chess[0].length - 1] = new Chess(0);
		}
		for(int i = 0; i < chess[0].length; i++){
			
			chess[0][i] = new Chess(0);
			chess[chess.length - 1][i] = new Chess(0);
		}
	}
	//--------设置线条粗细---Graphics2D 工具类配合使用----------
	Stroke stroke = new BasicStroke(3.0f);
	
	//------重写paint方法-------
	public void paint(Graphics g){
		super.paint(g);
		g.drawImage(Param.imageBackground,0,0,this);//背景
		g.setColor(Color.green);//颜色
		Font font = new Font("楷书",Font.BOLD,28);//字体
		g.setFont(font);//得到所设置的字体
		//g.drawString("连连看小游戏", 250, 70);//绘制字符串(绿色,font设置的字体)
		//判断游戏的状态值 绘制不同信息
		
		if (Param.gameStatus == 0) {
			g.drawString("游戏还没有开始...", 200, 200);

		} else if (Param.gameStatus == 2) {
			g.drawString("游戏暂停中...", 200, 200);

		} else if (Param.gameStatus == 3) {
			g.drawString("当前游戏结束...", 200, 200);

		} else {
			//----将图片随机放入棋盘中-----
			for(int i = 1; i <= Param.rows; i++){
				for(int j = 1; j <= Param.cols; j++){
					if(chess[i][j].getStatus() != 0){
						g.drawImage(Param.chessImage[chess[i][j].getStatus() - 1],
							Param.marginWidth + Param.chessWidth*j,
							Param.marginHeight + Param.chessHeight*i,this);
						g.drawRect(Param.marginWidth + Param.chessWidth*j,
							Param.marginHeight + Param.chessHeight*i,
							Param.chessWidth,Param.chessHeight);
					}
				}
			}
		}
		//判断第一个点是否为空
		if(firstPoint != null){
			drawMyRect(firstPoint,Color.blue);
		}
	}
	//重写鼠标点击方法,实现鼠标点击出现小方框
		public void mousePressed(MouseEvent e) {
			//游戏状态值  1进行中
			if(Param.gameStatus!=1){
				return;
			}
			
			//不是左键的判断
			if(e.getModifiers() != InputEvent.BUTTON1_MASK){
				return;
			}
			
			//----是左键----获取点击处的坐标--------
			int x = e.getX();
			int y = e.getY();
			
			//-----将坐标化为数组下标---->再化为左顶点处的坐标---->画出矩形
			//判断当前坐标是否在棋盘内
			if(x < Param.marginWidth + Param.chessWidth || x >= Param.marginWidth + Param.chessWidth * (Param.cols + 1)
		|| y < Param.marginHeight + Param.chessHeight || y >= Param.marginHeight + Param.chessHeight*(Param.rows + 1)){
				return;
			}
				int X = (y - Param.marginHeight)/Param.chessHeight;
				int Y = (x - Param.marginWidth)/Param.chessWidth;
				
				// 判断当前的位置是否已经消掉 图标状态值为0
				if (chess[X][Y].getStatus() == 0) {
					return;
				}
				int rowx = X*Param.chessWidth + Param.marginWidth;
				int rowy = Y*Param.chessHeight + Param.marginHeight;
	
				//第一次点击firstPoint||重复点击firstPoint
				if(firstPoint == null || (firstPoint.x == X && firstPoint.y == Y)){
					firstPoint = new Point(X,Y);
					drawMyRect(firstPoint,Color.blue);
					return;
					}
				
				//第二点
				secondPoint = new Point(X,Y);
				drawMyRect(secondPoint,Color.red);
			
				//状态相同:连通算法
				List<Point> list = Core.checkLinked(chess,firstPoint,secondPoint);
				if(list == null){
					firstPoint = secondPoint;
					Frame.repaint();
					return;
				}
				//可以连通:状态值设为0;将两点放空,绘制连接线,重画界面
				chess[firstPoint.x][firstPoint.y].setStatus(0);
				chess[secondPoint.x][secondPoint.y].setStatus(0);
				firstPoint = null;
				secondPoint = null;
				drawLinkedLine(list);
				Frame.repaint();
				Param.score += 10;
				Frame.setScore(Param.score);
		}
	public void mouseClicked(MouseEvent e) {}
	public void mouseReleased(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	//------绘制连通线--------------------------
	private void drawLinkedLine(List<Point> list) {
			Graphics2D G = (Graphics2D)this.getGraphics();
			G.setColor(Color.blue);
			G.setStroke(stroke);
			if(list.size() == 2){
				Point a = list.get(0);
				Point b = list.get(1);
				int ax = Param.marginWidth + a.y*Param.chessWidth + Param.chessWidth/2;
				int ay = a.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				int bx = b.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int by = b.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				G.drawLine(ax,ay,bx,by);
			}
			
			if(list.size() == 3){
				Point a = list.get(0);
				Point c = list.get(1);
				Point b = list.get(2);
				int ax = a.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int ay = a.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				int cx = c.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int cy = c.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				int bx = b.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int by = b.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				G.drawLine(ax, ay, cx, cy);
				G.drawLine(cx, cy, bx, by);
			}
			
			if(list.size() == 4){
				Point a = list.get(0);
				Point c = list.get(1);
				Point d = list.get(2);
				Point b = list.get(3);
				int ax = a.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int ay = a.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				int cx = c.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int cy = c.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				int dx = d.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int dy = d.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;		
				int bx = b.y*Param.chessWidth+Param.marginWidth+Param.chessWidth/2;
				int by = b.x*Param.chessHeight+Param.marginHeight+Param.chessHeight/2;
				G.drawLine(ax, ay, cx, cy);
				G.drawLine(cx, cy, dx, dy);
				G.drawLine(dx, dy, bx, by);
			}
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	public void drawMyRect(Point p,Color c){
		Graphics g = getGraphics();
		Graphics2D G = (Graphics2D) g;
		G.setStroke(stroke);
		G.setColor(c);
		int rowx = p.y*Param.chessWidth + Param.marginWidth;
		int rowy = p.x*Param.chessHeight + Param.marginHeight;
		G.drawRect(rowx + 2, rowy + 2, Param.chessWidth - 4, Param.chessHeight - 4);
	}

}
  • 其他一些小功能实现

 

 

 

/**
 * 菜单设置
 * @author lenovo
 *
 */
public class LinkupMenuBar extends JMenuBar{
	//设置:游戏参数,设置背景,设置棋子,查看成绩,退出游戏
	//帮助:游戏规则,游戏版权
	
	JMenuItem menuItemParam = new JMenuItem("游戏参数");
	JMenuItem menuItemBackground = new JMenu("游戏背景");
	JMenuItem menuItemChessIcon = new JMenu("设置棋子");
	JMenuItem menuItemScore = new JMenuItem("查看成绩");
	JMenuItem menuItemExit = new JMenuItem("退出游戏");
	JMenuItem menuItemRule = new JMenuItem("游戏规则");
	JMenuItem menuItemAbout = new JMenuItem("游戏版权");
	
	mainFrame frame;
	public LinkupMenuBar(mainFrame frame){
		this.frame = frame;
		this.init();
		
	}
	private void init(){
		JMenu menuSet = new JMenu("设置");
		
		//添加到设置中的菜单条
		menuSet.add(menuItemParam);
		menuSet.add(menuItemBackground);
		menuSet.add(menuItemChessIcon);
		menuSet.add(menuItemScore);
		menuSet.add(menuItemExit);
		
		
		//添加背景图片二级菜单
		String[] arr = new String[]{"背景1","背景2","背景3","背景4","背景5","背景6","背景7","背景8"};
		ButtonGroup buttonGroup =  new ButtonGroup();//互斥按钮
		for(int i = 0; i < arr.length; i++){
			final JCheckBoxMenuItem jCheckBoxMenuItem =  new JCheckBoxMenuItem(arr[i]);//二级菜单
			menuItemBackground.add(jCheckBoxMenuItem);
			buttonGroup.add(jCheckBoxMenuItem);
			//监听
			jCheckBoxMenuItem.addActionListener(new ActionListener(){
				public void actionPerformed(ActionEvent e){
					String text = jCheckBoxMenuItem.getText();
					if(text.equals("背景1")){
						Param.imageBackground = Param.imageBackground1;
					}else if(text.equals("背景2")){
						Param.imageBackground = Param.imageBackground2;
					}else if(text.equals("背景3")){
						Param.imageBackground = Param.imageBackground3;
					}else if(text.equals("背景4")){
						Param.imageBackground = Param.imageBackground4;
					}else if(text.equals("背景5")){
						Param.imageBackground = Param.imageBackground5;
					}else if(text.equals("背景6")){
						Param.imageBackground = Param.imageBackground6;
					}else if(text.equals("背景7")){
						Param.imageBackground = Param.imageBackground7;
					}else if(text.equals("背景8")){
						Param.imageBackground = Param.imageBackground8;
					}
					frame.repaint();
				}
			});
		}
		
		JMenu menuHelp = new JMenu("帮助");
		menuHelp.add(menuItemRule);
		menuHelp.add(menuItemAbout);
		this.add(menuSet);
	    this.add(menuHelp);	
	  		
		// 退出菜单栏监听
		menuItemExit.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

			}
		});
		menuItemScore.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

			}
		});

		// 游戏参数
		menuItemParam.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				//创建对话框
				new ParamJDialog(frame);
			}
		});
		// 游戏规则
		menuItemRule.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

			}
		});
		// 游戏版权
		menuItemAbout.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

			}
		});
	}
}

 

 

 

2.洗牌
/**
		 * 洗牌实现:没有消掉的图标 随机分布一次
		 * @param arr
		 */
		public static void refreshArr(Chess[][] arr){
			List<Chess> list = new ArrayList<Chess>();
			for (int i = 0; i < arr.length; i++) {
				for (int j = 0; j < arr[i].length; j++) {
					if(arr[i][j].getStatus()!=0){
						list.add(arr[i][j]);
					}
				}
			}
			//随机获得集合的索引,放到数组元素中即可
			Random random = new Random();
			for (int i = 0; i < arr.length; i++) {
				for (int j = 0; j < arr[i].length; j++) {
					//有图标的位置重新分配新图标
					if(arr[i][j].getStatus()!=0){
						int index = random.nextInt(list.size());
						arr[i][j] = list.get(index);
						//移除 指定索引的元素
						list.remove(index);
					}
				}
			}		
		}

3.提示

/**
		 * 提示 算法实现:寻找可以连通的两个点
		 * @param arr
		 * @return
		 */
		public static List<Point> remarkArr(Chess[][] arr){
			for (int i = 0; i < arr.length; i++) {
				for (int j = 0; j < arr[i].length; j++) {
					if(arr[i][j].getStatus()==0){
						continue;
					}
					for (int x = 0; x < arr.length; x++) {
						for (int y = 0; y < arr[x].length; y++) {
							if(arr[x][y].getStatus()==0){
								continue;
							}	
							//避免同一个点的下标
							if(i==x&&j==y){
								continue;
							}
							Point a = new Point(i,j);
							Point b = new Point(x,y);
							//判断是否可以连通
							if(checkLinked(arr, a, b)!=null){
								List<Point> list = new ArrayList<Point>();
								list.add(a);
								list.add(b);
								return list;
							}		
						}
					}
				}
			}
			return null;
		}

4.计时器计时

/**
 * 具备计时器功能的进度条
 * @author lenovo
 *
 */
public class TimerJProgressbar extends JProgressBar implements ActionListener{

	int count = Param.timeCount;//时间
	Timer timer = new Timer(1000, this);//隔1000毫秒执行this操作
	mainFrame Frame;
	
	public TimerJProgressbar(mainFrame Frame) {
		this.Frame = Frame;
		this.setMaximum(count);//进度条的最大值
		this.setValue(count);
		this.setString(count+"秒");//进度条现实的字符串
		this.setStringPainted(true);//可视
		this.setForeground(Color.green);//颜色	
	}
	
	public void actionPerformed(ActionEvent e) {
		//每次间隔会执行的方法
		count--;
		this.setValue(count);
		this.setString(count+"秒");
		//count<=0   游戏结束:停止计时器,界面屏蔽;游戏状态值3;记录成绩
		if(count <= 0){
			stop();
			Param.gameStatus = 3;
			JOptionPane.showMessageDialog(this,"游戏结束!");
		}
	}
	
	/**
	 * 启动定时器
	 */
	public void start(){
		timer.start();
	}
	
	/**
	 * 停止定时器
	 */
	public void stop(){
		timer.stop();
	}
	
	/**
	 * 重置定时器
	 */
	public void reset(){
		timer.stop();
		count = Param.timeCount;
		this.setMaximum(count);
		this.setValue(count);
		this.setString(count+"秒");
	}

}

5.设置时间、洗牌次数、提示次数

/**
 * 对话框设置(包含标签文本框的设置)
 * @author lenovo
 *
 */
public class ParamJDialog extends JDialog{

	//定义文本框:游戏时间设置;刷新次数设置;提示时间设置
	private JTextField textFieldTime = new JTextField(Param.timeCount + "");
	private JTextField textFieldRefleshCount = new JTextField(
			Param.refreshCountConstant + "");
	private JTextField textFieldReMarkCount = new JTextField(
			Param.remarkCountConstant + "");
	
	//定义按钮
	private JButton buttonSure = new JButton("确定");
	private JButton buttonCancel = new JButton("取消");
	
	mainFrame frame;
	public ParamJDialog(mainFrame frame){
		super(frame);
		this.frame = frame;
		init();
		
		//设置窗口
		setTitle("游戏参数设置");
		this.setSize(new Dimension(300, 250));
		this.setLocationRelativeTo(frame);//在窗体中央

		this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		this.setResizable(false);
		this.setModal(true);
		this.setVisible(true);
	}
	private void init(){
		this.setLayout(null);//设置空布局
		//设置标签
		JLabel labelTime = new JLabel("游戏时间:");
		JLabel labelReflesh = new JLabel("刷新次数:");
		JLabel labelRemark = new JLabel("提示次数:");
		JLabel labelTimeMessage = new JLabel("秒(整数)");
		JLabel labelRefleshMessage = new JLabel("*整数");
		JLabel labelRemarkMessage = new JLabel("*整数");
		
		//给标签添加属性----颜色
		labelTimeMessage.setForeground(Color.red);
		labelRefleshMessage.setForeground(Color.red);
		labelRemarkMessage.setForeground(Color.red);
		
		//位置大小的设定
		labelTime.setBounds(60, 20, 60, 25);
		textFieldTime.setBounds(121, 20, 60, 25);
		labelTimeMessage.setBounds(182, 20, 60, 25);

		labelReflesh.setBounds(60, 60, 60, 25);
		textFieldRefleshCount.setBounds(121, 60, 60, 25);
		labelRefleshMessage.setBounds(182, 60, 60, 25);

		labelRemark.setBounds(60, 100, 60, 25);
		textFieldReMarkCount.setBounds(121, 100, 60, 25);
		labelRemarkMessage.setBounds(182, 100, 60, 25);

		buttonSure.setBounds(60, 140, 60, 25);
		buttonCancel.setBounds(150, 140, 60, 25);
		
		//将文本框、标签添加到对话框中
		this.add(labelTime);
		this.add(textFieldTime);
		this.add(labelTimeMessage);

		this.add(labelReflesh);
		this.add(textFieldRefleshCount);
		this.add(labelRefleshMessage);

		this.add(labelRemark);
		this.add(textFieldReMarkCount);
		this.add(labelRemarkMessage);

		this.add(buttonSure);
		this.add(buttonCancel);
		initEvent();
	}
	
	/**
	 * 给按钮添加监听
	 * @param args
	 */
	private void initEvent() {
		buttonSure.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// 从文本框中获得时间
				String timeText = textFieldTime.getText();
				int time = 0;
				try {
					time = Integer.parseInt(timeText);
					if (!(10 <= time && time <= 600)) {
						JOptionPane.showMessageDialog(frame,"时间范围不合法,范围[10~600]!");
						return;
					}
				} catch (Exception e2) {
					JOptionPane.showMessageDialog(frame, "时间必须为数字,范围[10~600]!");
					return;
				}

				//从文本框中获得洗牌次数
				String refreshText = textFieldRefleshCount.getText();
				int refreshCount = 0;
				try {
					refreshCount = Integer.parseInt(refreshText);
					if (!(3 <= refreshCount && refreshCount <= 20)) {
						JOptionPane.showMessageDialog(frame,
								"洗牌次数范围不合法,范围[3~20]!");
						return;
					}
				} catch (Exception e2) {
					JOptionPane.showMessageDialog(frame, "洗牌次数必须为数字,范围[3~20]!");
					return;
				}

				// 从文本框中获得提示次数
				String reMarkText = textFieldReMarkCount.getText();
				int reMarkCount = 0;
				try {
					reMarkCount = Integer.parseInt(reMarkText);// 8984398
					if (!(3 <= reMarkCount && reMarkCount <= 20)) {
						JOptionPane.showMessageDialog(frame,
								"提示次数范围不合法,范围[3~20]!");
						return;
					}
				} catch (Exception e2) {
					JOptionPane.showMessageDialog(frame, "提示次数必须为数字,范围[3~20]!");
					return;
				}
				// 销毁对话框
				dispose();
				// 合法
				Param.timeCount = time;
				Param.refreshCountConstant = refreshCount;
				Param.remarkCountConstant = reMarkCount;
				frame.restartGame();
			}
		});

		// 销毁对话框
		buttonCancel.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				dispose();//销毁对话框
			}
		});

	}

}

6.重新开始游戏

/**
	 * 重新开始游戏方法
	 */
	public void restartGame(){
		//游戏状态值 1
		Param.gameStatus = 1;
		//进度条定时器 重置
		timerJProgressbar.reset();
		//洗牌次数,提示次数 还原
		refreshCount = Param.refreshCountConstant;
		remarkCount = Param.remarkCountConstant;
		labelRefresh.setText("洗牌("+Param.refreshCountConstant+")");
		labelRemark.setText("提示("+Param.remarkCountConstant+")");
		//游戏成绩0
		Param.score = 0;
		setScore(0);
		//棋盘数组重新 部署
		mapPanel.initChess();
		//设置 暂停
		labelStart.setText("暂停");
		// 启动计时器?
		timerJProgressbar.start();
		//界面重新绘制
		repaint();
	}

 

【源码的github地址】https://github.com/leijing000/linkup

 

 

 

 

  • 14
    点赞
  • 106
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值