运行效果:

1.项目结构

2.代码

basedata接口

package com.hsy.game;

import java.awt.*;

public interface basedata {
 font topicfont = new font("微软雅黑", font.bold, 50);
 font scorefont = new font("微软雅黑", font.bold, 28);
 font normalfont = new font("宋体", font.plain, 20);
 font font1 = new font("宋体", font.bold, 46);
 font font2 = new font("宋体", font.bold, 40);
 font font3 = new font("宋体", font.bold, 34);
 font font4 = new font("宋体", font.bold, 28);
 font font5 = new font("宋体", font.bold, 22);
 int normalfontdata = 20;
 int topicfontdata = 30;

 void init();
 void showview();
}

gameview类

package com.hsy.game;
import java.awt.color;
import java.awt.flowlayout;
import java.awt.fontmetrics;
import java.awt.graphics;
import java.awt.graphics2d;
import java.awt.renderinghints;
import java.awt.event.keyevent;
import java.awt.event.keylistener;
import java.util.arraylist;
import java.util.list;
import java.util.random;
import javax.swing.jframe;
import javax.swing.jlabel;
import javax.swing.jpanel;
public class gameview implements basedata{
private static final int jframewidth = 400;
private static final int jframeheight = 530;
private static int score = 0;
private jframe jframemain;
private jlabel jlbltitle;
private jlabel jlblscorename;
private jlabel jlblscore;
private gameboard gameboard;
private jlabel jlbltip;
public gameview() {
init();
}
@override
public void init() {
jframemain = new jframe("2048小游戏");
jframemain.setsize(jframewidth, jframeheight);
jframemain.setdefaultcloseoperation(jframe.exit_on_close);
jframemain.setlocationrelativeto(null);
jframemain.setresizable(false);
jframemain.setlayout(null);
jlbltitle = new jlabel("2048", jlabel.center);
jlbltitle.setfont(topicfont);
jlbltitle.setforeground(color.black);
jlbltitle.setbounds(50, 0, 150, 60);
jframemain.add(jlbltitle);
// 分数区
jlblscorename = new jlabel("得 分", jlabel.center);
jlblscorename.setfont(scorefont);
jlblscorename.setforeground(color.white);
jlblscorename.setopaque(true);
jlblscorename.setbackground(color.gray);
jlblscorename.setbounds(250, 0, 120, 30);
jframemain.add(jlblscorename);
jlblscore = new jlabel("0", jlabel.center);
jlblscore.setfont(scorefont);
jlblscore.setforeground(color.white);
jlblscore.setopaque(true);
jlblscore.setbackground(color.gray);
jlblscore.setbounds(250, 30, 120, 30);
jframemain.add(jlblscore);
// 说明:
jlbltip = new jlabel("操作: ↑ ↓ ← →, 按esc键重新开始 ",
jlabel.center);
jlbltip.setfont(normalfont);
jlbltip.setforeground(color.dark_gray);
jlbltip.setbounds(0, 60, 400, 40);
jframemain.add(jlbltip);
gameboard = new gameboard();
gameboard.setbounds(0, 100, 400, 400);
gameboard.setbackground(color.gray);
gameboard.setfocusable(true);
gameboard.setlayout(new flowlayout());
jframemain.add(gameboard);
}
// 游戏面板需要对键值实现侦听,
// 这里采用内部类来继承 jpanel 类,
// 并实现接口 keylistener 中的 keypressed 方法,
// 方格是通过
@suppresswarnings("serial")
class gameboard extends jpanel implements keylistener {
private static final int check_gap = 10;
private static final int check_arc = 20;
private static final int check_size = 86;
private check[][] checks = new check[4][4];
private boolean isadd = true;
public gameboard() {
initgame();
addkeylistener(this);
}
@override
public void keypressed(keyevent e) {
switch (e.getkeycode()) {
case keyevent.vk_escape:
initgame();
break;
case keyevent.vk_left:
moveleft();
createcheck();
judgegameover();
break;
case keyevent.vk_right:
moveright();
createcheck();
judgegameover();
break;
case keyevent.vk_up:
moveup();
createcheck();
judgegameover();
break;
case keyevent.vk_down:
movedown();
createcheck();
judgegameover();
break;
default:
break;
}
repaint();
}
private void initgame() {
score = 0;
for (int indexrow = 0; indexrow < 4; indexrow++) {
for (int indexcol = 0; indexcol < 4; indexcol++) {
checks[indexrow][indexcol] = new check();
}
}
// 生成两个数
isadd = true;
createcheck();
isadd = true;
createcheck();
}
private void createcheck() {
list<check> list = getemptychecks();
if (!list.isempty() && isadd) {
random random = new random();
int index = random.nextint(list.size());
check check = list.get(index);
// 2, 4出现概率3:1
check.value = (random.nextint(4) % 3 == 0) ? 2 : 4;
isadd = false;
}
}
// 获取空白方格
private list<check> getemptychecks() {
list<check> checklist = new arraylist<>();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (checks[i][j].value == 0) {
checklist.add(checks[i][j]);
}
}
}
return checklist;
}
private boolean judgegameover() {
jlblscore.settext(score + "");
if (!getemptychecks().isempty()) {
return false;
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//判断是否存在可合并的方格
if (checks[i][j].value == checks[i][j + 1].value
|| checks[i][j].value == checks[i + 1][j].value) {
return false;
}
}
}
return true;
}
private boolean moveleft() {
for (int i = 0; i < 4; i++) {
for (int j = 1, index = 0; j < 4; j++) {
if (checks[i][j].value > 0) {
if (checks[i][j].value == checks[i][index].value) {
score += checks[i][index++].value <<= 1;
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][index].value == 0) {
checks[i][index].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][++index].value == 0) {
checks[i][index].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
private boolean moveright() {
for (int i = 0; i < 4; i++) {
for (int j = 2, index = 3; j >= 0; j--) {
if (checks[i][j].value > 0) {
if (checks[i][j].value == checks[i][index].value) {
score += checks[i][index--].value <<= 1;
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][index].value == 0) {
checks[i][index].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
} else if (checks[i][--index].value == 0) {
checks[i][index].value = checks[i][j].value;
checks[i][j].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
private boolean moveup() {
for (int i = 0; i < 4; i++) {
for (int j = 1, index = 0; j < 4; j++) {
if (checks[j][i].value > 0) {
if (checks[j][i].value == checks[index][i].value) {
score += checks[index++][i].value <<= 1;
checks[j][i].value = 0;
isadd = true;
} else if (checks[index][i].value == 0) {
checks[index][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
} else if (checks[++index][i].value == 0){
checks[index][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
private boolean movedown() {
for (int i = 0; i < 4; i++) {
for (int j = 2, index = 3; j >= 0; j--) {
if (checks[j][i].value > 0) {
if (checks[j][i].value == checks[index][i].value) {
score += checks[index--][i].value <<= 1;
checks[j][i].value = 0;
isadd = true;
} else if (checks[index][i].value == 0) {
checks[index][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
} else if (checks[--index][i].value == 0) {
checks[index][i].value = checks[j][i].value;
checks[j][i].value = 0;
isadd = true;
}
}
}
}
return isadd;
}
@override
public void paint(graphics g) {
super.paint(g);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
drawcheck(g, i, j);
}
}
// gameover
if (judgegameover()) {
g.setcolor(new color(64, 64, 64, 150));
g.fillrect(0, 0, getwidth(), getheight());
g.setcolor(color.white);
g.setfont(topicfont);
fontmetrics fms = getfontmetrics(topicfont);
string value = "game over!";
g.drawstring(value,
(getwidth()-fms.stringwidth(value)) / 2,
getheight() / 2);
}
}
// 绘制方格
// graphics2d 类扩展了 graphics 类,
// 提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
private void drawcheck(graphics g, int i, int j) {
graphics2d gg = (graphics2d) g;
gg.setrenderinghint(renderinghints.key_antialiasing,
renderinghints.value_antialias_on);
gg.setrenderinghint(renderinghints.key_stroke_control,
renderinghints.value_stroke_normalize);
check check = checks[i][j];
gg.setcolor(check.getbackground());
// 绘制圆角
// x - 要填充矩形的 x 坐标。
// y - 要填充矩形的 y 坐标。
// width - 要填充矩形的宽度。
// height - 要填充矩形的高度。
// arcwidth - 4 个角弧度的水平直径。
// archeight - 4 个角弧度的垂直直径。
gg.fillroundrect(check_gap + (check_gap + check_size) * j,
check_gap + (check_gap + check_size) * i,
check_size, check_size, check_arc, check_arc);
gg.setcolor(check.getforeground());
gg.setfont(check.getcheckfont());
// 对文字的长宽高测量。
fontmetrics fms = getfontmetrics(check.getcheckfont());
string value = string.valueof(check.value);
//使用此图形上下文的当前颜色绘制由指定迭代器给定的文本。
//getascent()是fontmetrics中的一个方法,
//它返回某字体的基线(baseline)到该字体中大多数字符的升部(ascender)之间的距离
//getdescent 为降部
gg.drawstring(value,
check_gap + (check_gap + check_size) * j +
(check_size - fms.stringwidth(value)) / 2,
check_gap + (check_gap + check_size) * i +
(check_size - fms.getascent() - fms.getdescent()) / 2
+ fms.getascent());
}
@override
public void keyreleased(keyevent e) {
}
@override
public void keytyped(keyevent e) {
}
}
@override
public void showview() {
jframemain.setvisible(true);
}
}

check类

package com.hsy.game;
import java.awt.color;
import java.awt.font;
public class check {
public int value;
public check() {
clear();
}
public void clear() {
value = 0;
}
public color getforeground() {
switch (value) {
case 0:
return new color(0xcdc1b4);
case 2:
case 4:
return color.black;
default:
return color.white;
}
}
public color getbackground() {
switch (value) {
case 0:
return new color(0xcdc1b4);
case 2:
return new color(0xeee4da);
case 4:
return new color(0xede0c8);
case 8:
return new color(0xf2b179);
case 16:
return new color(0xf59563);
case 32:
return new color(0xf67c5f);
case 64:
return new color(0xf65e3b);
case 128:
return new color(0xedcf72);
case 256:
return new color(0xedcc61);
case 512:
return new color(0xedc850);
case 1024:
return new color(0xedc53f);
case 2048:
return new color(0xedc22e);
case 4096:
return new color(0x65da92);
case 8192:
return new color(0x5abc65);
case 16384:
return new color(0x248c51);
default:
return new color(0x248c51);
}
}
public font getcheckfont() {
if (value < 10) {
return basedata.font1;
}
if (value < 100) {
return basedata.font2;
}
if (value < 1000) {
return basedata.font3;
}
if (value < 10000) {
return basedata.font4;
}
return basedata.font5;
}
}

test类

package com.hsy.game;
public class test {
public static void main(string[] args) {
new gameview().showview();
}
}

运行test即可

总结

到此这篇关于java实现2048小游戏的文章就介绍到这了,更多相关java 2048小游戏内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!