本文实例为大家分享了java实现2048游戏源代码,供大家参考,具体内容如下
一.主要功能:
1、游戏初始化:新建游戏4×4的16宫格画布,随机格子上生成2或者4两个数字
2、格子的移动:先判断能否移动,移动后判断能否合并,合并后改变格子颜色和数字
3、新格子的生成:移动一次,就在剩余的空格子中随机生成一个2或者4
4、判赢:16宫格中合并出了“2048”则为游戏胜利
5、判输:16宫格中没有剩余空格子且不能再向任何方向移动则为游戏失败
二.项目的主要结构:
在项目2018游戏中,有4个源文件,此外,还有3个.png和两个.wav格式的音乐文件。一个音乐是按键移动的声音,另外一个是碰撞后的消除的声音。然后游戏的最高分保存是在Recording源文件中,之后附上所需的图片文件和音乐文件:
来了来了.
三.代码
1、Game.java
package shixun; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; public class Game extends JFrame { private static final long serialVersionUID = 1L; public static void main(String[] args) { Game UI = new Game(); UI.IntUI(); } // 用于存放数据的数组,构成游戏4*4界面的数值 private int Numbers[][] = new int[4][4] ; private void IntUI() { this.setTitle("2048小游戏"); this.setLocation(450, 100); this.setSize(400, 500); this.setLayout(null); // 开始游戏按钮 ImageIcon imgicon = new ImageIcon("res/start.png"); JButton bt = new JButton(imgicon); bt.setFocusable(false); bt.setBorderPainted(false); bt.setFocusPainted(false); bt.setContentAreaFilled(false); bt.setBounds(5, 10, 120, 30);// 设置按钮的x,y坐标位置和宽度与高度 this.add(bt); //后退一步按钮 ImageIcon backicon = new ImageIcon("res/backicon.png"); JButton back = new JButton(backicon); back.setFocusable(false); back.setBorderPainted(false); back.setFocusPainted(false); back.setContentAreaFilled(false); back.setBounds(270, 10, 120, 30);// 设置按钮的x,y坐标位置和宽度与高度 this.add(back); // 关于按钮 ImageIcon imgicon2 = new ImageIcon("res/about.png"); JButton about = new JButton(imgicon2); about.setFocusable(false); about.setBorderPainted(false); about.setFocusPainted(false); about.setContentAreaFilled(false); about.setBounds(160, 10, 70, 30); this.add(about); // 分数显示 JLabel lb = new JLabel("分数:0"); lb.setBounds(40, 45, 120, 30); lb.setFont(new Font("幼圆", Font.CENTER_BASELINE, 18)); lb.setForeground(new Color(0x000000)); this.add(lb); //最高分数 Recorder.getRecording(); int maxscore = Recorder.getMaxscore_2048(); JLabel M=new JLabel("最高分:0"); M.setBounds(150,45,120,30); M.setFont(new Font("幼圆", Font.CENTER_BASELINE, 18)); M.setForeground(new Color(0x000000)); this.add(M); //静音 JCheckBox isSoundBox=new JCheckBox("静音"); isSoundBox.setBounds(290, 45, 120, 30); isSoundBox.setFont(new Font("幼圆", Font.CENTER_BASELINE, 18)); isSoundBox.setFocusable(false); isSoundBox.setBorderPainted(false); isSoundBox.setFocusPainted(false); isSoundBox.setContentAreaFilled(false); this.add(isSoundBox); this.setDefaultCloseOperation(3); this.setResizable(false); this.setVisible(true);// 显示界面 // 创建事件处理类 MyListener cl = new MyListener(this,Numbers,lb,M, bt, about,back,isSoundBox); bt.addActionListener(cl); about.addActionListener(cl); back.addActionListener(cl); isSoundBox.addActionListener(cl); this.addKeyListener(cl); } // 重写窗体 @Override public void paint(Graphics g) { super.paint(g); g.setColor(new Color(0xBBADA0)); g.fillRoundRect(15, 110, 370, 370, 15, 15);// 大矩形框 g.setColor(new Color(0xCDC1B4)); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 15, 15);// 小矩形框 } } // 调整数字的位置并上色 for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (Numbers[j][i] != 0) { int FontSize = 30; int MoveX = 0, MoveY = 0; switch (Numbers[j][i]) { case 2: g.setColor(new Color(0xeee4da)); FontSize = 30; MoveX = 0; MoveY = 0; break; case 4: g.setColor(new Color(0xede0c8)); FontSize = 30; MoveX = 0; MoveY = 0; break; case 8: g.setColor(new Color(0xf2b179)); FontSize = 30; MoveX = 0; MoveY = 0; break; case 16: g.setColor(new Color(0xf59563)); FontSize = 29; MoveX = -5; MoveY = 0; break; case 32: g.setColor(new Color(0xf67c5f)); FontSize = 29; MoveX = -5; MoveY = 0; break; case 64: g.setColor(new Color(0xf65e3b)); FontSize = 29; MoveX = -5; MoveY = 0; break; case 128: g.setColor(new Color(0xedcf72)); FontSize = 28; MoveX = -10; MoveY = 0; break; case 256: g.setColor(new Color(0xedcc61)); FontSize = 28; MoveX = -10; MoveY = 0; break; case 512: g.setColor(new Color(0xedc850)); FontSize = 28; MoveX = -10; MoveY = 0; break; case 1024: g.setColor(new Color(0xedc53f)); FontSize = 27; MoveX = -15; MoveY = 0; break; case 2048: g.setColor(new Color(0xedc22e)); FontSize = 27; MoveX = -15; MoveY = 0; break; default: g.setColor(new Color(0x000000)); break; } g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 15, 15);// 小矩形框上色 g.setColor(new Color(0x000000)); g.setFont(new Font("Kristen ITC", Font.PLAIN, FontSize)); g.drawString(Numbers[j][i] + "", 25 + i * 90 + 30 + MoveX, 120 + j * 90 + 50 + MoveY); } } } } }
2、MyListener.java
package shixun; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.Arrays; import java.util.Random; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JOptionPane; public class MyListener extends KeyAdapter implements ActionListener { /** * KevinWu */ private Game UI;// 界面对象 private int Numbers[][];// 存放数据的数组 private Random rand = new Random(); private int BackUp[][]= new int[4][4];//用于备份数组,供回退时使用 private int BackUp2[][]= new int[4][4];//用于备份数组,供起死回生时使用 public JLabel lb; public JLabel M; int score = 0; int maxscore=Recorder.getMaxscore_2048(); int tempscore,tempscore2;//记录回退isWin的分数值 public JButton bt,about,back; public JCheckBox isSoundBox; private boolean isWin=false,relive=false,hasBack=false,isSound=true; public MyListener(Game UI, int Numbers[][], JLabel lb,JLabel M ,JButton bt,JButton about,JButton back,JCheckBox isSoundBox) { this.UI = UI; this.Numbers = Numbers; this.lb = lb; this.bt=bt; this.about=about; this.back=back; this.isSoundBox=isSoundBox; this.M=M; } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub if(e.getSource() ==bt ){ isWin=false; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) Numbers[i][j] = 0; score = 0;// 保证每次重置游戏都是0分开始 lb.setText("分数:" + score); M.setText("最高分:"+maxscore); int r1 = rand.nextInt(4); int r2 = rand.nextInt(4); int c1 = rand.nextInt(4); int c2 = rand.nextInt(4); while (r1 == r2 && c1 == c2) { r2 = rand.nextInt(4); c2 = rand.nextInt(4); } // 生成数字(2或者4) int value1 = rand.nextInt(2) * 2 + 2; int value2 = rand.nextInt(2) * 2 + 2; // 把数字存进对应的位置 Numbers[r1][c1] = value1; Numbers[r2][c2] = value2; UI.paint(UI.getGraphics()); } else if(e.getSource()==about){ JOptionPane.showMessageDialog(UI, "游戏规则:\n" + "开始时棋盘内随机出现两个数字,出现的数字仅可能为2或4\n" + "玩家可以选择上下左右四个方向,若棋盘内的数字出现位移或合并,视为有效移动\n" + "玩家选择的方向上若有相同的数字则合并,每次有效移动可以同时合并,但不可以连续合并\n" + "合并所得的所有新生成数字想加即为该步的有效得分\n" + "玩家选择的方向行或列前方有空格则出现位移\n" + "每有效移动一步,棋盘的空位(无数字处)随机出现一个数字(依然可能为2或4)\n" + "棋盘被数字填满,无法进行有效移动,判负,游戏结束\n" + "棋盘上出现2048,判胜,游戏结束。\n" ); } else if(e.getSource()==back&&hasBack==false){ hasBack=true; if(relive==false){ score=tempscore; lb.setText("分数:" + score); for(int i=0;i<BackUp.length;i++){ Numbers[i]=Arrays.copyOf(BackUp[i], BackUp[i].length); } } else{ score=tempscore2; lb.setText("分数:" + score); for(int i=0;i<BackUp2.length;i++){ Numbers[i]=Arrays.copyOf(BackUp2[i], BackUp2[i].length); } relive=false; } UI.paint(UI.getGraphics()); } else if(e.getSource().equals(isSoundBox)){ if (isSoundBox.isSelected()) isSound=false; else isSound=true; } } // 键盘监听 public void keyPressed(KeyEvent event) { int Counter = 0;// 计算器,判断是否移动了 int NumCounter = 0;// 用于统计整个大方框中数字的个数,判断是否已满 int NumNearCounter = 0;// 用于统计相邻格子数字相同的个数 /* * 方向键键值:左:37上:38右:39下:40 */ hasBack = false; if (BackUp != null || BackUp.length != 0) { tempscore2 = tempscore;// 先把分数备份好 // 下面的for循环调用java.util.Arrays.copyOf()方法复制数组,实现备份 for (int i = 0; i < BackUp.length; i++) { BackUp2[i] = Arrays.copyOf(BackUp[i], BackUp[i].length); } } tempscore = score;// 先把分数备份好 // 下面的for循环调用java.util.Arrays.copyOf()方法复制数组,实现备份 for (int i = 0; i < Numbers.length; i++) { BackUp[i] = Arrays.copyOf(Numbers[i], Numbers[i].length); } if (isWin == false) { switch (event.getKeyCode()) { case 37: // 向左移动 if (isSound == true) new PlaySound("move.wav").start(); for (int h = 0; h < 4; h++) for (int l = 0; l < 4; l++) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = l - 1; while (pre >= 0 && Numbers[h][pre] == 0) { Numbers[h][pre] = temp; Numbers[h][pre + 1] = 0; pre--; Counter++; } } for (int h = 0; h < 4; h++) for (int l = 0; l < 4; l++) if (l + 1 < 4 && (Numbers[h][l] == Numbers[h][l + 1]) && (Numbers[h][l] != 0 || Numbers[h][l + 1] != 0)) { if (isSound == true) new PlaySound("merge.wav").start(); Numbers[h][l] = Numbers[h][l] + Numbers[h][l + 1]; Numbers[h][l + 1] = 0; Counter++; score += Numbers[h][l]; if (Numbers[h][l] == 2048) { isWin = true; } } for (int h = 0; h < 4; h++) for (int l = 0; l < 4; l++) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = l - 1; while (pre >= 0 && Numbers[h][pre] == 0) { Numbers[h][pre] = temp; Numbers[h][pre + 1] = 0; pre--; Counter++; } } break; case 39:// 向右移动 if (isSound == true) new PlaySound("move.wav").start(); for (int h = 3; h >= 0; h--) for (int l = 3; l >= 0; l--) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = l + 1; while (pre <= 3 && Numbers[h][pre] == 0) { Numbers[h][pre] = temp; Numbers[h][pre - 1] = 0; pre++; Counter++; } } for (int h = 3; h >= 0; h--) for (int l = 3; l >= 0; l--) if (l + 1 < 4 && (Numbers[h][l] == Numbers[h][l + 1]) && (Numbers[h][l] != 0 || Numbers[h][l + 1] != 0)) { if (isSound == true) new PlaySound("merge.wav").start(); Numbers[h][l + 1] = Numbers[h][l] + Numbers[h][l + 1]; Numbers[h][l] = 0; Counter++; score += Numbers[h][l + 1]; if (Numbers[h][l + 1] == 2048) { isWin = true; } } for (int h = 3; h >= 0; h--) for (int l = 3; l >= 0; l--) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = l + 1; while (pre <= 3 && Numbers[h][pre] == 0) { Numbers[h][pre] = temp; Numbers[h][pre - 1] = 0; pre++; Counter++; } } break; case 38: //向上移动 if (isSound == true) new PlaySound("move.wav").start(); for (int l = 0; l < 4; l++) for (int h = 0; h < 4; h++) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = h - 1; while (pre >= 0 && Numbers[pre][l] == 0) { Numbers[pre][l] = temp; Numbers[pre + 1][l] = 0; pre--; Counter++; } } for (int l = 0; l < 4; l++) for (int h = 0; h < 4; h++) if (h + 1 < 4 && (Numbers[h][l] == Numbers[h + 1][l]) && (Numbers[h][l] != 0 || Numbers[h + 1][l] != 0)) { if (isSound == true) new PlaySound("merge.wav").start(); Numbers[h][l] = Numbers[h][l] + Numbers[h + 1][l]; Numbers[h + 1][l] = 0; Counter++; score += Numbers[h][l]; if (Numbers[h][l] == 2048) { isWin = true; } } for (int l = 0; l < 4; l++) for (int h = 0; h < 4; h++) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = h - 1; while (pre >= 0 && Numbers[pre][l] == 0) { Numbers[pre][l] = temp; Numbers[pre + 1][l] = 0; pre--; Counter++; } } break; case 40: // 向下移动 if (isSound == true) new PlaySound("move.wav").start(); for (int l = 3; l >= 0; l--) for (int h = 3; h >= 0; h--) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = h + 1; while (pre <= 3 && Numbers[pre][l] == 0) { Numbers[pre][l] = temp; Numbers[pre - 1][l] = 0; pre++; Counter++; } } for (int l = 3; l >= 0; l--) for (int h = 3; h >= 0; h--) if (h + 1 < 4 && (Numbers[h][l] == Numbers[h + 1][l]) && (Numbers[h][l] != 0 || Numbers[h + 1][l] != 0)) { if (isSound == true) new PlaySound("merge.wav").start(); Numbers[h + 1][l] = Numbers[h][l] + Numbers[h + 1][l]; Numbers[h][l] = 0; Counter++; score += Numbers[h + 1][l]; if (Numbers[h + 1][l] == 2048) { isWin = true; } } for (int l = 0; l < 4; l++) for (int h = 0; h < 4; h++) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = h - 1; while (pre >= 0 && Numbers[pre][l] == 0) { Numbers[pre][l] = temp; Numbers[pre + 1][l] = 0; pre--; Counter++; } } break; case 40: // 向下移动 if (isSound == true) new PlaySound("move.wav").start(); for (int l = 3; l >= 0; l--) for (int h = 3; h >= 0; h--) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = h + 1; while (pre <= 3 && Numbers[pre][l] == 0) { Numbers[pre][l] = temp; Numbers[pre - 1][l] = 0; pre++; Counter++; } } for (int l = 3; l >= 0; l--) for (int h = 3; h >= 0; h--) if (h + 1 < 4 && (Numbers[h][l] == Numbers[h + 1][l]) && (Numbers[h][l] != 0 || Numbers[h + 1][l] != 0)) { if (isSound == true) new PlaySound("merge.wav").start(); Numbers[h + 1][l] = Numbers[h][l] + Numbers[h + 1][l]; Numbers[h][l] = 0; Counter++; score += Numbers[h + 1][l]; if (Numbers[h + 1][l] == 2048) { isWin = true; } } for (int l = 3; l >= 0; l--) for (int h = 3; h >= 0; h--) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = h + 1; while (pre <= 3 && Numbers[pre][l] == 0) { Numbers[pre][l] = temp; Numbers[pre - 1][l] = 0; pre++; Counter++; } } break; default:break; } if(maxscore<=score) { maxscore=score; Recorder.setMaxscore(maxscore); Recorder.keepRecording(); } for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (Numbers[i][j] == Numbers[i][j + 1] && Numbers[i][j] != 0) { NumNearCounter++; } if (Numbers[i][j] == Numbers[i + 1][j] && Numbers[i][j] != 0) { NumNearCounter++; } if (Numbers[3][j] == Numbers[3][j + 1] && Numbers[3][j] != 0) { NumNearCounter++; } if (Numbers[i][3] == Numbers[i + 1][3] && Numbers[i][3] != 0) { NumNearCounter++; } } } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (Numbers[i][j] != 0) { NumCounter++; } } } if (Counter > 0) { lb.setText("分数:" + score); M.setText("最高分:"+maxscore); int r1 = rand.nextInt(4); int c1 = rand.nextInt(4); while (Numbers[r1][c1] != 0) { r1 = rand.nextInt(4); c1 = rand.nextInt(4); } int value1 = rand.nextInt(2) * 2 + 2; Numbers[r1][c1] = value1; } if (isWin == true){ UI.paint(UI.getGraphics()); JOptionPane.showMessageDialog(UI, "恭喜你赢了!\n您的最终得分为:" + score); } if (NumCounter == 16 && NumNearCounter == 0) { relive = true; JOptionPane.showMessageDialog(UI, "没地方可以合并咯!!" + "\n很遗憾,您输了~>_<~" + "\n悄悄告诉你,游戏有起死回生功能哦,不信你“退一步”试试?" + "\n说不定能扭转乾坤捏 (^_~)"); } UI.paint(UI.getGraphics()); } } }
3、PlaySound.java
package shixun; import java.io.File; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.SourceDataLine; //播放声音的线程 public class PlaySound extends Thread { private String filename; public PlaySound(String wavfile) { filename = "res/" + wavfile; } public void run() { File soundFile = new File(filename); AudioInputStream audioInputStream = null; try { audioInputStream = AudioSystem.getAudioInputStream(soundFile); } catch (Exception e1) { e1.printStackTrace(); return; } AudioFormat format = audioInputStream.getFormat(); SourceDataLine auline = null; DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); try { auline = (SourceDataLine) AudioSystem.getLine(info); auline.open(format); } catch (Exception e) { e.printStackTrace(); return; } auline.start(); int nBytesRead = 0; // 这是缓冲 byte[] abData = new byte[512]; try { while (nBytesRead != -1) { nBytesRead = audioInputStream.read(abData, 0, abData.length); if (nBytesRead >= 0) auline.write(abData, 0, nBytesRead); } } catch (IOException e) { e.printStackTrace(); return; } finally { auline.drain(); auline.close(); } } }
4、Recorder.java
package shixun; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Recorder { private static int maxscore_2048=0; public static int getMaxscore_2048() { // TODO Auto-generated method stub return maxscore_2048; } public static void setMaxscore(int maxscore_2048) { // TODO Auto-generated method stub Recorder.maxscore_2048=maxscore_2048; } private static FileReader fr=null; private static BufferedReader br=null; private static FileWriter fw=null; private static BufferedWriter bw=null; //从文件中读取,记录 public static void getRecording() { boolean flag =false;//判断文件是否新建 try { File f=new File("src/myRecording.txt"); if(f.exists()) { fr=new FileReader(f); br=new BufferedReader(fr); String n=br.readLine(); maxscore_2048=Integer.parseInt(n); } else { flag=f.createNewFile(); } } catch(Exception e) { e.printStackTrace(); } finally { try { if(!flag) { br.close(); fr.close(); } }catch(Exception e2) { e2.printStackTrace(); } } } //保存最高分记录 public static void keepRecording() { try { File f=new File("src/myRecording.txt"); fw=new FileWriter(f); bw=new BufferedWriter(fw); bw.write(maxscore_2048+"\r\n"); }catch(IOException e) { e.printStackTrace(); } finally { try { bw.close(); fw.close(); } catch(IOException e) { e.printStackTrace(); } } } }
四.游戏截图
更多有趣的经典小游戏实现专题,分享给大家:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。
- 本文固定链接: https://zxbcw.cn/post/190571/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)