21xrx.com
2025-03-27 14:01:21 Thursday
文章检索 我的文章 写文章
JAVA小游戏编程:连连看源代码分享
2023-06-19 16:28:48 深夜i     124     0
Java 小游戏 连连看

近年来,由于智能手机、平板电脑等移动设备的普及,小游戏也越来越受到人们的追捧,如连连看、消消乐等休闲游戏成为了家喻户晓的游戏类型。本文将分享一种使用Java编写的连连看小游戏源代码,希望对Java编程初学者有所帮助。

一、游戏玩法简介

连连看是一种十分简单的游戏,玩家需要在规定的时间内点击相同的方块,使它们被连接起来并消除掉。当所有的方块都被消除完之后,游戏即为胜利。

二、连连看游戏源代码分享

连连看游戏是一种纯客户端的游戏,我们可以使用Java Swing框架进行界面的搭建,使用多线程技术实现倒计时和方块的运动,使用集合来存储方块的图片以及其他元素。以下是主要代码片段:

1.主函数代码:

public static void main(String[] args) {
 JFrame frame=new JFrame("连连看");
 frame.setSize(520, 630);
 frame.setLocationRelativeTo(null);
 frame.setResizable(false);
 JPanel panel=new JPanel();
 panel.setBorder(new EmptyBorder(5,5,5,5));
 frame.setContentPane(panel);
 panel.setLayout(new BorderLayout(0, 0));
 JButton btnNewButton = new JButton("开始");
 panel.add(btnNewButton, BorderLayout.SOUTH);
 LianLianKan game=new LianLianKan();
 panel.add(game, BorderLayout.CENTER);
 frame.setVisible(true);
 btnNewButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent arg0) {
   game.startGame();
  }
 });
}

2.游戏面板代码:

public class LianLianKan extends JPanel implements MouseListener{
 private BufferedImage backgroundImg;//背景图片
 private List
  blocks;//方块集合
 
 private boolean isStart=false;//标记游戏是否开始
 private boolean isError=false;//标记两个方块是否连接
 private Point startPoint;//标记选中的第一块方块的位置
 private Point endPoint;//标记选中的第二块方块的位置
 private Timer timer;//计时器对象
 private int timeCount;//计时器计数器
 private final int WIDTH=360;//游戏区宽度
 private final int HEIGHT=510;//游戏区高度
 private final int BLOCK_SIZE=45;//方块大小
 private final int MARGIN=20;//游戏区边缘宽度
 private final int LEVEL=20;//游戏难度等级
 //构造函数用于初始化游戏面板
 public LianLianKan(){
  initialize();
 }
 //初始化游戏面板
 private void initialize(){
  setPreferredSize(new Dimension(520, 630));
  backgroundImg=getImage("/background.png");
  addMouseListener(this);
  blocks=new ArrayList
  ();
 
  for(int i=0;i
   int type=i%10;
   Block block1=new Block(type, i*2, this);
   Block block2=new Block(type, i*2+1, this);
   blocks.add(block1);
   blocks.add(block2);
  }
 }
 //游戏面板重绘方法,负责绘制游戏界面
 @Override
 protected void paintComponent(Graphics g) {
  super.paintComponent(g);
  g.drawImage(backgroundImg, 0, 0, getWidth(), getHeight(), null);
  for (Block block : blocks) {
   block.draw(g);
  }
  if(isStart&&!isError&&startPoint!=null&&endPoint!=null){//选定了两个方块,且它们可连接
   g.setColor(Color.red);
   g.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
  }
  if(isStart){//游戏已开始,显示剩余时间
   g.setColor(Color.white);
   g.setFont(new Font("宋体", Font.BOLD, 20));
   g.drawString("剩余时间: "+(60-timeCount)+" 秒", MARGIN, HEIGHT+50);
  }
 }
 //鼠标事件方法,负责响应游戏界面的鼠标事件
 @Override
 public void mouseClicked(MouseEvent e) {
  if(!isStart)return;
  if(e.getX()
  
 
  int col=(int)((e.getX()-MARGIN)/BLOCK_SIZE);//根据鼠标点击的坐标计算出当前选中的方块所在的列数
  int row=(int)((e.getY()-MARGIN)/BLOCK_SIZE);//根据鼠标点击的坐标计算出当前选中的方块所在的行数
  for (Block block : blocks) {//遍历所有方块
   if(block.getCol()==col&&block.getRow()==row&&block.isAlive()){//如果找到了被选中的那个方块
    if(startPoint==null){//如果还没有选中任何方块
     startPoint=new Point(e.getX(), e.getY());//标记选中的第一块方块的位置
     block.setSelected(true);//将选中的方块设置为被选中状态
    }else if(endPoint==null){//如果已经选中了第一块方块,但还没有选中第二块方块
     endPoint=new Point(e.getX(), e.getY());//标记选中的第二块方块的位置
     if(block.getType()==blocks.get(getIndex(startPoint)).getType()){//如果选中的两个方块类型相同
      if(isLink(startPoint, endPoint)){//如果两个方块可以连接
       blocks.get(getIndex(startPoint)).setAlive(false);//将第一块方块设置为已消除状态
       blocks.get(getIndex(endPoint)).setAlive(false);//将第二块方块设置为已消除状态
       startPoint=null;//将第一块方块置空
       endPoint=null;//将第二块方块置空
       isError=false;//将标记两个方块是否连接的布尔值设为false
       if(isWin()){//如果所有方块都已被消除
        JOptionPane.showMessageDialog(null, "恭喜您,您已通关!", "提示", JOptionPane.INFORMATION_MESSAGE);//弹出通关提示框
        System.exit(0);//关闭游戏
       }
      }else{//如果两个方块不可以连接
       blocks.get(getIndex(startPoint)).setSelected(false);//将第一块方块的选中状态设为false
       startPoint=null;//将第一块方块置空
       endPoint=null;//将第二块方块置空
       isError=true;//将标记两个方块是否连接的布尔值设为true
      }
     }else{//如果选中的两个方块类型不同
      blocks.get(getIndex(startPoint)).setSelected(false);//将第一块方块的选中状态设为false
      startPoint=null;//将第一块方块置空
      endPoint=null;//将第二块方块置空
      isError=true;//将标记两个方块是否连接的布尔值设为true
     }
    }
    break;
   }
  }
  repaint();
 }
 //获取给定坐标所在的方块在集合中的索引
 public int getIndex(Point p){
  int col=(int)((p.getX()-MARGIN)/BLOCK_SIZE);//根据坐标计算出当前选中的方块所在的列数
  int row=(int)((p.getY()-MARGIN)/BLOCK_SIZE);//根据坐标计算出当前选中的方块所在的行数
  for (Block block : blocks) {//遍历所有方块
   if(block.getCol()==col&&block.getRow()==row&&block.isAlive()){//如果找到了被选中的那个方块
    return blocks.indexOf(block);//返回该方块在集合中的索引
   }
  }
  return -1;
 }
 //判断两个方块是否可以连接
 public boolean isLink(Point p1, Point p2){
  int x1=(int) p1.getX(), y1=(int) p1.getY();
  int x2=(int) p2.getX(), y2=(int) p2.getY();
  int row1=(y1-MARGIN)/BLOCK_SIZE, col1=(x1-MARGIN)/BLOCK_SIZE;
  int row2=(y2-MARGIN)/BLOCK_SIZE, col2=(x2-MARGIN)/BLOCK_SIZE;
  if(row1==row2){//两个方块在同一行
   for (int i = Math.min(col1, col2)+1; i < Math.max(col1, col2); i++) {//遍历两个方块之间的所有位置
    Block block1=blocks.get(getIndex(new Point(i*BLOCK_SIZE+MARGIN, row1*BLOCK_SIZE+MARGIN)));
    if(block1.isAlive())//如果两个方块之间有一个或多个方块未被消除
     return false;//则它们两个不能连接
    
   }
   return true;//两个方块之间没有阻挡,可以连接
  }else if(col1==col2){//两个方块在同一列
   for (int i = Math.min(row1, row2)+1; i < Math.max(row1, row2); i++) {//遍历两个方块之间的所有位置
    Block block1=blocks.get(getIndex(new Point(col1*BLOCK_SIZE+MARGIN, i*BLOCK_SIZE+MARGIN)));
    if(block1.isAlive())//如果两个方块之间有一个或多个方块未被消除
     return false;//则它们两个不能连接
    
   }
   return true;//两个方块之间没有阻挡,可以连接
  }else{return false;}//两个方块既不在同一行也不在同一列,不能连接
 }
 //判断游戏是否胜利
 public boolean isWin(){
  for (Block block : blocks) {//遍历所有方块
   if(block.isAlive())//如果存在未被消除的方块
    return false;//则游戏未胜利
   
  }
  return true;//如果所有方块都已被消除,则游戏胜利
 }
 //开始游戏方法
 public void startGame(){
  isStart=true;//将标记游戏是否开始的布尔值设为true
  timeCount=0;//将计时器计数器归零
  timer=new Timer(1000, new ActionListener() {//创建计时器对象
   public void actionPerformed(ActionEvent arg0) {
    timeCount++;//每秒钟将计数器自增1
    if(timeCount>=60){//如果已经超过60秒,即时间到
     JOptionPane.showMessageDialog(null, "时间到了,游戏结束!", "提示", JOptionPane.INFORMATION_MESSAGE);//弹出游戏结束提示框
     System.exit(0);//关闭游戏
    }
    repaint();//重绘游戏界面
   }
  });
  timer.start();//启动计时器
  Collections.shuffle(blocks);//打乱方块的顺序
  repaint();
 }
 //获取指定名称的图片
 public BufferedImage getImage(String fileName){
  try {
   URL url=this.getClass().getResource(fileName);
   return ImageIO.read(url);
  } catch (IOException e) {
   e.printStackTrace();
   return null;
  }
 }
}

3.方块类代码:

public class Block {
 private int type;//方块类型
 private boolean selected;//标记方块是否被选中
 private int row;//方块所在的行数
 private int col;//方块所在的列数
 private BufferedImage image;//方块图片
 private boolean alive=true;//标记方块是否还存活
 private LianLianKan game;//游戏面板对象
 //构造函数用于初始化方块
 public Block(int type, int index, LianLianKan game){
  this.type=type;
  this.game=game;
  row=index/game.LEVEL;
  col=index%game.LEVEL;
  image=game.getImage("/"+type+".png");
 }
 //画出方块
 public void draw(Graphics g){
  if(alive){
   g.drawImage(image, col*game.BLOCK_SIZE+game.MARGIN, row*game.BLOCK_SIZE+game.MARGIN, game.BLOCK_SIZE, game.BLOCK_SIZE, null);
   if(selected){
    g.setColor(Color.red);
    g.drawRect(col*game.BLOCK_SIZE+game.MARGIN+1, row*game.BLOCK_SIZE+game.MARGIN+1, game.BLOCK_SIZE-2, game.BLOCK_SIZE-2);
   }
  }
 }
 //判断方块是否被选中
 public boolean isSelected()
  return selected;
 
 //设置方块是否被选中
 public void setSelected(boolean selected)
  this.selected = selected;
 
 //获取方块所在的行数
 public int getRow()
  return row;
 
 //获取方块所在的列数
 public int getCol()
  return col;
 
 //获取方块的类型
 public int getType()
  return type;
 
 //设置方块是否存活
 public void setAlive(boolean alive)
  this.alive = alive;
 
 //判断方块是否存活
 public boolean isAlive()
  return alive;
 
}

三、关键词

Java、小游戏、连连看

  
  

评论区