用JAVA实现2048小游戏

2024-03-05 11:40
文章标签 java 实现 小游戏 2048

本文主要是介绍用JAVA实现2048小游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

用JAVA实现2048小游戏

  • 前言
  • 一、代码
    • 运行结果


前言

今天给大家分享一个简单的游戏——2048,想必大家平常都玩过这款,那么今天我就给大家分享一下这游戏的代码吧。下面直接给大家上代码展示!!

一、代码

package com.company;import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
//继承 JPanel 用于我们游戏界面布局
//tips:JPanel 是 Java图形用户界面(GUI)工具包swing中的面板容器类
/*** 2048小游戏* 游戏玩法:通过上下左右方向键移动图块,使得数字合出2048则获胜*/
public class Game2048 extends JPanel {//枚举:开始,获胜,正在进行游戏,游戏结束enum State {start, won, running, over}final Color[] colorTable = {new Color(0x701710), new Color(0xFFE4C3), new Color(0xfff4d3),new Color(0xffdac3), new Color(0xe7b08e), new Color(0xe7bf8e),new Color(0xffc4c3), new Color(0xE7948e), new Color(0xbe7e56),new Color(0xbe5e56), new Color(0x9c3931), new Color(0x701710)};final static int target = 2048;//游戏最终目标static int higheNum;//最高数static int score;private Color gridColor = new Color(0xBBADA0);//网格颜色private Color emptyColor = new Color(0xCDC1B4);//没有图块的格子的颜色private Color startColor = new Color(0xFFEBCD);//开始界面框的颜色private Random rand = new Random();private Tile[][] tiles;private int side = 4;private State gamestate = State.start;private boolean checkingAvailableMoves;public Game2048() {setPreferredSize(new Dimension(900, 700));setBackground(new Color(0xFAF8EF));setFont(new Font("SansSerif", Font.BOLD, 48));setFocusable(true);addMouseListener(new MouseAdapter() {@Overridepublic void mousePressed(MouseEvent e) {startGame();repaint();}});addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {switch (e.getKeyCode()) {case KeyEvent.VK_UP:moveUp();break;case KeyEvent.VK_DOWN:moveDown();break;case KeyEvent.VK_LEFT:moveLeft();break;case KeyEvent.VK_RIGHT:moveRight();break;}repaint();}});}//复写JPanel里面的paintComponent方法,创建一个我们自己想要的界面@Overridepublic void paintComponent(Graphics gg) {super.paintComponent(gg);Graphics2D g = (Graphics2D) gg;g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);drawGrid(g);}//开始游戏void startGame() {if (gamestate != State.running) {score = 0;higheNum = 0;gamestate = State.running;tiles = new Tile[side][side];//执行两次,生成两个随机数addRandomTile();addRandomTile();}}//生成框及里面内容void drawGrid(Graphics2D g) {g.setColor(gridColor);g.fillRoundRect(200, 100, 499, 499, 15, 15);if (gamestate == State.running) {for (int r = 0; r < side; r++) {for (int c = 0; c < side; c++) {if (tiles[r][c] == null) {g.setColor(emptyColor);g.fillRoundRect(215 + c * 121, 115 + r * 121, 106, 106, 7, 7);} else {drawTile(g, r, c);}}}} else {g.setColor(startColor);g.fillRoundRect(215, 115, 469, 469, 7, 7);g.setColor(gridColor.darker());//设置一个比当前颜色深一级的Colorg.setFont(new Font("SansSerif", Font.BOLD, 128));g.drawString("2048", 310, 270);g.setFont(new Font("SansSerif", Font.BOLD, 20));if (gamestate == State.won) {g.drawString("恭喜你,你成功得到2048!!", 330, 350);} else if (gamestate == State.over)g.drawString("你失败了,请重新开始游戏", 330, 350);g.setColor(gridColor);g.drawString("开始游戏", 390, 470);g.drawString("tips:使用上下左右箭头移动图块", 310, 530);}}void drawTile(Graphics2D g, int r, int c) {int value = tiles[r][c].getValue();g.setColor(colorTable[(int) (Math.log(value) / Math.log(2)) + 1]);g.fillRoundRect(215 + c * 121, 115 + r * 121, 106, 106, 7, 7);String s = String.valueOf(value);g.setColor(value < 128 ? colorTable[0] : colorTable[1]);FontMetrics fm = g.getFontMetrics();int asc = fm.getAscent();int dec = fm.getDescent();int x = 215 + c * 121 + (106 - fm.stringWidth(s)) / 2;int y = 115 + r * 121 + (asc + (106 - (asc + dec)) / 2);g.drawString(s, x, y);}private void addRandomTile() {int pos = rand.nextInt(side * side);int row, col;do {pos = (pos + 1) % (side * side);row = pos / side;col = pos % side;} while (tiles[row][col] != null);int val = rand.nextInt(10) == 0 ? 4 : 2;tiles[row][col] = new Tile(val);}private boolean move(int countDownFrom, int yIncr, int xIncr) {boolean moved = false;for (int i = 0; i < side * side; i++) {int j = Math.abs(countDownFrom - i);int r = j / side;int c = j % side;if (tiles[r][c] == null)continue;int nextR = r + yIncr;int nextC = c + xIncr;while (nextR >= 0 && nextR < side && nextC >= 0 && nextC < side) {Tile next = tiles[nextR][nextC];Tile curr = tiles[r][c];if (next == null) {if (checkingAvailableMoves)return true;tiles[nextR][nextC] = curr;tiles[r][c] = null;r = nextR;c = nextC;nextR += yIncr;nextC += xIncr;moved = true;} else if (next.canMergeWith(curr)) {if (checkingAvailableMoves)return true;int value = next.mergeWith(curr);if (value > higheNum)higheNum = value;score += value;tiles[r][c] = null;moved = true;break;} elsebreak;}}if (moved) {if (higheNum < target) {clearMerged();addRandomTile();if (!movesAvailable()) {//如果不能再移动图块,则则把游戏状态变成游戏失败gamestate = State.over;}} else if (higheNum == target)//如果最高数=2048,则把游戏状态变成游戏成功gamestate = State.won;}return moved;}boolean moveUp() {return move(0, -1, 0);}boolean moveDown() {return move(side * side - 1, 1, 0);}boolean moveLeft() {return move(0, 0, -1);}boolean moveRight() {return move(side * side - 1, 0, 1);}void clearMerged() {for (Tile[] row : tiles)for (Tile tile : row)if (tile != null)tile.setMerged(false);}//判断是否还能继续移动图块boolean movesAvailable() {checkingAvailableMoves = true;boolean hasMoves = moveUp() || moveDown() || moveLeft() || moveRight();checkingAvailableMoves = false;return hasMoves;}public static void main(String[] args) {SwingUtilities.invokeLater(() -> {JFrame f = new JFrame();f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);f.setTitle("2048小游戏");f.setResizable(true);f.add(new Game2048(), BorderLayout.CENTER);f.pack();f.setLocationRelativeTo(null);f.setVisible(true);});}
}class Tile {private boolean merged;private int value;Tile(int val) {value = val;}boolean canMergeWith(Tile other) {return !merged && other != null && !other.merged && value == other.getValue();}int mergeWith(Tile other) {if (canMergeWith(other)) {value *= 2;merged = true;return value;}return -1;}//set getint getValue() {return value;}void setMerged(boolean m) {merged = m;}
}

运行结果

1.开始界面
在这里插入图片描述
2.游戏界面
在这里插入图片描述
3.失败后界面
在这里插入图片描述

这篇关于用JAVA实现2048小游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/776391

相关文章

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它