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; } } //获取空白方格 privateList getEmptyChecks(){ List checkList=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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。