21xrx.com
2024-12-23 02:17:22 Monday
登录
文章检索 我的文章 写文章
JAVA小游戏编程:连连看源代码分享
2023-06-19 16:28:48 深夜i     --     --
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、小游戏、连连看

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复