java实现的2048游戏完整实例

 更新时间:2018年01月03日 12:12:06   作者:cjc雪狼  
这篇文章主要介绍了java实现的2048游戏,结合完整实例形式分析了java实现2048游戏功能的相关数值运算、swing组件布局、事件响应等相关操作技巧,需要的朋友可以参考下

本文实例讲述了java实现的2048游戏。分享给大家供大家参考,具体如下:

先来看看运行效果:

具体代码如下:

package awtDemo;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
@SuppressWarnings("serial")
public class Game2048 extends JApplet{
  @SuppressWarnings("unused")
 private static final int UP=0,DOWN=1,LEFT=2,RIGHT=3;
  private static final int WID=150,SP=10;
  @SuppressWarnings("unused")
 private int scores=0;
  private static JLabel scoreLabel;
  private boolean change,CheckMode=false,gameOverFlag=false,successFlag=false;
  private int[] label={2,4,8,16,32,64,128};
  private Color[] clo={
      new Color(200,200,200),new Color(228,228,160),new Color(214,163,92),
      new Color(234,124,72),new Color(240,84,77),new Color(255,68,53),new Color(200,200,64)
  };
  @SuppressWarnings("rawtypes")
 private Map cmap=new HashMap();
  public static RectObject[][] rset=new RectObject[4][4];
  public RectObject[][] list=new RectObject[4][4];
  private My2048Panel myp;
  @SuppressWarnings("rawtypes")
 private LinkedList saveList=new LinkedList();
  private JButton goBackButton;
  KeyListener kl=new KeyListener(){
    public void keyPressed(KeyEvent e){
      saveTheStep();
      goBackButton.setVisible(true);
      if(gameOverFlag==true){
        return;
      }
      if(!aDirAble()){
        gameOver();
      }
      int key=e.getKeyCode();
      switch(key){
      case KeyEvent.VK_UP:
        change=false;
        moveUp(true);
        if(change==true){
          getARandomRect();
          //saveTheStep();
        }
        break;
      case KeyEvent.VK_DOWN:
        change=false;
        moveDown(true);
        if(change==true){
          getARandomRect();
          //saveTheStep();
        }
        break;
      case KeyEvent.VK_LEFT:
        change=false;
        moveLeft(true);
        if(change==true){
          getARandomRect();
          //saveTheStep();
        }
        break;
      case KeyEvent.VK_RIGHT:
        change=false;
        moveRight(true);
        if(change==true){
          getARandomRect();
          //saveTheStep();
        }
        break;
      }
      //saveTheStep();
    }
    public void keyTyped(KeyEvent e){}
    public void keyReleased(KeyEvent e){}
  };
  class RectObject{
    private int value;
    public RectObject(){
      value=0;
    }
    public RectObject(RectObject obj){
      value=obj.value;
    }
    public boolean equals(Object inobj){
      RectObject obj=(RectObject)inobj;
      if(obj.value==value){
        return true;
      }
      return false;
    }
  }
  class Point{
    int x;
    int y;
    public Point(int i,int j){
      x=i;
      y=j;
    }
  }
  class My2048Panel extends JPanel{
    private int[] xindex={SP,2*SP+WID,3*SP+2*WID,4*SP+3*WID};
    private int[] yindex={SP,2*SP+WID,3*SP+2*WID,4*SP+3*WID};
    @SuppressWarnings("deprecation")
 public void paintComponent(Graphics g){
      //background
      super.paintComponent(g);
      for(int i=0;i<xindex.length;i++){
        for(int j=0;j<yindex.length;j++){
          g.setColor(Color.WHITE);
          g.drawRoundRect(xindex[i], yindex[j], WID, WID, WID/5, WID/5);
          g.setColor(new Color(197,183,129));
          g.fillRoundRect(xindex[i], yindex[j], WID, WID, WID/5, WID/5);
        }
      }
      //paint rectangle
      for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
          if(rset[i][j]!=null){
            g.setColor(Color.WHITE);
            g.drawRoundRect(yindex[j], xindex[i], WID, WID, WID/5, WID/5);
            if(rset[i][j].value<128){
              g.setColor((Color)cmap.get(rset[i][j].value));
            }else{
              g.setColor((Color)cmap.get(128));
            }
            g.fillRoundRect(yindex[j], xindex[i], WID, WID, WID/5, WID/5);
            g.setColor(Color.BLACK);
            Font font=new Font("TimesRoman",Font.BOLD,50);
            g.setFont(font);
            FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
            int len=fm.stringWidth(""+rset[i][j].value);
            int hg=fm.getHeight();
            g.drawString(""+rset[i][j].value, yindex[j]+WID/2-len/2, xindex[i]+WID/2+hg/4);
            if(rset[i][j].value==2048 && successFlag==false){
              successFlag=true;
              gameSuccess();
            }
          }
        }
      }
    }
  }
  class GameOverPane extends JPanel{
    public GameOverPane(int w,int h){
      setSize(w,h);
      //setOpaque(false);
    }
    @SuppressWarnings("deprecation")
 public void paintComponent(Graphics g){
      super.paintComponent(g);
      Font font=new Font("TimesRoman",Font.BOLD,80);
      g.setFont(font);
      FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
      int width=fm.stringWidth("Game Over");
      int height=fm.getHeight();
      g.setColor(new Color(255,0,0));
      g.drawString("Game Over!", getWidth()/2-width/2, getHeight()/2-height/2);
    }
  }
  class SuccessPane extends JPanel{
    public SuccessPane(int w,int h){
      setSize(w,h);
      //setOpaque(false);
    }
    public void paintComponent(Graphics g){
      super.paintComponent(g);
      Font font=new Font("TimesRoman",Font.BOLD,80);
      g.setFont(font);
      @SuppressWarnings("deprecation")
  FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
      int width=fm.stringWidth("Success!");
      int height=fm.getHeight();
      g.setColor(new Color(255,0,0));
      g.drawString("Success!", getWidth()/2-width/2, getHeight()/2-height/2);
    }
  }
  class LOGO extends JPanel{
    public LOGO(int w ,int h){
      setSize(w,h);
    }
    @SuppressWarnings("unused")
 public void paintComponent(Graphics g){
      super.paintComponent(g);
      Font font=new Font("TimesRoman",Font.BOLD,60);
      g.setFont(font);
      @SuppressWarnings("deprecation")
  FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
      int width=fm.stringWidth("2048");
      int height=fm.getHeight();
      g.setColor(new Color(255,0,0));
      g.drawString("2048", 20, getHeight()/2+20);
    }
  }
  public class goBackListener implements ActionListener{
    @SuppressWarnings("rawtypes")
 public void actionPerformed(ActionEvent e){
      if(saveList.size()==0){
        goBackButton.setVisible(false);
        return;
      }
      ArrayList arr=(ArrayList)saveList.getLast();
      scoreLabel.setText(""+arr.get(0));
      for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
          int num=(int)arr.get(4*i+j+1);
          if(num!=0){
            rset[i][j]=new RectObject();
            rset[i][j].value=num;
          }else{
            rset[i][j]=null;
          }
        }
      }
      saveList.removeLast();
      repaint();
    }
  }
  public class resetListener implements ActionListener{
    public void actionPerformed(ActionEvent e){
      refreshBest();
      for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
          rset[i][j]=null;
        }
      }
      scoreLabel.setText("0");
      repaint();
      getARandomRect();
      getARandomRect();
    }
  }
  //the applet init
  public void init(){
    Container cp=getContentPane();
    cp.setLayout(null);
    cp.setFocusable(true);
    cp.addKeyListener(kl);
    Font font=new Font("TimesNewman",Font.BOLD,30);
    JLabel sl=new JLabel();
    sl.setLayout(new GridLayout(2,1));
    JLabel sllb=new JLabel("Scores");
    sllb.setFont(font);
    scoreLabel=new JLabel("0");
    scoreLabel.setFont(font);
    sl.add(sllb);
    sl.add(scoreLabel);
    int best=0;
    try{
      File file=new File("BestRecord");
      if(file.exists()){
        RandomAccessFile f=new RandomAccessFile(file,"rw");
        best=f.readInt();
        f.close();
      }
    }catch(FileNotFoundException e){
      best=0;
      e.printStackTrace();
    }catch(IOException e){
      best=0;
      e.printStackTrace();
    }
    JLabel bsl=new JLabel();
    bsl.setLayout(new GridLayout(2,1));
    JLabel jl=new JLabel("Best");
    jl.setFont(font);
    JLabel jl1=new JLabel(""+best);
    jl1.setFont(font);
    bsl.add(jl);
    bsl.add(jl1);
    myp=new My2048Panel();
    LOGO logo=new LOGO(0,0);
    goBackButton=new JButton("UNDO");
    goBackButton.setFont(font);
    goBackButton.addActionListener(new goBackListener());
    goBackButton.addKeyListener(kl);
    JButton jb=new JButton("RESET");
    jb.setFont(font);
    jb.addActionListener(new resetListener());
    jb.addKeyListener(kl);
    sl.setBounds(500,20,200,80);
    bsl.setBounds(300,20,200,80);
    logo.setBounds(0, 0, 600, 100);
    myp.setBounds(0,90,700,700);
    goBackButton.setBounds(700,250,150,60);
    jb.setBounds(700,450,150,60);
    cp.add(sl);
    cp.add(bsl);
    cp.add(logo);
    cp.add(myp);
    cp.add(goBackButton);
    cp.add(jb);
    File f=new File("LASTRECORD");
    if(f.exists()){
      try{
        RandomAccessFile file=new RandomAccessFile(f,"rw");
        int num=file.readInt();
        scoreLabel.setText(""+num);
        for(int i=0;i<4;i++){
          for(int j=0;j<4;j++){
            num=file.readInt();
            if(num!=0){
              rset[i][j]=new RectObject();
              rset[i][j].value=num;
            }
          }
        }
        file.close();
      }catch(FileNotFoundException e){
        e.printStackTrace();
      }catch(IOException e){
        e.printStackTrace();
      }
    }else{
      getARandomRect();
      getARandomRect();
    }
  }
  @SuppressWarnings("unchecked")
 public Game2048(){
    //saveTheStep();
    for(int i=0;i<7;i++){
      cmap.put(label[i], clo[i]);
    }
  }
  //moveLeft
  public void moveLeft(boolean flag){
    clearList(list);
    for(int i=0;i<4;i++){
      int k=0;
      for(int j=0;j<4;j++){
        if(rset[i][j]!=null){
          list[i][k++]=new RectObject(rset[i][j]);
        }
      }
    }
    for(int i=0;i<4 && flag;i++){
      for(int j=0;j<3;j++){
        if(list[i][j]!=null && list[i][j+1]!=null && list[i][j].value==list[i][j+1].value){
          list[i][j].value*=2;
          if(CheckMode==false){
            int sum=Integer.parseInt(scoreLabel.getText());
            sum+=list[i][j].value;
            scoreLabel.setText(""+sum);
          }
          list[i][j+1]=null;
          j++;
        }
      }
    }
    if(isChange()){
      if(CheckMode==false){
        copySet(rset,list);
        repaint();
        moveLeft(false);
      }
      change=true;
    }else{
      repaint();
    }
  }
  //moveRight
  public void moveRight(boolean flag){
    clearList(list);
    for(int i=0;i<4;i++){
      int k=3;
      for(int j=3;j>-1;j--){
        if(rset[i][j]!=null){
          list[i][k--]=new RectObject(rset[i][j]);
        }
      }
    }
    for(int i=0;i<4 && flag;i++){
      for(int j=3;j>0;j--){
        if(list[i][j]!=null && list[i][j-1]!=null && list[i][j].value==list[i][j-1].value){
          list[i][j].value*=2;
          if(CheckMode==false){
            int sum=Integer.parseInt(scoreLabel.getText());
            sum+=list[i][j].value;
            scoreLabel.setText(""+sum);
          }
          list[i][j-1]=null;
          j--;
        }
      }
    }
    if(isChange()){
      if(CheckMode==false){
        copySet(rset,list);
        repaint();
        moveRight(false);
      }
      change=true;
    }else{
      repaint();
    }
  }
  //moveup
  public void moveUp(boolean flag){
    clearList(list);
    for(int j=0;j<4;j++){
      int k=0;
      for(int i=0;i<4;i++){
        if(rset[i][j]!=null){
          list[k++][j]=new RectObject(rset[i][j]);
        }
      }
    }
    for(int j=0;j<4 && flag;j++){
      for(int i=0;i<3;i++){
        if(list[i][j]!=null && list[i+1][j]!=null && list[i][j].value==list[i+1][j].value){
          list[i][j].value*=2;
          if(CheckMode==false){
            int sum=Integer.parseInt(scoreLabel.getText());
            sum+=list[i][j].value;
            scoreLabel.setText(""+sum);
          }
          list[i+1][j]=null;
          i++;
        }
      }
    }
    if(isChange()){
      if(CheckMode==false){
        copySet(rset,list);
        repaint();
        moveUp(false);
      }
      change=true;
    }else{
      repaint();
    }
  }
  //movedown
  public void moveDown(boolean flag){
    clearList(list);
    for(int j=0;j<4;j++){
      int k=3;
      for(int i=3;i>-1;i--){
        if(rset[i][j]!=null){
          list[k--][j]=new RectObject(rset[i][j]);
        }
      }
    }
    for(int j=0;j<4 && flag;j++){
      for(int i=3;i>0;i--){
        if(list[i][j]!=null && list[i-1][j]!=null && list[i][j].value==list[i-1][j].value){
          list[i][j].value*=2;
          if(CheckMode==false){
            int sum=Integer.parseInt(scoreLabel.getText());
            sum+=list[i][j].value;
            scoreLabel.setText(""+sum);
          }
          list[i-1][j]=null;
          i--;
        }
      }
    }
    if(isChange()){
      if(CheckMode==false){
        copySet(rset,list);
        repaint();
        moveDown(false);
      }
      change=true;
    }else{
      repaint();
    }
  }
  //other functions
  private void copySet(RectObject[][] dst, RectObject[][] src){
    for(int i=0;i<4;i++){
      for(int j=0;j<4;j++){
        dst[i][j]=src[i][j];
      }
    }
  }
  //detect whether rset is different from list or not
  private boolean isChange(){
    for(int i=0;i<4;i++){
      for(int j=0;j<4;j++){
        if(rset[i][j]!=null && list[i][j]!=null && !rset[i][j].equals(list[i][j])){
          return true;
        }
        if(rset[i][j]!=null && list[i][j]==null){
          return true;
        }
        if(rset[i][j]==null && list[i][j]!=null){
          return true;
        }
      }
    }
    return false;
  }
  private void clearList(RectObject[][] s){
    for(int i=0;i<s.length;i++){
      for(int j=0;j<s[i].length;j++){
        s[i][j]=null;
      }
    }
  }
  //get a random rectangle
  @SuppressWarnings({ "unchecked", "rawtypes" })
 public void getARandomRect(){
    ArrayList list=new ArrayList();
    for(int i=0;i<4;i++){
      for(int j=0;j<4;j++){
        if(rset[i][j]==null){
          list.add(new Point(i,j));
        }
      }
    }
    if(list.size()==0 && !aDirAble()){
      gameOver();
      return;
    }
    Random rand=new Random();
    int index=rand.nextInt(list.size());
    Point loc=(Point)list.get(index);
    index=rand.nextInt(2);
    rset[loc.x][loc.y]=new RectObject();
    if(index==1){
      rset[loc.x][loc.y].value=4;
    }else{
      rset[loc.x][loc.y].value=2;
    }
  }
  //detect whether there are other steps or not
  public boolean aDirAble(){
    CheckMode=true;
    change=false;
    moveLeft(true);
    moveRight(true);
    moveDown(true);
    moveUp(true);
    CheckMode=false;
    if(change==true){
      return true;
    }else{
      return false;
    }
  }
  public void gameOver(){
    gameOverFlag=true;
    JPanel jl=new GameOverPane(myp.getWidth(),myp.getHeight());
    jl.setBounds(0, 0, 700, 700);
    JButton jb1=new JButton("Again");
    Font font=new Font("TimesRoman",Font.BOLD,30);
    jb1.setOpaque(false);
    jb1.setFont(font);
    JButton jb2=new JButton("Close");
    jb2.setSize(jb1.getSize());
    jb2.setOpaque(false);
    jb2.setFont(font);
    jb1.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        scoreLabel.setText("0");
        myp.remove(jl);
        clearList(rset);
        myp.validate();
        getARandomRect();
        getARandomRect();
        repaint();
        gameOverFlag=false;
        refreshBest();
      }
    });
    jb2.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        refreshBest();
        File f=new File("LASTRECORD");
        if(f.exists()){
          f.delete();
        }
        System.exit(0);
      }
    });
    jl.add(jb1);
    jl.add(jb2);
    myp.add(jl);
    jl.validate();
  }
  public void gameSuccess(){
    JPanel jl=new SuccessPane(myp.getWidth(),myp.getHeight());
    jl.setOpaque(false);
    jl.setBounds(0, 0, 700, 700);
    JButton jb1=new JButton("Continue");
    Font font=new Font("TimesRoman",Font.BOLD,30);
    jb1.setOpaque(false);
    jb1.setFont(font);
    JButton jb2=new JButton("Close");
    jb2.setSize(jb1.getSize());
    jb2.setOpaque(false);
    jb2.setFont(font);
    jb1.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        myp.remove(jl);
        myp.validate();
        repaint();
      }
    });
    jb2.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        refreshBest();
        System.exit(0);
      }
    });
    jl.add(jb1);
    jl.add(jb2);
    myp.add(jl);
    jl.validate();
  }
  @SuppressWarnings("unchecked")
 public void saveTheStep(){
    if(saveList.size()<20){
      @SuppressWarnings("rawtypes")
  ArrayList arr=new ArrayList();
      int score=Integer.parseInt(scoreLabel.getText());
      arr.add(score);
      for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
          if(rset[i][j]!=null){
            arr.add(rset[i][j].value);
          }else{
            arr.add(0);
          }
        }
      }
      saveList.addLast(arr);
    }else{
      saveList.removeFirst();
      saveTheStep();
    }
  }
  public static String title(Object o){
    String t=o.getClass().toString();
    if(t.indexOf("class")!=-1){
      t=t.substring(6);
    }
    return t;
  }
  public static void refreshBest(){
    try {
      int best=0;
      File f=new File("BestRecord");
      RandomAccessFile file;
      if(f.exists()){
        file=new RandomAccessFile(f,"rw");
        best=file.readInt();
        file.seek(0);
      }else{
        file=new RandomAccessFile(f,"rw");
      }
      //System.out.println("The Best score is "+best);
      int cur=Integer.parseInt(scoreLabel.getText());
      if(cur>best){
        file.writeInt(cur);
      }
      file.close();
    } catch (FileNotFoundException e1) {
      e1.printStackTrace();
    }catch(IOException e2){
      e2.printStackTrace();
    }
  }
  @SuppressWarnings("resource")
 public static void saveRecord(){
    try{
      RandomAccessFile file=new RandomAccessFile(new File("LASTRECORD"),"rw");
      int score=Integer.parseInt(scoreLabel.getText());
      file.writeInt(score);
      for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
          if(rset[i][j]!=null){
            file.writeInt(rset[i][j].value);
          }else{
            file.writeInt(0);
          }
        }
      }
    }catch(FileNotFoundException e){
      e.printStackTrace();
    }catch(IOException e){
      e.printStackTrace();
    }
  }
  public static void run(JApplet applet,int width,int height){
    JFrame frame=new JFrame(title(applet));
    frame.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
        refreshBest();
        saveRecord();
        //System.out.println("The score is "+scoreLabel.getText());
      }
    });
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(applet);
    frame.setSize(width,height);
    applet.init();
    applet.start();
    frame.setVisible(true);
  }
  public static void main(String[] args){
    run(new Game2048(), 900, 800);
  }
}

PS:这里再为大家推荐另两款本站2048游戏供大家参考(JS实现)

在线2048游戏:
http://tools.jb51.net/games/game2048

在线2048小游戏数字版:
http://tools.jb51.net/games/game2048num

更多关于java算法相关内容感兴趣的读者可查看本站专题:《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • 图解Spring容器中实例化bean的四种方式

    图解Spring容器中实例化bean的四种方式

    这篇文章主要介绍了图解Spring容器中实例化bean的四种方式,传统应用程序可以通过new和反射方式进行实例化Bean,而Spring IOC容器则需要根据 Bean 定义里的配置元数据,使用反射机制来创建Bean,需要的朋友可以参考下
    2023-11-11
  • 使用注解+RequestBodyAdvice实现http请求内容加解密方式

    使用注解+RequestBodyAdvice实现http请求内容加解密方式

    这篇文章主要介绍了使用注解+RequestBodyAdvice实现http请求内容加解密方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • JavaWeb开发中alias拦截器的使用方法

    JavaWeb开发中alias拦截器的使用方法

    本文给大家介绍在JavaWeb开发中alias拦截器的使用方法相关知识,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起看下吧
    2016-08-08
  • SharedingSphere 自定义脱敏规则介绍

    SharedingSphere 自定义脱敏规则介绍

    这篇文章主要介绍了SharedingSphere 自定义脱敏规则,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java定时器Timer与TimerTask的使用详解

    Java定时器Timer与TimerTask的使用详解

    这篇文章主要介绍了Java定时器Timer与TimerTask的使用详解,在JDK类库中Timer主要负责计划任务的功能,也就是在指定时间执行某一任务,执行时候会在主线程之外起一个单独的线程执行指定的任务,该类主要是设置任务计划,但封装的类是TimerTask类,需要的朋友可以参考下
    2023-10-10
  • 三种Spring BeanName生成器,你了解吗

    三种Spring BeanName生成器,你了解吗

    无论我们是通过 XML 文件,还是 Java 代码,亦或是包扫描的方式去注册 Bean,都可以不设置BeanName,而Spring均会为之提供默认的 beanName,本文我们就来看看 Spring 中三种处理不同情况的 beanName生成器吧
    2023-09-09
  • springboot处理url中带斜杠/\字符的参数报400问题

    springboot处理url中带斜杠/\字符的参数报400问题

    这篇文章主要介绍了springboot处理url中带斜杠/\字符的参数报400问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • java中实现控制台打印sql语句方式

    java中实现控制台打印sql语句方式

    这篇文章主要介绍了java中实现控制台打印sql语句方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • springboot restTemplate连接池整合方式

    springboot restTemplate连接池整合方式

    这篇文章主要介绍了springboot restTemplate连接池整合方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • Java访问权限原理与用法详解

    Java访问权限原理与用法详解

    这篇文章主要介绍了Java访问权限,结合实例形式详细分析了java构造者思想、包、访问修饰符等相关原理、应用与操作注意事项,需要的朋友可以参考下
    2020-02-02

最新评论