基于JAVA实现的连连看小游戏

Java连连看小游戏实现:

     连连看小游戏曾经在我们的童年给我们带来了很多乐趣。连连看这款游戏现在基本上没人玩了,甚至在新一代人的印象中都已毫无记忆了。。。但是,这款游戏可以在一定程度上锻炼自己的编程能力。

运行效果如图:

游戏面板实现:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class GamePanel extends JPanel implements ActionListener ,MouseListener,KeyListener{

   private Image[] pics;//图片数组
   private int n;//行列数
   private int[][] map;//存储地图信息
   private int leftX = 140,leftY = 80;//row,column表示人物坐标;leftX,leftY记载左上角图片位置
   private boolean isClick = false;//标记是否第一次选中图片
   private int clickId,clickX,clickY;//记录首次选中图片的id,以及数组下标
   private int linkMethod;//连接方式
   private Node z1,z2;//存储拐角点的信息
   private Map mapUtil;//地图工具类
   public static int count = 0;//存储消去图案的个数


   public static final int LINKBYHORIZONTAL = 1,LINKBYVERTICAL = 2,LINKBYONECORNER = 3,LINKBYTWOCORNER = 4;
   public static final int BLANK_STATE = -1;

   public GamePanel(int count){
      setSize(600, 600);
      n = 10;
      mapUtil = new Map(count, n);
      map = mapUtil.getMap();//获取初始时,图片种类为count,行列数为n的地图信息
      this.setVisible(true);
      this.addKeyListener(this);
      this.addMouseListener(this);
      this.setFocusable(true);
      getPics();
      repaint();
   }


   //初始化图片数组
   private void getPics() {
      pics = new Image[10];
      for(int i=0;i<=9;i++){
         pics[i] = Toolkit.getDefaultToolkit().getImage(".\\lianliankan\\src\\main\\java\\com\\llk\\util\\linkGame\\pic"+(i+1)+".png");
      }
   }



   public void paint(Graphics g){
      g.clearRect(0, 0, 800, 30);

      for(int i=0;i<n;i++){
         for(int j=0;j<n;j++){
            if(map[i][j]!=BLANK_STATE){
               g.drawImage(pics[map[i][j]],leftX+j*50,leftY+i*50,50,50,this);
            }else{
               g.clearRect(leftX+j*50,leftY+i*50,50,50);
            }
         }
      }

   }


   //判断是否可以水平相连
   private boolean horizontalLink(int clickX1, int clickY1, int clickX2, int clickY2) {

      if(clickY1>clickY2){//保证y1<y2
         int temp1 = clickX1;
         int temp2 = clickY1;
         clickX1 = clickX2;
         clickY1 = clickY2;
         clickX2 = temp1;
         clickY2 = temp2;
      }

      if(clickX1==clickX2){//如果两个选中图片的所在行数相同,说明可能可以水平相联

         for(int i=clickY1+1;i<clickY2;i++){
            if(map[clickX1][i]!=BLANK_STATE){//如果两图片中间还有其他图片,说明不能直接水平相连
               return false;
            }
         }

         //System.out.println("我们俩水平相连,我的下标是("+clickX1+","+clickY1+"),它的坐标是("+clickX2+","+clickY2+")");
         linkMethod = LINKBYHORIZONTAL;
         return true;
      }


      return false;
   }


   //判断是否可以垂直连接
   private boolean verticalLink(int clickX1, int clickY1, int clickX2, int clickY2) {

      if(clickX1>clickX2){//保证x1<x2
         int temp1 = clickX1;
         int temp2 = clickY1;
         clickX1 = clickX2;
         clickY1 = clickY2;
         clickX2 = temp1;
         clickY2 = temp2;
      }

      if(clickY1==clickY2){//如果两个选中图片的所在列数相同,说明可能可以垂直相联

         for(int i=clickX1+1;i<clickX2;i++){
            if(map[i][clickY1]!=BLANK_STATE){//如果两图片中间还有其他图片,说明不能直接垂直相连
               return false;
            }
         }

         linkMethod = LINKBYVERTICAL;
         //System.out.println("我们俩垂直相连,我的下标是("+clickX1+","+clickY1+"),它的坐标是("+clickX2+","+clickY2+")");

         return true;
      }



      return false;
   }

   //判断是否可以通过一个拐点相连
   private boolean oneCornerLink(int clickX1, int clickY1, int clickX2, int clickY2) {

      if(clickY1>clickY2){//保证(x1,y1)是矩形的左上角或者左下角
         int temp1 = clickX1;
         int temp2 = clickY1;
         clickX1 = clickX2;
         clickY1 = clickY2;
         clickX2 = temp1;
         clickY2 = temp2;
      }

      if(clickX1<clickX2){//如果(x1,y1)位于矩形左上角

         //判断右上角是否为空并且可以直接与(x1,y1)(x2,y2)相连接,(clickX1, clickY2)是右上角拐点下标
         if(map[clickX1][clickY2]==BLANK_STATE&&horizontalLink(clickX1, clickY1, clickX1, clickY2)&&verticalLink(clickX2,clickY2,clickX1,clickY2)){
            linkMethod = LINKBYONECORNER;
            z1 = new Node(clickX1,clickY2);
            return true;
         }

         //判断左下角是否为空并且可以直接与(x1,y1)(x2,y2)相连接,(clickX2, clickY1)是左下角拐点下标
         if(map[clickX2][clickY1]==BLANK_STATE&&horizontalLink(clickX2, clickY2, clickX2, clickY1)&&verticalLink(clickX1,clickY1,clickX2, clickY1)){
            linkMethod = LINKBYONECORNER;
            z1 = new Node(clickX2,clickY1);
            return true;
         }

      }else{//如果(x1,y1)位于矩形左下角

         //判断左上角是否为空并且可以直接与(x1,y1)(x2,y2)相连接,(clickX2, clickY1)是左上角拐点下标
         if(map[clickX2][clickY1]==BLANK_STATE&&horizontalLink(clickX2, clickY2, clickX2, clickY1)&&verticalLink(clickX1,clickY1,clickX2, clickY1)){
            linkMethod = LINKBYONECORNER;
            z1 = new Node(clickX2,clickY1);
            return true;
         }

         //判断右下角是否为空并且可以直接与(x1,y1)(x2,y2)相连接,(clickX1, clickY2)是右下角拐点下标
         if(map[clickX1][clickY2]==BLANK_STATE&&horizontalLink(clickX1, clickY1, clickX1, clickY2)&&verticalLink(clickX2,clickY2,clickX1, clickY2)){
            linkMethod = LINKBYONECORNER;
            z1 = new Node(clickX1,clickY2);
            return true;
         }

      }

      return false;
   }



   //判断是否可以通过两个拐点相连
   private boolean twoCornerLink(int clickX1, int clickY1, int clickX2, int clickY2) {

      //向上查找
      for(int i=clickX1-1;i>=-1;i--){

         //两个拐点在选中图案的上侧,并且两个拐点在地图区域之外
         if(i==-1&&throughVerticalLink(clickX2, clickY2, true)){
            z1 = new Node(-1,clickY1);
            z2 = new Node(-1,clickY2);
            linkMethod = LINKBYTWOCORNER;
            return true;
         }

         if(i>=0&&map[i][clickY1]==BLANK_STATE){

            if(oneCornerLink(i, clickY1, clickX2, clickY2)){
               linkMethod = LINKBYTWOCORNER;
               z1 = new Node(i,clickY1);
               z2 = new Node(i,clickY2);
               return true;
            }


         }else{
            break;
         }

      }

      //向下查找
      for(int i=clickX1+1;i<=n;i++){

         //两个拐点在选中图案的下侧,并且两个拐点在地图区域之外
         if(i==n&&throughVerticalLink(clickX2, clickY2, false)){
            z1 = new Node(n,clickY1);
            z2 = new Node(n,clickY2);
            linkMethod = LINKBYTWOCORNER;
            return true;
         }

         if(i!=n&&map[i][clickY1]==BLANK_STATE){

            if(oneCornerLink(i, clickY1, clickX2, clickY2)){
               linkMethod = LINKBYTWOCORNER;
               z1 = new Node(i,clickY1);
               z2 = new Node(i,clickY2);
               return true;
            }

         }else{
            break;
         }

      }


      //向左查找
      for(int i=clickY1-1;i>=-1;i--){

         //两个拐点在选中图案的左侧,并且两个拐点在地图区域之外
         if(i==-1&&throughHorizontalLink(clickX2, clickY2, true)){
            linkMethod = LINKBYTWOCORNER;
            z1 = new Node(clickX1,-1);
            z2 = new Node(clickX2,-1);
            return true;
         }


         if(i!=-1&&map[clickX1][i]==BLANK_STATE){

            if(oneCornerLink(clickX1, i, clickX2, clickY2)){
               linkMethod = LINKBYTWOCORNER;
               z1 = new Node(clickX1,i);
               z2 = new Node(clickX2,i);
               return true;
            }

         }else{
            break;
         }

      }

      //向右查找
      for(int i=clickY1+1;i<=n;i++){

         //两个拐点在选中图案的右侧,并且两个拐点在地图区域之外
         if(i==n&&throughHorizontalLink(clickX2, clickY2, false)){
            z1 = new Node(clickX1,n);
            z2 = new Node(clickX2,n);
            linkMethod = LINKBYTWOCORNER;
            return true;
         }

         if(i!=n&&map[clickX1][i]==BLANK_STATE){

            if(oneCornerLink(clickX1, i, clickX2, clickY2)){
               linkMethod = LINKBYTWOCORNER;
               z1 = new Node(clickX1,i);
               z2 = new Node(clickX2,i);
               return true;
            }

         }else{
            break;
         }

      }


      return false;
   }


   //根据flag,判断(x1,y1)左右两侧中的一侧是否还有其他图片,如果没有,可以相连
   private boolean throughHorizontalLink(int clickX, int clickY,boolean flag){

      if(flag){//向左查找

         for(int i=clickY-1;i>=0;i--){
            if(map[clickX][i]!=BLANK_STATE){
               return false;
            }
         }

      }else{//向右查找

         for(int i=clickY+1;i<n;i++){
            if(map[clickX][i]!=BLANK_STATE){
               return false;
            }
         }

      }

      return true;
   }


   //根据flag,判断(x1,y1)上下两侧中的一侧是否还有其他图片,如果没有,可以相连
   private boolean throughVerticalLink(int clickX,int clickY,boolean flag){

      if(flag){//向上查找

         for(int i=clickX-1;i>=0;i--){
            if(map[i][clickY]!=BLANK_STATE){
               return false;
            }
         }

      }else{//向下查找

         for(int i=clickX+1;i<n;i++){
            if(map[i][clickY]!=BLANK_STATE){
               return false;
            }
         }

      }


      return true;
   }

   //画选中框
   private void drawSelectedBlock(int x, int y, Graphics g) {
      Graphics2D g2 = (Graphics2D) g;//生成Graphics对象
      BasicStroke s = new BasicStroke(1);//宽度为1的画笔
      g2.setStroke(s);
      g2.setColor(Color.RED);
      g.drawRect(x+1, y+1, 48, 48);
   }

   //画线,此处的x1,y1,x2,y2二维数组下标
   @SuppressWarnings("static-access")
   private void drawLink(int x1, int y1, int x2, int y2) {

      Graphics g = this.getGraphics();
      Point p1 = new Point(y1*50+leftX+25,x1*50+leftY+25);
      Point p2 = new Point(y2*50+leftX+25,x2*50+leftY+25);
      if(linkMethod == LINKBYHORIZONTAL || linkMethod == LINKBYVERTICAL){
         g.drawLine(p1.x, p1.y,p2.x, p2.y);
         System.out.println("无拐点画线");
      }else if(linkMethod ==LINKBYONECORNER){
         Point point_z1 = new Point(z1.y*50+leftX+25,z1.x*50+leftY+25);//将拐点转换成像素坐标
         g.drawLine(p1.x, p1.y,point_z1.x, point_z1.y);
         g.drawLine(p2.x, p2.y,point_z1.x, point_z1.y);
         System.out.println("单拐点画线");
      }else{
         Point point_z1 = new Point(z1.y*50+leftX+25,z1.x*50+leftY+25);
         Point point_z2 = new Point(z2.y*50+leftX+25,z2.x*50+leftY+25);

         if(p1.x!=point_z1.x&&p1.y!=point_z1.y){//保证(x1,y1)与拐点z1在同一列或者同一行
            Point temp;
            temp = point_z1;
            point_z1 = point_z2;
            point_z2 = temp;
         }

         g.drawLine(p1.x, p1.y, point_z1.x, point_z1.y);
         g.drawLine(p2.x, p2.y, point_z2.x, point_z2.y);
         g.drawLine(point_z1.x,point_z1.y, point_z2.x, point_z2.y);

         System.out.println("双拐点画线");
      }

      count+=2;//消去的方块数目+2
      GameClient.textField.setText(count+"");
      try {
         Thread.currentThread().sleep(500);//延时500ms
      } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      repaint();
      map[x1][y1] = BLANK_STATE;
      map[x2][y2] = BLANK_STATE;
      isWin();//判断游戏是否结束
   }


   public void clearSelectBlock(int i,int j,Graphics g){
      g.clearRect(j*50+leftX, i*50+leftY, 50, 50);
      g.drawImage(pics[map[i][j]],leftX+j*50,leftY+i*50,50,50,this);
//    System.out.println("清空选定"+i+","+j);
   }


   //提示,如果有可以连接的方块就消去并且返回true
   private boolean find2Block() {

//    boolean isFound = false;

      if(isClick){//如果之前玩家选中了一个方块,清空该选中框
         clearSelectBlock(clickX, clickY, this.getGraphics());
         isClick = false;
      }

      for(int i=0;i<n;i++){
         for(int j=0;j<n;j++){

            if(map[i][j]==BLANK_STATE){
               continue;
            }

            for(int p=i;p<n;p++){
               for(int q=0;q<n;q++){
                  if(map[p][q]!=map[i][j]||(p==i&&q==j)){//如果图案不相等
                     continue;
                  }

                  if(verticalLink(p,q,i,j)||horizontalLink(p,q,i,j)
                        ||oneCornerLink(p,q,i,j)||twoCornerLink(p,q,i,j)){
                     drawSelectedBlock(j*50+leftX, i*50+leftY, this.getGraphics());
                     drawSelectedBlock(q*50+leftX, p*50+leftY, this.getGraphics());
                     drawLink(p, q, i, j);
                     repaint();
                     return true;
                  }

               }
            }
         }
      }

      isWin();

      return false;
   }


   private void isWin() {

      if(count==n*n){
         String msg = "恭喜您通关成功,是否开始新局?";
         int type = JOptionPane.YES_NO_OPTION;
         String title = "过关";
         int choice = 0;
         choice = JOptionPane.showConfirmDialog(null, msg,title,type);
         if(choice==1){
            System.exit(0);
         }else if(choice == 0){
            startNewGame();
         }
      }

   }



   public void startNewGame() {
      // TODO Auto-generated method stub
      count = 0;
      mapUtil = new Map(10,n);
      map = mapUtil.getMap();
      isClick = false;
      clickId = -1;
      clickX = -1;
      clickY = -1;
      linkMethod = -1;
      GameClient.textField.setText(count+"");
      repaint();
   }



   public class Node{
      int x;
      int y;

      public Node(int x,int y){
         this.x = x;
         this.y = y;
      }

   }

   @Override
   public void keyPressed(KeyEvent e) {
      // TODO Auto-generated method stub

      if(e.getKeyCode() == KeyEvent.VK_A){//打乱地图
         map = mapUtil.getResetMap();
         repaint();
      }

      if(e.getKeyCode() == KeyEvent.VK_D){//智能提示
         if(!find2Block()){
            JOptionPane.showMessageDialog(this, "没有可以连通的方块了");
         }

         isWin();//判断是否游戏结束

      }
   }

   @Override
   public void mousePressed(MouseEvent e) {
      // TODO Auto-generated method stub

      Graphics g = this.getGraphics();

      int x = e.getX()-leftX;//点击位置x-偏移量x
      int y = e.getY()-leftY;//点击位置y-偏移量y
      int i = y/50;//对应数组行数,根据像素坐标转换成数组下标坐标
      int j = x/50;//对应数组列数
      if(x<0||y<0)//超出地图范围
         return ;



      if(isClick){//第二次点击

         if(map[i][j]!=BLANK_STATE){
            if(map[i][j]==clickId){//点击的是相同图片Id,但不是重复点击同一图片
               if(i==clickX&&j==clickY)
                  return ;

               if(verticalLink(clickX,clickY,i,j)||horizontalLink(clickX,clickY,i,j)||oneCornerLink(clickX,clickY,i,j)||twoCornerLink(clickX,clickY,i,j)){//如果可以连通,画线连接,然后消去选中图片并重置第一次选中标识
                  drawSelectedBlock(j*50+leftX,i*50+leftY,g);
                  drawLink(clickX,clickY,i,j);//画线连接
                  isClick = false;

               }else{
                  clickId = map[i][j];//重新选中图片并画框
                  clearSelectBlock(clickX,clickY,g);
                  clickX = i;
                  clickY = j;
                  drawSelectedBlock(j*50+leftX,i*50+leftY,g);
               }

            }else{
               clickId = map[i][j];//重新选中图片并画框
               clearSelectBlock(clickX,clickY,g);
               clickX = i;
               clickY = j;
               drawSelectedBlock(j*50+leftX,i*50+leftY,g);
            }

         }

      }else{//第一次点击
         if(map[i][j]!=BLANK_STATE){
            //选中图片并画框
            clickId = map[i][j];
            isClick = true;
            clickX = i;
            clickY = j;
            drawSelectedBlock(j*50+leftX,i*50+leftY,g);
         }
      }
   }



   @Override
   public void mouseClicked(MouseEvent e) {
      // TODO Auto-generated method stub

   }


   @Override
   public void mouseReleased(MouseEvent e) {
      // TODO Auto-generated method stub
   }

   @Override
   public void mouseEntered(MouseEvent e) {
      // TODO Auto-generated method stub

   }

   @Override
   public void mouseExited(MouseEvent e) {
      // TODO Auto-generated method stub

   }

   @Override
   public void actionPerformed(ActionEvent e) {
      // TODO Auto-generated method stub

   }

   @Override
   public void keyTyped(KeyEvent e) {
      // TODO Auto-generated method stub

   }


   @Override
   public void keyReleased(KeyEvent e) {
      // TODO Auto-generated method stub

   }

}

此篇文章仅为部分代码!

完整素材及全部代码

代码已上传csdn,0积分下载,觉得这片博文有用请留下你的点赞。

基于JAVA实现的连连看小游戏
 

  • 41
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蜜蜂vs码农

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值