功能要求:2048的基本界面,能够实现2048的游戏功能。

总思路:两个类:Game和GameListener。

Game负责界面的实现和paint方法的重写

GameListener负责实现键盘和鼠标事件的处理。移动方法,相加方法,输赢判断和随机数的出现都要在键盘监听的方法中实现。

实现分析:要实现2048游戏,首先需要考虑2048都有些什么?

界面实现:

2048的游戏界面很简单,就是一些方格和数字。要实现这样的界面,我们可以考虑一下使用Java的绘图功能。具体来说就是使用JFrame类提供的Graphics对象进行绘图。2048界面由一个大的矩形背景和包含数字的许多小方块组成。Graphics对象的绘制矩形的方法就能实现背景和小方格的绘制。小方格内的数字则可以使用graphics的drawString方法来绘制。只需要在绘制的时候注意一下颜色就好。界面实现要拥到的类主要是JFrame类。

基本界面实现代码,不过是一些按钮之类的,没什么好说的。

private voidinitUI() {

setTitle("2048");

setDefaultCloseOperation(3);

setSize(600, 700);

setLocationRelativeTo(null);this.setLayout(null);//添加分数

jl2 = new JLabel("分数:0");

jl2.setFont(new Font("黑体", Font.BOLD, 30));

jl2.setBounds(20, 30, 200, 50);this.add(jl2);//添加开始按钮

ImageIcon start=new ImageIcon("res/start.png");//开始游戏图标,随意替换就好

startJB=newJButton(start);

startJB.setBounds(280, 40, 120, 30);

startJB.setFocusable(false);

startJB.setBorderPainted(false);//设置按钮的边框为空

startJB.setFocusPainted(false);

startJB.setContentAreaFilled(false);//设置按钮的边框内填充颜色//添加退一步按钮

ImageIcon back=new ImageIcon("res/backicon.png");//游戏结束图标,随意替换就好

backJB=newJButton(back);

backJB.setBounds(430, 40, 120, 30);

backJB.setFocusable(false);

backJB.setBorderPainted(false);

backJB.setFocusPainted(false);

backJB.setContentAreaFilled(false);this.add(startJB);this.add(backJB);

setVisible(true);

GameListener gl= new GameListener(this, arry, jl2,startJB,backJB);

addKeyListener(gl);

startJB.addActionListener(gl);

backJB.addActionListener(gl);

}

方格和数字的绘制:

方格和数字的绘制同样是使用JFrame的画布对象的绘制矩形的方法实现。

public voidbuffPaint(Graphics g) {

Image image= createImage(600, 600);

Graphics g2=image.getGraphics();

g2.setColor(Color.LIGHT_GRAY);

Graphics2D g2d=(Graphics2D) g2;

g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

g2.fillRoundRect(0, 0, Draw2048.RD, Draw2048.RD, 20, 20);

g2.setColor(Color.GRAY);for (int r = 0; r < arry.length; r++) {for (int c = 0; c < arry[r].length; c++) {

g2.fillRect(20 + c * (Draw2048.D + Draw2048.space), 20 +r* (Draw2048.D +Draw2048.space), Draw2048.D, Draw2048.D);

}

}for (int r = 0; r < arry.length; r++) {for (int c = 0; c < arry[r].length; c++) {if (arry[r][c] != 0) {

g2.setColor(255, 250, 240);

g2.fillRect(20 + c * (Draw2048.D + Draw2048.space), 20 +r* (Draw2048.D +Draw2048.space), Draw2048.D,

Draw2048.D);

g2.setColor(new Color(0, 191, 255));

g2.setFont(new Font("楷体", Font.BOLD, Draw2048.FSIZE));

g2.drawString(arry[r][c]+ "", 50 +c* (Draw2048.D + Draw2048.space), 90 +r* (Draw2048.D +Draw2048.space));

}

}

}

g.drawImage(image,50, 150, this);

}

Draw2048是一个接口,里面定义了关于方格绘制的相关常量,D方格边长,space方格间间隔。RD背景大矩形的边长。使用接口的好处就是使得界面的更改(如改成5*5的格子)可以更加方便的实现,提高程序的扩展性。另外界面需要不断的更新,所以要调用paint方法不断的重绘。如果直接把这里的绘制写在paint方法中,不断的重绘会使得界面一直在闪烁。这里的解决方案就是使用图片缓冲,先在图片中绘制好,在把图片一次性绘制出来,这样就不会出现界面的闪烁问题了。

移动实现:

要想让方格移动起来,可以考虑的方法就是使用画板的重绘。方格内的数字则使用一个二维数组来保存。每次移动就让数组的值发生变化就行,然后根据数组的值把数据绘制到界面上。当然玩游戏时总不能靠意念操控,我们需要有输入设备,也就是键盘。所以需要给界面加上键盘监听。当用户按下不同的键则实现不同的移动算法。值得注意的是,在监听类中编写相应的移动算法的时候要理清循环的使用和结束(尤其是break语句的使用),否则会出现各种各样的bug。移动实现是需要用到keyListener类。

下面是向上移动的实现,其他方向的移动都差不多,自己琢磨一下就好:

//向上移动的算法

for (int r = 0; r < arry.length; r++)for (int c = 0; c < arry[r].length; c++) {if (arry[r][c] > max)//找出数组最大值,用于判断玩家的方块是否达到2048

max =arry[r][c];if (arry[r][c] == 0) {for (int r1 = r + 1; r1 < arry[c].length; r1++)if (arry[r1][c] != 0) {

arry[r][c]=arry[r1][c];

arry[r1][c]= 0;

count++;//判断是否发生移动,并且作为输赢判断的标准之一break;

}

}

}

通过双层循环,循环每一个值,如果它为0,则可以往上移动。遍历该值所在列,找到第一个不为0的值,移动这个值(即交换两个数的值)。移动后退出内层循环,继续遍历下一个值。

数字的相加:

使用独立的算法遍历数组,在移动方向上的相邻数两个相加,然后一个置为0。这里的算法实现和移动的算法十分相像,需要注意的地方同样也是break和循环的使用。还有一个要注意的就是:数字的相加要放在数字移动之前来完成,否则会出现移动后的数字空格。

//向左的相加算法

for (int r = 0; r < arry.length; r++)for (int c = 0; c < arry[r].length; c++)if (arry[r][c] != 0)for (int c1 = c + 1; c1 < arry[r].length; c1++)if (arry[r][c] ==arry[r][c1]) {

arry[r][c]*= 2;

score+=arry[r][c];

arry[r][c1]= 0;

count++;//判断是否发生相加,并作为输赢判断条件之一。break;

}else if (arry[r][c1] != 0) {break;

}

同样是遍历数组的每一个值,如果这个值不为0,则找所在行的相邻的相同的值相加,结束最内层循环。如果相邻的两个值不同,也结束最内层循环。两个break语句的使用,避免了数字之间的跳跃相加。

输赢的判断:

2048的赢的规则是,相加数字出现2048,所以只需要判断数组中是否有一个数字等于2048就行,如果有,就输出相应的获胜信息。

2048的输的规则是,界面已经满(数组已满,且无可移动,相加的数字)。个人的判断方法是全局变量count加上判断数组是否已满。count如果等于0,则表示无法移动和相加,配合数组已满的条件就能判断玩家已经输了。

随机数字的出现:

随机数字出现的条件是发生移动或者相加,所以判断然让使用count。条件成立则调用相应算法实现。

java2048分析_Java版2048相关推荐

  1. java 2048思路_Java版2048

    功能要求:2048的基本界面,能够实现2048的游戏功能. 总思路:两个类:Game和GameListener. Game负责界面的实现和paint方法的重写 GameListener负责实现键盘和鼠 ...

  2. java编辑2048小游戏_Java 制作命令行版 2048小游戏

    Java 命令行版 2048小游戏(2020年8月14日) 制作背景 大二即将开学,从头开始学习了一个多月的java,对二维数组的操作稍微熟悉了一些.于是想做一个简单的2048来试一试. 众所周知,2 ...

  3. 网页版2048html制作,基于HTML+CSS+JS的网页版2048的实现.pdf

    ELECTRONICS WORLD ・探索与观察 基于HTML+CSS+JS的网页版2048的实现 山西农业大学 王艺燕 [摘要] 描述了一个使用HTML和CSS进行UI界面设计,使用JS进行后台逻辑 ...

  4. 2048网页版html项目报告,jQuery编写网页版2048小游戏

    大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了,但是自己实现起 ...

  5. 详解200行Python代码实现控制台版2048【总有一款坑适合你】【超详细】

    跟着实验楼学习了2048的Python实现,先丢个地址 200行Python代码实现2048 我接触Python时间不长,只了解一些基本的语法和容器,在学习的过程中遇到不少问题,这里做一个记录. cu ...

  6. Skype 协议分析(2006版)

    Skype 协议分析(2006版) 整理翻译:袁建明 Angel_YY@126.com 概要: Skype是创建Kazaa的组织在2003年开发的一个基于Peer-to-Peer(对等网络)的VoIP ...

  7. java动态分区分配算法,操作系统_动态分区分配算法课程设计_java版

    <操作系统_动态分区分配算法课程设计_java版>由会员分享,可在线阅读,更多相关<操作系统_动态分区分配算法课程设计_java版(13页珍藏版)>请在人人文库网上搜索. 1. ...

  8. 模仿Hibernate的逆向工程_java版_源码下载

    在这篇blog:"Hibernate逆向工程原理_java版本"中谈到了Hibernate逆向工程原理. 我喜欢理论和实践相结合....so,今天我试着模仿hibernate的逆向 ...

  9. java象棋无框架版_Java版中国象棋

    /* *中国象棋Java *作者:yanick *源文件:Chess.java *最后修改时间:2006-11-1 *添加功能:实现了当前棋局的保存 *Chess.java */ import jav ...

  10. matlab 30案例 目录,MATLAB-智能算法30个案例分析-终极版(带目录).doc

    MATLAB-智能算法30个案例分析-终极版(带目录) MATLAB 智能算法30个案例分析(终极版) 1?基于遗传算法的TSP算法(王辉)? 2?基于遗传算法和非线性规划的函数寻优算法(史峰)? 3 ...

最新文章

  1. python读取文件r_python read文件的r和rb的区别
  2. java concurrent包的学习(转)
  3. 基于Visual Studio2010讲解C#4.0语法(5)--使用CollectionClasses
  4. 【颠覆认知】为什么YouTube广告只看五秒更赚钱,微博商业产品经理深度剖析。...
  5. 、简述global关键字的作用_详解static inline关键字
  6. mysql cte 表不存在_使用CTE解决复杂查询的问题_MySQL
  7. 多路串口服务器的应用及应用范围介绍
  8. java循环输入直到,使用循环接受其他用户输入,直到用户输入结束输入的值
  9. ACCESS-类型转换函数
  10. 暴力 gcd __gcd (详解)C语言求两个数的最大公约数
  11. 用txt写的mysql数据库_TXT怎么导入mySQL数据库
  12. C#打印机套打三联单
  13. rgb sw 线主板接口在哪_华硕ROG STRIX LC 360 RGB一体式水冷:与ROG主板更配
  14. linux启动菜单ubuntu,在Ubuntu上用BURG来美化开机选择菜单
  15. Memory cgroup out of memory
  16. MySQL数据库中.frm和.myi和.myd文件是什么文件?
  17. Ubuntu视频没有声音
  18. 实体字段校验@NotNull、@NotEmpty、@NotBlank
  19. 计算机控制系统z变换公式,计算机控制系统03 Z变换.ppt
  20. 打印时的纸张大小尺寸

热门文章

  1. 一个人的“野蛮”战争——周鸿祎奋斗记
  2. win10电脑插上U盘不显示盘符如何办?
  3. 自然语言处理 | (4)英文文本处理与NLTK
  4. 【实习面经】头条后台开发岗一面凉经
  5. java合并图片合成多张横向或竖向
  6. 【MYSQL】【基础知识】【MySQL的基本使用】
  7. java 为文件赋权,linux 系统给文件赋权命令大全
  8. 【信号与系统】(十一)离散系统的时域分析 ——卷积和
  9. Python学习两个月心得
  10. tan x x的matlab求解,matlab画x=tan(x)