Java实现2048小游戏(可直接运行)
运行效果:
1.项目结构
2.代码
BaseData接口
packagecom.hsy.game;
importjava.awt.*;
publicinterfaceBaseData{
FonttopicFont=newFont("微软雅黑",Font.BOLD,50);
FontscoreFont=newFont("微软雅黑",Font.BOLD,28);
FontnormalFont=newFont("宋体",Font.PLAIN,20);
Fontfont1=newFont("宋体",Font.BOLD,46);
Fontfont2=newFont("宋体",Font.BOLD,40);
Fontfont3=newFont("宋体",Font.BOLD,34);
Fontfont4=newFont("宋体",Font.BOLD,28);
Fontfont5=newFont("宋体",Font.BOLD,22);
intnormalFontData=20;
inttopicFontData=30;
voidinit();
voidshowView();
}
GameView类
packagecom.hsy.game;
importjava.awt.Color;
importjava.awt.FlowLayout;
importjava.awt.FontMetrics;
importjava.awt.Graphics;
importjava.awt.Graphics2D;
importjava.awt.RenderingHints;
importjava.awt.event.KeyEvent;
importjava.awt.event.KeyListener;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Random;
importjavax.swing.JFrame;
importjavax.swing.JLabel;
importjavax.swing.JPanel;
publicclassGameViewimplementsBaseData{
privatestaticfinalintjFrameWidth=400;
privatestaticfinalintjFrameHeight=530;
privatestaticintscore=0;
privateJFramejFrameMain;
privateJLabeljLblTitle;
privateJLabeljLblScoreName;
privateJLabeljLblScore;
privateGameBoardgameBoard;
privateJLabeljlblTip;
publicGameView(){
init();
}
@Override
publicvoidinit(){
jFrameMain=newJFrame("2048小游戏");
jFrameMain.setSize(jFrameWidth,jFrameHeight);
jFrameMain.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrameMain.setLocationRelativeTo(null);
jFrameMain.setResizable(false);
jFrameMain.setLayout(null);
jLblTitle=newJLabel("2048",JLabel.CENTER);
jLblTitle.setFont(topicFont);
jLblTitle.setForeground(Color.BLACK);
jLblTitle.setBounds(50,0,150,60);
jFrameMain.add(jLblTitle);
//分数区
jLblScoreName=newJLabel("得分",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=newJLabel("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=newJLabel("操作:↑↓←→,按esc键重新开始",
JLabel.CENTER);
jlblTip.setFont(normalFont);
jlblTip.setForeground(Color.DARK_GRAY);
jlblTip.setBounds(0,60,400,40);
jFrameMain.add(jlblTip);
gameBoard=newGameBoard();
gameBoard.setBounds(0,100,400,400);
gameBoard.setBackground(Color.GRAY);
gameBoard.setFocusable(true);
gameBoard.setLayout(newFlowLayout());
jFrameMain.add(gameBoard);
}
//游戏面板需要对键值实现侦听,
//这里采用内部类来继承JPanel类,
//并实现接口KeyListener中的keyPressed方法,
//方格是通过
@SuppressWarnings("serial")
classGameBoardextendsJPanelimplementsKeyListener{
privatestaticfinalintCHECK_GAP=10;
privatestaticfinalintCHECK_ARC=20;
privatestaticfinalintCHECK_SIZE=86;
privateCheck[][]checks=newCheck[4][4];
privatebooleanisAdd=true;
publicGameBoard(){
initGame();
addKeyListener(this);
}
@Override
publicvoidkeyPressed(KeyEvente){
switch(e.getKeyCode()){
caseKeyEvent.VK_ESCAPE:
initGame();
break;
caseKeyEvent.VK_LEFT:
moveLeft();
createCheck();
judgeGameOver();
break;
caseKeyEvent.VK_RIGHT:
moveRight();
createCheck();
judgeGameOver();
break;
caseKeyEvent.VK_UP:
moveUp();
createCheck();
judgeGameOver();
break;
caseKeyEvent.VK_DOWN:
moveDown();
createCheck();
judgeGameOver();
break;
default:
break;
}
repaint();
}
privatevoidinitGame(){
score=0;
for(intindexRow=0;indexRow<4;indexRow++){
for(intindexCol=0;indexCol<4;indexCol++){
checks[indexRow][indexCol]=newCheck();
}
}
//生成两个数
isAdd=true;
createCheck();
isAdd=true;
createCheck();
}
privatevoidcreateCheck(){
Listlist=getEmptyChecks();
if(!list.isEmpty()&&isAdd){
Randomrandom=newRandom();
intindex=random.nextInt(list.size());
Checkcheck=list.get(index);
//2,4出现概率3:1
check.value=(random.nextInt(4)%3==0)?2:4;
isAdd=false;
}
}
//获取空白方格
privateListgetEmptyChecks(){
ListcheckList=newArrayList<>();
for(inti=0;i<4;i++){
for(intj=0;j<4;j++){
if(checks[i][j].value==0){
checkList.add(checks[i][j]);
}
}
}
returncheckList;
}
privatebooleanjudgeGameOver(){
jLblScore.setText(score+"");
if(!getEmptyChecks().isEmpty()){
returnfalse;
}
for(inti=0;i<3;i++){
for(intj=0;j<3;j++){
//判断是否存在可合并的方格
if(checks[i][j].value==checks[i][j+1].value
||checks[i][j].value==checks[i+1][j].value){
returnfalse;
}
}
}
returntrue;
}
privatebooleanmoveLeft(){
for(inti=0;i<4;i++){
for(intj=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;
}elseif(checks[i][index].value==0){
checks[i][index].value=checks[i][j].value;
checks[i][j].value=0;
isAdd=true;
}elseif(checks[i][++index].value==0){
checks[i][index].value=checks[i][j].value;
checks[i][j].value=0;
isAdd=true;
}
}
}
}
returnisAdd;
}
privatebooleanmoveRight(){
for(inti=0;i<4;i++){
for(intj=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;
}elseif(checks[i][index].value==0){
checks[i][index].value=checks[i][j].value;
checks[i][j].value=0;
isAdd=true;
}elseif(checks[i][--index].value==0){
checks[i][index].value=checks[i][j].value;
checks[i][j].value=0;
isAdd=true;
}
}
}
}
returnisAdd;
}
privatebooleanmoveUp(){
for(inti=0;i<4;i++){
for(intj=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;
}elseif(checks[index][i].value==0){
checks[index][i].value=checks[j][i].value;
checks[j][i].value=0;
isAdd=true;
}elseif(checks[++index][i].value==0){
checks[index][i].value=checks[j][i].value;
checks[j][i].value=0;
isAdd=true;
}
}
}
}
returnisAdd;
}
privatebooleanmoveDown(){
for(inti=0;i<4;i++){
for(intj=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;
}elseif(checks[index][i].value==0){
checks[index][i].value=checks[j][i].value;
checks[j][i].value=0;
isAdd=true;
}elseif(checks[--index][i].value==0){
checks[index][i].value=checks[j][i].value;
checks[j][i].value=0;
isAdd=true;
}
}
}
}
returnisAdd;
}
@Override
publicvoidpaint(Graphicsg){
super.paint(g);
for(inti=0;i<4;i++){
for(intj=0;j<4;j++){
drawCheck(g,i,j);
}
}
//GameOver
if(judgeGameOver()){
g.setColor(newColor(64,64,64,150));
g.fillRect(0,0,getWidth(),getHeight());
g.setColor(Color.WHITE);
g.setFont(topicFont);
FontMetricsfms=getFontMetrics(topicFont);
Stringvalue="GameOver!";
g.drawString(value,
(getWidth()-fms.stringWidth(value))/2,
getHeight()/2);
}
}
//绘制方格
//Graphics2D类扩展了Graphics类,
//提供了对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
privatevoiddrawCheck(Graphicsg,inti,intj){
Graphics2Dgg=(Graphics2D)g;
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
gg.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
RenderingHints.VALUE_STROKE_NORMALIZE);
Checkcheck=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());
//对文字的长宽高测量。
FontMetricsfms=getFontMetrics(check.getCheckFont());
Stringvalue=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
publicvoidkeyReleased(KeyEvente){
}
@Override
publicvoidkeyTyped(KeyEvente){
}
}
@Override
publicvoidshowView(){
jFrameMain.setVisible(true);
}
}
Check类
packagecom.hsy.game;
importjava.awt.Color;
importjava.awt.Font;
publicclassCheck{
publicintvalue;
publicCheck(){
clear();
}
publicvoidclear(){
value=0;
}
publicColorgetForeground(){
switch(value){
case0:
returnnewColor(0xcdc1b4);
case2:
case4:
returnColor.BLACK;
default:
returnColor.WHITE;
}
}
publicColorgetBackground(){
switch(value){
case0:
returnnewColor(0xcdc1b4);
case2:
returnnewColor(0xeee4da);
case4:
returnnewColor(0xede0c8);
case8:
returnnewColor(0xf2b179);
case16:
returnnewColor(0xf59563);
case32:
returnnewColor(0xf67c5f);
case64:
returnnewColor(0xf65e3b);
case128:
returnnewColor(0xedcf72);
case256:
returnnewColor(0xedcc61);
case512:
returnnewColor(0xedc850);
case1024:
returnnewColor(0xedc53f);
case2048:
returnnewColor(0xedc22e);
case4096:
returnnewColor(0x65da92);
case8192:
returnnewColor(0x5abc65);
case16384:
returnnewColor(0x248c51);
default:
returnnewColor(0x248c51);
}
}
publicFontgetCheckFont(){
if(value<10){
returnBaseData.font1;
}
if(value<100){
returnBaseData.font2;
}
if(value<1000){
returnBaseData.font3;
}
if(value<10000){
returnBaseData.font4;
}
returnBaseData.font5;
}
}
Test类
packagecom.hsy.game;
publicclassTest{
publicstaticvoidmain(String[]args){
newGameView().showView();
}
}
运行Test即可
总结
到此这篇关于Java实现2048小游戏的文章就介绍到这了,更多相关Java2048小游戏内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。