转载请标明出处:http://blog.csdn.net/idealism_xxm/article/details/50284487,本文出自: 【idealism_xxm的博客】
根据必要功能按照自己的想法写了一下,可能实现得比较麻烦,但是感觉还不错,暂时没发现其他bug
import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.event.KeyListener; /* * 未设置不同数字的大小 * 未设置实时显示分数 * ……总之就是最简易的版本 */ public class Game extends JFrame { private final int LEN=100,MAXN=4;//LEN是一个方块的边长,MAXN是方阵的阶数 private JLabel[][] jlb=new JLabel[MAXN][MAXN]; private int num[][]=new int[MAXN][MAXN]; private int filled,score; public Game() { getContentPane().setBackground(new Color(187,173,160));//【注意】JFrame应该这样改变颜色 setLayout(new GridLayout(MAXN,MAXN,10,10)); for(int i=0;i<MAXN;++i) { for(int j=0;j<MAXN;++j) { num[i][j]=0; add(jlb[i][j]=new JLabel()); jlb[i][j].setBackground(getBkgColor(0)); jlb[i][j].setForeground(getFrgColor(0)); jlb[i][j].setOpaque(true);//【注意】JLabel默认情况下是透明,所以只能先将其设成不透明才能显示颜色 jlb[i][j].setText(null); jlb[i][j].setHorizontalAlignment(JLabel.CENTER);//居中显示 } } addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { switch(e.getKeyCode()) { case KeyEvent.VK_LEFT: { if(moveLeft()) { next(); display(); if(!canMove()) { JOptionPane.showMessageDialog(null,"Score:"+score, "Game Over", JOptionPane.PLAIN_MESSAGE, null); reset(); } } return; } case KeyEvent.VK_UP: { turnClockwise(3); if(moveLeft()) { turnClockwise(1); next(); display(); if(!canMove()) { JOptionPane.showMessageDialog(null,"Score:"+score, "Game Over", JOptionPane.PLAIN_MESSAGE, null); reset(); } } else { turnClockwise(1); } return; } case KeyEvent.VK_RIGHT: { turnClockwise(2); if(moveLeft()) { turnClockwise(2); next(); display(); if(!canMove()) { JOptionPane.showMessageDialog(null,"Score:"+score, "Game Over", JOptionPane.PLAIN_MESSAGE, null); reset(); } } else { turnClockwise(2); } return; } case KeyEvent.VK_DOWN: { turnClockwise(1); if(moveLeft()) { turnClockwise(3); next(); display(); if(!canMove()) { JOptionPane.showMessageDialog(null,"Score:"+score, "Game Over", JOptionPane.PLAIN_MESSAGE, null); reset(); } } else { turnClockwise(3); } return; } } } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } }); reset(); setTitle(""+2048); setSize(LEN*MAXN+10,LEN*MAXN+10); setLocationRelativeTo(null); setResizable(false); setVisible(true); } private void reset() { score=filled=0; for(int r=0;r<MAXN;++r) for(int c=0;c<MAXN;++c) num[r][c]=0; next(); next(); display(); } private boolean canMove() {//判断能否继续移动 if(filled!=MAXN*MAXN) return true; int ori[][]=new int[4][4],tmp=filled,temp=score; myCopy(num,ori); if(!moveLeft()) {//无法向左移动 myCopy(ori,num); turnClockwise(3); if(!moveLeft()) {//无法向上移动 myCopy(ori,num); turnClockwise(2); if(!moveLeft()) {//无法向右移动 myCopy(ori,num); turnClockwise(1); if(!moveLeft()) {//无法向下移动 myCopy(ori,num); return false; } } } } filled=tmp; score=temp; myCopy(ori,num); return true; } private void display() {//将数字与JLabel对应 for(int i=0;i<MAXN;++i) for(int j=0;j<MAXN;++j) { jlb[i][j].setText(Integer.toString(num[i][j])); jlb[i][j].setBackground(getBkgColor(num[i][j])); jlb[i][j].setForeground(getFrgColor(num[i][j])); } } private boolean moveLeft() {//按下左箭头时,内部矩阵的计算 boolean moved=false; for(int r=0;r<MAXN;++r) if(moveRow(r)) moved=true; return moved; } private boolean moveRow(int r) {//按下左箭头时,内部矩阵第r行的计算 boolean moved=fillUp(r); for(int c=1;c<MAXN;++c) {//合并 if(num[r][c]==num[r][c-1]&&num[r][c]!=0) { --filled; moved=true; num[r][c-1]<<=1; num[r][c]=0; score+=num[r][c-1]; } } return fillUp(r)||moved; } private boolean fillUp(int r) {//当前行向左移动 int c=0,t; boolean moved=false; while(c<MAXN&&num[r][c]!=0)//找到第一个空位 ++c; t=c; for(;t<MAXN;++t) {//补齐空位 if(num[r][t]!=0) { moved=true; num[r][c++]=num[r][t]; } } for(;c<MAXN;++c) if(num[r][c]!=0) {//若c~MAXN-1存在非0方块,则必定产生移动 moved=true; num[r][c]=0; } return moved; } private void next() {//填入一个方块2或4 ++filled; int r=((int)(Math.random()*MAXN))%MAXN,c=((int)(Math.random()*MAXN))%MAXN,n=((int)(Math.random()*2))%2; while(num[r][c]!=0) { r=((int)(Math.random()*MAXN))%MAXN; c=((int)(Math.random()*MAXN))%MAXN; } num[r][c]=2<<n; } private void turnClockwise(int times) {//将矩阵顺时针旋转times*90° times%=4; while((times--)>0) { int tmp[][]=new int[MAXN][MAXN],r,c,t; myCopy(num,tmp); for(r=0;r<MAXN;++r)//顺时针旋转90° for(c=0,t=MAXN-1;c<MAXN;++c,--t) num[r][c]=tmp[t][r]; } } private void myCopy(int[][] src,int[][] dest) { for(int r=0;r<MAXN;++r) for(int c=0;c<MAXN;++c) dest[r][c]=src[r][c]; } private Color getBkgColor(int num) { switch(num) { case 0: return new Color(205,193,180); case 2: return new Color(238,228,218); case 4: return new Color(224,237,200); case 8: return new Color(242,117,121); case 16: return new Color(249,149,99); case 32: return new Color(246,124,95); case 64: return new Color(246,94,59); case 128: return new Color(237,217,114); case 256: return new Color(237,204,97); case 512: return new Color(236,176,77); case 1024: return new Color(236,148,55); case 2048: return new Color(236,120,33); } return new Color(236,120,33); } private Color getFrgColor(int num) { switch(num) { case 0: return new Color(205,193,180); case 2: case 4: return new Color(119,110,101); case 8: case 16: case 32: case 64: case 128: case 256: return new Color(249,246,242); } return new Color(0,0,0); } public static void main(String[] argv) { new Game(); } }