一、游戏规则:2048游戏共有16个格子,初始时初始数字由2或者4构成。
1、手指向一个方向滑动,所有格子会向那个方向运动。
2、相同数字的两个格子,相撞时数字会相加。
3、每次滑动时,空白处会随机刷新出一个数字的格子。
4、当界面不可运动时(当界面全部被数字填满时),游戏结束;当界面中最大数字是2048时,游戏胜利。
二、只有一个程序文件
package game2048;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Game2048 extends JPanel implements KeyListener,ActionListener
{
/**
* 2048游戏
*/
private static final long serialVersionUID = 1L;
enum State //1.四种状态
{
start,win,running,over
}
final Color[] colorTable=
{
new Color(0x701710),new Color(0xFFE4C3),new Color(0xfff4d3),
new Color(0xffdac3),new Color(0xe7b8e),new Color(0xe7b8e),
new Color(0xffc4c3),new Color(0xe7948e),new Color(0xbe7e56),
new Color(0xbe5e56),new Color(0x9c3931),new Color(0x701710),
};
final static int target=2048;
static int highest,score;
private Color gridColor= new Color(0xbbada0);//整体颜色
private Color emptyColor= new Color(0xcdc1b4);
private Color startColor= new Color(0xfffbcd);
private Random random=new Random();
private Tile[][] tiles;
private int side=4;
private State gamestate=State.start ;
private boolean checkingAvailableMoves;
public Game2048() //2.构造方法
{
setPreferredSize(new Dimension(900, 700));
setBackground(new Color(0xfaf8ef));
setFont(new Font("SansSerif",Font.BOLD,48));
setFocusable(true);
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
startGame();
repaint();
}
});
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
switch (e.getKeyCode())
{
case KeyEvent.VK_UP:
moveUp();
break;
case KeyEvent.VK_DOWN:
moveDown();
break;
case KeyEvent.VK_LEFT:
moveLeft();
break;
case KeyEvent.VK_RIGHT:
moveRight();
break;
}
repaint();
}
});
}
@Override
protected void paintComponent(Graphics gg) //3.渲染
{
super.paintComponent(gg);
Graphics2D g =(Graphics2D)gg;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
drawGrid(g);
}
void drawGrid(Graphics2D g) //4.游戏状态
{
g.setColor(gridColor);
g.fillRoundRect(200, 100, 499,499,15,15);
if (gamestate==State.running)//开始中的状态
{
for(int r=0;r<side;r++)
for(int c=0;c<side;c++)
if (tiles[r][c]==null)
{
g.setColor(emptyColor);
g.fillRoundRect(215+c*121,115+r*121,106 ,106, 7,7);
}
else drawTile(g,r,c);
}
else //开始前、后状态
{
g.setColor(startColor);
g.fillRoundRect(215, 115, 469, 469, 7, 7);
g.setColor(gridColor.darker());
g.setFont(new Font("SansSerif",Font.BOLD,128));
g.drawString("2048", 310, 270);
g.setFont(new Font("SansSerif",Font.BOLD,20));
if (gamestate==State.win) g.drawString("Sucess!", 390, 350);
else if (gamestate==State.over) g.drawString("game over", 400, 350);
g.setColor(gridColor);
g.drawString("restart", 400, 350);
g.drawString("use arrow keys to move tiles", 400, 350);
}
}
private void drawTile(Graphics2D g, int r, int c)//5.随机数
{
int value=tiles[r][c].getValue();
g.setColor(colorTable[(int)(Math.log(value )/Math .log(2))+1]);
g.fillRoundRect(215+r*121,115+c*121,106,106,7,7);
String string=String.valueOf(value);
g.setColor(value<128?colorTable[0]:colorTable[1]);
FontMetrics fm = g.getFontMetrics();
int asc=fm.getAscent();
int dec=fm.getDescent();
int x=215+r*121+(106-fm.stringWidth(string))/2;
int y=115+c*121+(asc+(106-(asc+dec))/2);
g.drawString(string, x, y);
}
private boolean move(int countDownFrom,int yIncr,int xIncr)//7.核心
{
boolean moved =false;
for(int i=0;i<side*side;i++)
{
int j=Math.abs(countDownFrom-i);
int r=j/side;
int c=j%side;
if (tiles[r][c]==null) continue;
int nextR=r+yIncr;
int nextC=c+xIncr;
while (nextR>=0&&nextR<side&&nextC>=0&&nextC<side)
{
Tile next=tiles[nextR][nextC];
Tile curr=tiles[r][c];
if (next==null)
{
if (checkingAvailableMoves) return true;
tiles[nextR][nextC]=curr;
tiles[r][c]=null;
r=nextR;
c=nextC;
nextR+=yIncr;
nextC+=xIncr;
moved=true;
}
else if (next.canMergeWith(curr))
{
if (checkingAvailableMoves) return true;
int value=next.mergeWith(curr);
if (value>highest) highest=value;
score+=value ;
tiles[r][c]=null;
moved=true;
break;
}else break;
}
}
}
boolean moveRight()
{
return move(side*side-1,0,1);
}
boolean moveLeft()
{
return move(0,0,-1);
}
boolean moveDown()
{
return move(side*side-1,1,0);
}
boolean moveUp()
{
return move(0,-1,0);
}
void clearMerged()
{
for(Tile[] row:tiles)
for(Tile tile:row)
if(tile!=null) tile.setMerged(false);
}
boolean movesAvailable()
{
checkingAvailableMoves=true;
boolean hasMoves=moveUp()||moveDown()||moveLeft()||moveRight();
return hasMoves;
}
public static void main(String[] args) //入口
{
SwingUtilities.invokeLater(()->{
JFrame f =new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setTitle("2048");
f.setResizable(true);
f.add(new Game2048(),BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
protected void startGame() //开始游戏
{
if (gamestate!=State.running)
{
score=0;
highest=0;
gamestate=State.running;
tiles=new Tile[side][side];
addRandomTile();
addRandomTile();
}
}
private void addRandomTile() //6.放东西
{
int pos=random.nextInt(side*side);
int row,col;
do {
pos=(pos+1)%(side*side);
row=pos/side;
col=pos%side;
} while (tiles[row][col]!=null);
int val=random.nextInt(10)==0?4:2;
tiles[row][col]=new Tile(val);
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
class Tile
{
private boolean merged;
private int value;
Tile(int val)
{
value=val;
}
int getValue()
{
return value;
}
void setMerged(boolean m)
{
merged = m;
}
boolean canMergeWith(Tile other)
{
return !merged&&other!=null&&!other.merged&&value ==other .getValue();
}
int mergeWith(Tile other)
{
if (canMergeWith(other))
{
value*=2;
merged=true;
return value;
}
return -1;
}
}