一个纯纯小白,想写点什么,也想学习一下怎么在这里写东西,就简单的写个2048小游戏。写的不好,大佬就不用看了,希望和大家交流学习,有写的不好或有更好的建议也欢迎提出来。(需要用的可直接粘贴复制)(轻喷)

目录

游戏展示

讲解

代码


游戏展示

基本上做到了和手机上一样。 我会按照我的思路为大家讲解一下,有需要的可以看看,想直接看效果或者需要用的,可以直接滑倒最后粘贴复制。


讲解

目录结构如下

按照我自己的思路讲一下,可能有点乱。

1.首先初始化一下画板,将不会改变的部分先完成。

private void initPaint(Graphics g) {//TODO 画方块所造区域g.setColor(new Color(192, 175, 159));g.fillRect(10, 120, 360 + 8, 360 + 8);//TODO 画得分区域以及说明区域g.setColor(new Color(209, 132, 102));g.fillRect(200, 15, 80, 50);g.fillRect(290, 15, 80, 50);g.setColor(Color.black);g.setFont(new Font("宋体", Font.BOLD, 20));g.drawString("得分", 220, 35);g.drawString("最高分", 300, 35);g.setFont(new Font("宋体", Font.BOLD, 35));g.drawString("游戏说明:", 15, 55);g.setFont(new Font("宋体", Font.BOLD, 20));g.drawString("按上下左右键控制;按空格键重新游戏", 15, 100);//画空白方块for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {paintBlock(g, new Block(table[i][j]), j, i);}}}

2.创建带有数字的方块,这里创建了一个block类,主要存储了,每种方块所显示的数字,数字颜色,背景颜色等属性。并且有一个setAllFont方法,来设置这些属性。

package game_2048;import java.awt.*;public class Block {int kind;Font wFont;Color wColor;Color bColor;String s;public Block(int kind) {this.kind = kind;}private final Font font1 = new Font("宋体", Font.BOLD, 46);private final Font font2 = new Font("宋体", Font.BOLD, 40);private final Font font3 = new Font("宋体", Font.BOLD, 34);private final Font font4 = new Font("宋体", Font.BOLD, 28);private final Color color1 = new Color(119,108,99);private final Color color2 = new Color(254,254,254);public void setAllFont() {switch (kind) {case 0 -> bColor = new Color(206, 194, 180);case 1 -> {wFont = font1;wColor = color1;bColor = new Color(237, 229, 218);s = 2 + "";}case 2 -> {wFont = font1;wColor = color1;bColor = new Color(237, 220, 190);s = 4 + "";}case 3 -> {wFont = font1;wColor = color1;bColor = new Color(242, 177, 123);s = 8 + "";}case 4 -> {wFont = font2;wColor = color2;bColor = new Color(246, 147, 92);s = 16 + "";}case 5 -> {wFont = font2;wColor = color2;bColor = new Color(245, 118, 86);s = 32 + "";}case 6 -> {wFont = font2;wColor = color2;bColor = new Color(245, 83, 45);s = 64 + "";}case 7 -> {wFont = font3;wColor = color2;bColor = new Color(237, 206, 115);s = 128 + "";}case 8 -> {wFont = font3;wColor = color2;bColor = new Color(230,209,81);s = 256 + "";}case 9 -> {wFont = font3;wColor = color2;bColor = new Color(207,163,12);s = 512 + "";}case 10 -> {wFont = font4;wColor = color2;bColor = new Color(229,180,6);s = 1024 + "";}case 11 -> {wFont = font4;wColor = color2;bColor = new Color(161,131,115);s = 2048 + "";}default -> {}}}}

3.绘制每个方块(这里在1里面已经用过了,当时是画空白的)

//画方块private void paintBlock(Graphics g, Block block, int x, int y) {block.setAllFont();g.setColor(block.bColor);g.fillRect(10 + x * 90 + 7, 120 + y * 90 + 7, 83, 83);if (block.kind > 0) {g.setColor(block.wColor);g.setFont(block.wFont);FontMetrics fm = getFontMetrics(block.wFont);String value = block.s;g.drawString(value,10 + x * 90 + 7 + (83 - fm.stringWidth(value)) / 2,120 + y * 90 + 7 + (83 - fm.getAscent() - fm.getDescent()) / 2 + fm.getAscent());}}

4.初始化界面,包括分数,和最开始显示的方块。

用random类来随机刷新方块存在的位置。

这里的getS()和后面的setS()分别是读、取文件,为了显示最高分用。(这两个方法写了不是很好,就不讲了)

private void init() {isOver = false;source = 0;try {best = getS();} catch (IOException e) {throw new RuntimeException(e);}for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {table[i][j] = 0;}}bX = rand1.nextInt(4);bY = rand2.nextInt(4);table[bX][bY] = 1;}

5. 控制所有方块的移动。

通过一系列控制语句,来决定是否能移动或者合并。我这里是为了做滑动的效果,可能写的有点啰嗦,反正能用就行吧。

private void bDown() {for (int j = 0; j <= 3; j++) {//第一个if是为了一种稍微特殊的地方//后面的每个方向都一样if (table[0][j] == table[1][j] && table[2][j] == table[3][j]&& table[0][j] != 0 && table[2][j] != 0) {table[1][j]++;table[0][j] = 0;}for (int i = 2; i >= 0; i--) {if (table[i + 1][j] == 0) {table[i + 1][j] = table[i][j];table[i][j] = 0;}if (table[i][j] != 0 && table[i][j] == table[i + 1][j]) {if (c[j]) {table[i + 1][j]++;table[i][j] = 0;c[j] = false;source += (int) Math.pow(2, table[i + 1][j]);}}}}}

6.我这里是用线程的方法,来实现滑动的效果。

每次按按键后,将改变fx的值,然后启动线程,每次会执行三次方块的移动,每次延迟40ms,依次来达到滑动的效果。

    @Overridepublic void run() {for (int i = 0; i < 4; i++) {c[i] = true;}int[][] tt = new int[4][4];for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {tt[i][j] = table[i][j];}}for (int k = 0; k < 3; k++) {switch (fx) {case 0 -> bUp();case 1 -> bRight();case 2 -> bDown();case 3 -> bLeft();default -> {}}try {Thread.sleep(40);} catch (InterruptedException e) {throw new RuntimeException(e);}if (best < source) {best = source;try {setS(source);} catch (IOException ioException) {ioException.printStackTrace();}}repaint();}isMove = false;loop:for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {if (tt[i][j] != table[i][j]) {isMove = true;break loop;}}}randomBlock();}

8.随机生成新的方块。 每次移动之后,就会随机产生新的方块,并且也在这里设置了结束的条件。

private void randomBlock() {v.clear();for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {if (table[i][j] == 0) {v.add(i);v.add(j);}}}if (v.size() > 0 && isMove) {int kk = rand.nextInt(v.size() / 2);table[v.get(kk * 2)][v.get(kk * 2 + 1)] = (rand.nextInt(7) % 6 == 0) ? 2 : 1;}if (v.size() == 0) {boolean isSame = false;loop1:for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {if ((table[i][j] == table[i + 1][j]) || (table[j][i] == table[j][i + 1])) {isSame = true;break loop1;}}}if (!isSame) {isOver = true;repaint();}}}

就这样吧,,,有啥问题也可以问,我也会回答。。。。。。


代码

best.txt

best.txt主要用来记录最高得分,创建时候需要在里面存储个0,不然读取的时候会报错。

MPanel

Panel类,主要的代码都在这个类里。

package game_2048;import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
import java.util.Vector;public class MPanel extends JPanel implements KeyListener, Runnable {int[][] table = new int[4][4];int fx; //上下左右0123Random rand1 = new Random();Random rand2 = new Random();Random rand = new Random();int bX;int bY;Vector<Integer> v = new Vector<>();boolean isMove;boolean[] c = new boolean[4];int source = 0;int best;boolean isOver;public MPanel() {setFocusable(true);setBackground(new Color(241, 228, 219));this.addKeyListener(this);init();}private void init() {isOver = false;source = 0;try {best = getS();} catch (IOException e) {throw new RuntimeException(e);}for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {table[i][j] = 0;}}bX = rand1.nextInt(4);bY = rand2.nextInt(4);table[bX][bY] = 1;}@Overridepublic void paint(Graphics g) {super.paint(g);initPaint(g);g.setColor(Color.white);g.setFont(new Font("宋体", Font.BOLD, 25));FontMetrics fm = getFontMetrics(new Font("宋体", Font.BOLD, 20));String value1 = source + "";g.drawString(value1,195 + (80 - fm.stringWidth(value1)) / 2,30 + (50 - fm.getAscent() - fm.getDescent()) / 2 + fm.getAscent());String value2 = best + "";g.drawString(value2,285 + (80 - fm.stringWidth(value2)) / 2,30 + (50 - fm.getAscent() - fm.getDescent()) / 2 + fm.getAscent());if (isOver) {g.setColor(new Color(0, 0, 0, 0.5f));g.fillRect(0, 0, getWidth(), getHeight());g.setFont(new Font("宋体", Font.BOLD, 60));fm = getFontMetrics(new Font("宋体", Font.BOLD, 60));String value = "游戏结束";g.drawString(value,(getWidth() - fm.stringWidth(value)) / 2,(getHeight() - fm.getAscent() - fm.getDescent()) / 2 + fm.getAscent());}}//初始化画板private void initPaint(Graphics g) {//TODO 画方块所造区域g.setColor(new Color(192, 175, 159));g.fillRect(10, 120, 360 + 8, 360 + 8);//TODO 画得分区域以及说明区域g.setColor(new Color(209, 132, 102));g.fillRect(200, 15, 80, 50);g.fillRect(290, 15, 80, 50);g.setColor(Color.black);g.setFont(new Font("宋体", Font.BOLD, 20));g.drawString("得分", 220, 35);g.drawString("最高分", 300, 35);g.setFont(new Font("宋体", Font.BOLD, 35));g.drawString("游戏说明:", 15, 55);g.setFont(new Font("宋体", Font.BOLD, 20));g.drawString("按上下左右键控制;按空格键重新游戏", 15, 100);for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {paintBlock(g, new Block(table[i][j]), j, i);}}}//画方块private void paintBlock(Graphics g, Block block, int x, int y) {block.setAllFont();g.setColor(block.bColor);g.fillRect(10 + x * 90 + 7, 120 + y * 90 + 7, 83, 83);if (block.kind > 0) {g.setColor(block.wColor);g.setFont(block.wFont);FontMetrics fm = getFontMetrics(block.wFont);String value = block.s;g.drawString(value,10 + x * 90 + 7 + (83 - fm.stringWidth(value)) / 2,120 + y * 90 + 7 + (83 - fm.getAscent() - fm.getDescent()) / 2 + fm.getAscent());}}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();if (!isOver) {Thread thread = new Thread(this);if (keyCode == KeyEvent.VK_DOWN) {fx = 2;thread.start();} else if (keyCode == KeyEvent.VK_UP) {fx = 0;thread.start();} else if (keyCode == KeyEvent.VK_RIGHT) {fx = 1;thread.start();} else if (keyCode == KeyEvent.VK_LEFT) {fx = 3;thread.start();}}if (keyCode == KeyEvent.VK_SPACE) {init();}repaint();}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void run() {for (int i = 0; i < 4; i++) {c[i] = true;}int[][] tt = new int[4][4];for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {tt[i][j] = table[i][j];}}for (int k = 0; k < 3; k++) {switch (fx) {case 0 -> bUp();case 1 -> bRight();case 2 -> bDown();case 3 -> bLeft();default -> {}}try {Thread.sleep(40);} catch (InterruptedException e) {throw new RuntimeException(e);}if (best < source) {best = source;try {setS(source);} catch (IOException ioException) {ioException.printStackTrace();}}repaint();}isMove = false;loop:for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {if (tt[i][j] != table[i][j]) {isMove = true;break loop;}}}randomBlock();}private void randomBlock() {v.clear();for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {if (table[i][j] == 0) {v.add(i);v.add(j);}}}if (v.size() > 0 && isMove) {int kk = rand.nextInt(v.size() / 2);table[v.get(kk * 2)][v.get(kk * 2 + 1)] = (rand.nextInt(7) % 6 == 0) ? 2 : 1;}if (v.size() == 0) {boolean isSame = false;loop1:for (int i = 0; i < 3; i++) {for (int j = 0; j < 4; j++) {if ((table[i][j] == table[i + 1][j]) || (table[j][i] == table[j][i + 1])) {isSame = true;break loop1;}}}if (!isSame) {isOver = true;repaint();}}}private void bDown() {for (int j = 0; j <= 3; j++) {//第一个if是为了一种稍微特殊的地方//后面的每个方向都一样if (table[0][j] == table[1][j] && table[2][j] == table[3][j]&& table[0][j] != 0 && table[2][j] != 0) {table[1][j]++;table[0][j] = 0;}for (int i = 2; i >= 0; i--) {if (table[i + 1][j] == 0) {table[i + 1][j] = table[i][j];table[i][j] = 0;}if (table[i][j] != 0 && table[i][j] == table[i + 1][j]) {if (c[j]) {table[i + 1][j]++;table[i][j] = 0;c[j] = false;source += (int) Math.pow(2, table[i + 1][j]);}}}}}private void bLeft() {for (int i = 0; i <= 3; i++) {if (table[i][0] == table[i][1] && table[i][2] == table[i][3]&& table[i][0] != 0 && table[i][2] != 0) {table[i][2]++;table[i][3] = 0;}for (int j = 1; j <= 3; j++) {if (table[i][j - 1] == 0) {table[i][j - 1] = table[i][j];table[i][j] = 0;}if (table[i][j] != 0 && table[i][j] == table[i][j - 1]) {if (c[i]) {table[i][j - 1]++;table[i][j] = 0;c[i] = false;source += (int) Math.pow(2, table[i][j - 1]);}}}}}private void bRight() {for (int i = 0; i <= 3; i++) {if (table[i][0] == table[i][1] && table[i][2] == table[i][3]&& table[i][0] != 0 && table[i][2] != 0) {table[i][1]++;table[i][0] = 0;}for (int j = 2; j >= 0; j--) {if (table[i][j + 1] == 0) {table[i][j + 1] = table[i][j];table[i][j] = 0;}if (table[i][j] != 0 && table[i][j] == table[i][j + 1]) {if (c[i]) {table[i][j + 1]++;table[i][j] = 0;c[i] = false;source += (int) Math.pow(2, table[i][j + 1]);}}}}}private void bUp() {for (int j = 0; j <= 3; j++) {if (table[0][j] == table[1][j] && table[2][j] == table[3][j]&& table[0][j] != 0 && table[2][j] != 0) {table[2][j]++;table[3][j] = 0;}for (int i = 1; i <= 3; i++) {if (table[i - 1][j] == 0) {table[i - 1][j] = table[i][j];table[i][j] = 0;}if (table[i][j] != 0 && table[i][j] == table[i - 1][j]) {if (c[j]) {table[i - 1][j]++;table[i][j] = 0;c[j] = false;source += (int) Math.pow(2, table[i - 1][j]);}}}}}public int getS() throws IOException {String filePath = "src\\game_2048\\best.txt";FileReader fileReader = new FileReader(filePath);int data = 0;String s = "";while ((data = fileReader.read()) != -1) {s += (char) data;}int y = Integer.parseInt(s);fileReader.close();return y;}private void setS(int y) throws IOException {String filePath = "src\\game_2048\\best.txt";FileWriter fileWriter = new FileWriter(filePath);String yy = y + "";fileWriter.write(yy);fileWriter.close();}}

Block 

每个方块创建的类。

package game_2048;import java.awt.*;public class Block {int kind;Font wFont;Color wColor;Color bColor;String s;public Block(int kind) {this.kind = kind;}private final Font font1 = new Font("宋体", Font.BOLD, 46);private final Font font2 = new Font("宋体", Font.BOLD, 40);private final Font font3 = new Font("宋体", Font.BOLD, 34);private final Font font4 = new Font("宋体", Font.BOLD, 28);private final Color color1 = new Color(119,108,99);private final Color color2 = new Color(254,254,254);public void setAllFont() {switch (kind) {case 0 -> bColor = new Color(206, 194, 180);case 1 -> {wFont = font1;wColor = color1;bColor = new Color(237, 229, 218);s = 2 + "";}case 2 -> {wFont = font1;wColor = color1;bColor = new Color(237, 220, 190);s = 4 + "";}case 3 -> {wFont = font1;wColor = color1;bColor = new Color(242, 177, 123);s = 8 + "";}case 4 -> {wFont = font2;wColor = color2;bColor = new Color(246, 147, 92);s = 16 + "";}case 5 -> {wFont = font2;wColor = color2;bColor = new Color(245, 118, 86);s = 32 + "";}case 6 -> {wFont = font2;wColor = color2;bColor = new Color(245, 83, 45);s = 64 + "";}case 7 -> {wFont = font3;wColor = color2;bColor = new Color(237, 206, 115);s = 128 + "";}case 8 -> {wFont = font3;wColor = color2;bColor = new Color(230,209,81);s = 256 + "";}case 9 -> {wFont = font3;wColor = color2;bColor = new Color(207,163,12);s = 512 + "";}case 10 -> {wFont = font4;wColor = color2;bColor = new Color(229,180,6);s = 1024 + "";}case 11 -> {wFont = font4;wColor = color2;bColor = new Color(161,131,115);s = 2048 + "";}default -> {}}}}

MFrame

package game_2048;/**@author douhehe*/import javax.swing.*;public class MFrame {public static void main(String[] args) {JFrame jf = new JFrame("2048小游戏");jf.add(new MPanel());jf.setSize(401,552);jf.setLocationRelativeTo(null);     //居中jf.setResizable(false);jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);jf.setVisible(true);}
}

2048小游戏 java版(代码+注释)相关推荐

  1. 贪吃蛇小游戏java实现代码分析

    贪吃蛇小游戏java实现代码分析 贪吃蛇的小游戏,网上的代码比较多,今天周五,在教研室没啥事做,在电脑中发现了一个贪吃蛇的小游戏,于是就看了下实现的源码,发现别人写的代码确实挺好的,自己也是边加注释边 ...

  2. java实现2048小游戏(源码+注释)

    实现文件 APP.java import javax.swing.*;public class APP {public static void main(String[] args) {new MyF ...

  3. 简易贪吃蛇小游戏java版_用GUI实现java版贪吃蛇小游戏

    本文实例为大家分享了java版贪吃蛇小游戏的具体代码,供大家参考,具体内容如下 项目结构 新建一个JFrame窗口,作为程序入口 public class GameStart{ public stat ...

  4. go语言实现2048小游戏(完整代码)

    文章目录 2048逻辑分析 完整代码 2048逻辑分析 2048小游戏的基本操作是上下左右,每个操作的逻辑都不太一样! 这个时候,通过数组旋转的方式.将所有操作转换为向上的操作 git地址 https ...

  5. 五子棋小游戏 java版(代码+详细注释)

    游戏展示         这周闲来无事,再来写个五子棋小游戏.基本功能都实现了,包括人人对战.人机对战.界面布局和功能都写的还行,没做到很优秀,但也不算差.如有需要,做个java初学者的课程设计或者自 ...

  6. 魔塔小游戏Java版项目

    这是一款童年游戏4399网站上的魔塔仿制版,回忆童年,入手开发项目,全方面的代码解析 更多项目: 1.飞机大战Java版(Java+JavaSwing+多线程结构) 2.Java之马里奥游戏 3.大鱼 ...

  7. YSO小游戏·VB6版代码

    Form1: tmrFPS Inteval = 1000 Enable = False tmrAudio Inteval = 100 Enable = False tmrLine Inteval = ...

  8. C语言版2048小游戏创作思路及代码

    自己学习c语言也有一段时间,但还是对c语言没有感觉,所有想通过写博客来提高自己对c语言的理解. 在写2048的时候,参考了不少优秀的代码,也有一些自己的理解,希望能给大家一些参考. 先要有界面,顺带把 ...

  9. 2048c语言的思路,C语言版2048小游戏创作思路及代码

    #include "stdafx.h" #include "stdlib.h" #include "conio.h" //writeKey( ...

最新文章

  1. webdriver Google-chrome crashed
  2. CodeForces 390E Inna and Large Sweet Matrix(树状数组改段求段)
  3. Day4-Springmvc表单数据
  4. 合并两个有序数组—leetcode88
  5. 重磅!阿里云发布业界首款SaaS化防火墙
  6. Salesforce 中获取数据表字段的 picklist 的值
  7. Linux虚拟网络原理小结
  8. Nuget:Newtonsoft.Json
  9. 手机网站与普通网站的不同
  10. 半导体芯片产业链公司大全
  11. #学习笔记 使用c语言来制作一个计算器
  12. 通信原理、模电——部分英文术语对照表
  13. 关于苹果开发证书、发布证书、开发推送证书、发布推送证书的申请
  14. Win11怎么以管理员身份运行?Win11以管理员身份运行的设置方法
  15. typeScrip(一)基础类型
  16. Netty空闲检测之读空闲
  17. 计算机组成原理之计算机最基本的工作原理
  18. webERP安装配置超详细
  19. 1024px是个好模版
  20. el-upload点击打开文件上传弹窗之前进行其他操作,等待操作完成后再打开文件上传弹窗

热门文章

  1. 有skycc营销软件,我的网站PR飙升
  2. 世界上最美的晚秋,美过油画,令人叫绝!
  3. 用GRUB2来实现——坎特伯雷项目 The Canterbury Project
  4. Three.js学习笔记---我和小伙伴都惊呆了
  5. SOLIDWORKS中如何使用配置创建系列零件
  6. 富文本转化为普通文本
  7. You are trying to add a non-nullable field 'code' to business without a default; we can't do that...
  8. 网页设计与构架中的几个SEO优化原则
  9. matlab等势面,利用Matlab模拟点电荷系的电场线和等势面
  10. 【XAI】Nettack IG-JSMA