基於java2048小遊戲簡單程式設計
阿新 • • 發佈:2019-02-11
上學期學習了一些java設計方法和模式,做個2048練練手再熟悉一下。
專案主要分為element、game、manager三個包。
element:與遊戲有關的元素類,包括基本矩形RectObject和用來表示座標的Point類。
game:與遊戲執行主體有關的,包括三個介面的Jpanel,JFrame,以及整個遊戲執行緒控制GameRunThread和遊戲主類。
manager:元素管理類,管理所有element,單例模式。
if(MyJFrame.change==true){ ElementManager.getElementManager().getARandomRect(); //saveTheStep(); }
package game; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Toolkit; import javax.swing.JPanel; public class GameoverJPanel extends JPanel { public GameoverJPanel(int w,int h){ setSize(w,h); //setOpaque(false); } public void paintComponent(Graphics g){ super.paintComponent(g); Font font=new Font("TimesRoman",Font.BOLD,80); g.setFont(font); FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font); int width=fm.stringWidth("Game Over"); int height=fm.getHeight(); g.setColor(new Color(255,0,0)); g.drawString("Game Over!", getWidth()/2-width/2, getHeight()/2-height/2); } }
package game; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.util.ArrayList; import javax.swing.JButton; import javax.swing.JPanel; import element.RectObject; import manager.ElementManager; public class GameRunThread extends Thread{ @Override public void run() { // TODO Auto-generated method stub while(true) { rectMove(); System.out.println("ok"); isReset(); isGoBack(); isGameOver(); isGameSuccess(); } } public void isGameSuccess() { if(MyJFrame.successFlag) gameSuccess(); } public void isReset() { if(MyJFrame.isReset) { refreshBest(); for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ ElementManager.getElementManager().rectObj[i][j]=null; } } MyJFrame.scoreLabel.setText("0"); MyJFrame.isReset = false; ElementManager.getElementManager().getARandomRect(); ElementManager.getElementManager().getARandomRect(); } } public void isGoBack() { if(MyJFrame.isGoBack) { // 第0位存分數,後面存數字 ArrayList arr=(ArrayList)MyJFrame.saveList.getLast(); MyJFrame.scoreLabel.setText(""+arr.get(0)); for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ int num=(int)arr.get(4*i+j+1); if(num!=0){ ElementManager.getElementManager().rectObj[i][j]=new RectObject(); ElementManager.getElementManager().rectObj[i][j].value=num; }else{ ElementManager.getElementManager().rectObj[i][j]=null; } } } MyJFrame.saveList.removeLast(); MyJFrame.isGoBack = false; } } public void isGameOver() { if( !aMoveAble()){ gameOver(); return; } } public void gameOver() { MyJFrame.gameOverFlag=true; JPanel jl=new GameoverJPanel(MyJFrame.myp.getWidth(),MyJFrame.myp.getHeight()); jl.setBounds(0, 0, 700, 700); JButton jb1=new JButton("Again"); Font font=new Font("TimesRoman",Font.BOLD,30); jb1.setOpaque(false); jb1.setFont(font); JButton jb2=new JButton("Close"); jb2.setSize(jb1.getSize()); jb2.setOpaque(false); jb2.setFont(font); jb1.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ MyJFrame.scoreLabel.setText("0"); MyJFrame.myp.remove(jl); clearList(ElementManager.getElementManager().rectObj); MyJFrame.myp.validate(); ElementManager.getElementManager().getARandomRect(); ElementManager.getElementManager().getARandomRect(); MyJFrame.myp.repaint(); MyJFrame.gameOverFlag=false; refreshBest(); } }); jb2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ refreshBest(); File f=new File("LASTRECORD"); if(f.exists()){ f.delete(); } System.exit(0); } }); jl.add(jb1); jl.add(jb2); MyJFrame.myp.add(jl); jl.validate(); } public void gameSuccess() { JPanel jl=new GameSuccessJPanel(MyJFrame.myp.getWidth(),MyJFrame.myp.getHeight()); jl.setOpaque(false); jl.setBounds(0, 0, 700, 700); JButton jb1=new JButton("Continue"); Font font=new Font("TimesRoman",Font.BOLD,30); jb1.setOpaque(false); jb1.setFont(font); JButton jb2=new JButton("Close"); jb2.setSize(jb1.getSize()); jb2.setOpaque(false); jb2.setFont(font); jb1.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ MyJFrame.myp.remove(jl); MyJFrame.myp.validate(); } }); jb2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ refreshBest(); System.exit(0); } }); jl.add(jb1); jl.add(jb2); MyJFrame.myp.add(jl); jl.validate(); } public boolean aMoveAble() { MyJFrame.CheckMode=true; MyJFrame.change=false; moveLeft(true); moveRight(true); moveDown(true); moveUp(true); MyJFrame.CheckMode=false; if(MyJFrame.change==true){ return true; }else{ return false; } } private void rectMove() { // TODO Auto-generated method stub if(MyJFrame.isUp) { moveUp(true); if(MyJFrame.change==true){ ElementManager.getElementManager().getARandomRect(); //saveTheStep(); } MyJFrame.isUp = false; } else if(MyJFrame.isDown) { moveDown(true); if(MyJFrame.change==true){ ElementManager.getElementManager().getARandomRect(); //saveTheStep(); } MyJFrame.isDown = false; } else if(MyJFrame.isLeft) { moveLeft(true); if(MyJFrame.change==true){ ElementManager.getElementManager().getARandomRect(); //saveTheStep(); } MyJFrame.isLeft = false; } else if(MyJFrame.isRight) { moveRight(true); if(MyJFrame.change==true){ ElementManager.getElementManager().getARandomRect(); //saveTheStep(); } MyJFrame.isRight = false; } } public void moveRight(boolean flag) { // TODO Auto-generated method stub clearList(ElementManager.getElementManager().rectNext); for(int i=0;i<4;i++){ int k=3; for(int j=3;j>-1;j--){ if(ElementManager.getElementManager().rectObj[i][j]!=null){ ElementManager.getElementManager().rectNext[i][k--]=new RectObject(ElementManager.getElementManager().rectObj[i][j]); } } } for(int i=0;i<4 && flag;i++){ for(int j=3;j>0;j--){ if(ElementManager.getElementManager().rectNext[i][j]!=null && ElementManager.getElementManager().rectNext[i][j-1]!=null && ElementManager.getElementManager().rectNext[i][j].value==ElementManager.getElementManager().rectNext[i][j-1].value){ ElementManager.getElementManager().rectNext[i][j].value*=2; if(MyJFrame.CheckMode==false){ int sum=Integer.parseInt(MyJFrame.scoreLabel.getText()); sum+=ElementManager.getElementManager().rectNext[i][j].value; MyJFrame.scoreLabel.setText(""+sum); } ElementManager.getElementManager().rectNext[i][j-1]=null; j--; } } } if(isChange()){ if(MyJFrame.CheckMode==false){ copySet(ElementManager.getElementManager().rectObj,ElementManager.getElementManager().rectNext); moveRight(false); } MyJFrame.change=true; }else{ } } public void moveLeft(boolean flag) { // TODO Auto-generated method stub clearList(ElementManager.getElementManager().rectNext); for(int i=0;i<4;i++){ int k=0; for(int j=0;j<4;j++){ if(ElementManager.getElementManager().rectObj[i][j]!=null){ ElementManager.getElementManager().rectNext[i][k++]=new RectObject(ElementManager.getElementManager().rectObj[i][j]); } } } for(int i=0;i<4 && flag;i++){ for(int j=0;j<3;j++){ if(ElementManager.getElementManager().rectNext[i][j]!=null && ElementManager.getElementManager().rectNext[i][j+1]!=null && ElementManager.getElementManager().rectNext[i][j].value==ElementManager.getElementManager().rectNext[i][j+1].value){ ElementManager.getElementManager().rectNext[i][j].value*=2; if(MyJFrame.CheckMode==false){ int sum=Integer.parseInt(MyJFrame.scoreLabel.getText()); sum+=ElementManager.getElementManager().rectNext[i][j].value; MyJFrame.scoreLabel.setText(""+sum); } ElementManager.getElementManager().rectNext[i][j+1]=null; j++; } } } if(isChange()){ if(MyJFrame.CheckMode==false){ copySet(ElementManager.getElementManager().rectObj,ElementManager.getElementManager().rectNext); moveLeft(false); } MyJFrame.change=true; }else{ } } public void moveDown(boolean flag) { // TODO Auto-generated method stub clearList(ElementManager.getElementManager().rectNext); for(int j=0;j<4;j++){ int k=3; for(int i=3;i>-1;i--){ if(ElementManager.getElementManager().rectObj[i][j]!=null){ ElementManager.getElementManager().rectNext[k--][j]=new RectObject(ElementManager.getElementManager().rectObj[i][j]); } } } for(int j=0;j<4 && flag;j++){ for(int i=3;i>0;i--){ if(ElementManager.getElementManager().rectNext[i][j]!=null && ElementManager.getElementManager().rectNext[i-1][j]!=null && ElementManager.getElementManager().rectNext[i][j].value==ElementManager.getElementManager().rectNext[i-1][j].value){ ElementManager.getElementManager().rectNext[i][j].value*=2; if(MyJFrame.CheckMode==false){ int sum=Integer.parseInt(MyJFrame.scoreLabel.getText()); sum+=ElementManager.getElementManager().rectNext[i][j].value; MyJFrame.scoreLabel.setText(""+sum); } ElementManager.getElementManager().rectNext[i-1][j]=null; i--; } } } if(isChange()){ if(MyJFrame.CheckMode==false){ copySet(ElementManager.getElementManager().rectObj,ElementManager.getElementManager().rectNext); moveDown(false); } MyJFrame.change=true; }else{ } } public void moveUp(boolean flag) { // TODO Auto-generated method stub clearList(ElementManager.getElementManager().rectNext); for(int j=0;j<4;j++){ int k=0; for(int i=0;i<4;i++){ if(ElementManager.getElementManager().rectObj[i][j]!=null){ ElementManager.getElementManager().rectNext[k++][j]=new RectObject(ElementManager.getElementManager().rectObj[i][j]); } } } for(int j=0;j<4 && flag;j++){ for(int i=0;i<3;i++){ if(ElementManager.getElementManager().rectNext[i][j]!=null && ElementManager.getElementManager().rectNext[i+1][j]!=null && ElementManager.getElementManager().rectNext[i][j].value==ElementManager.getElementManager().rectNext[i+1][j].value){ ElementManager.getElementManager().rectNext[i][j].value*=2; if(MyJFrame.CheckMode==false){ int sum=Integer.parseInt(MyJFrame.scoreLabel.getText()); sum+=ElementManager.getElementManager().rectNext[i][j].value; MyJFrame.scoreLabel.setText(""+sum); } ElementManager.getElementManager().rectNext[i+1][j]=null; i++; } } } if(isChange()){ if(MyJFrame.CheckMode==false){ copySet(ElementManager.getElementManager().rectObj,ElementManager.getElementManager().rectNext); moveUp(false); } MyJFrame.change=true; }else{ } } public boolean isChange() { for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ if(ElementManager.getElementManager().rectObj[i][j]!=null && ElementManager.getElementManager().rectNext[i][j]!=null && !ElementManager.getElementManager().rectObj[i][j].equals(ElementManager.getElementManager().rectNext[i][j])){ return true; } if(ElementManager.getElementManager().rectObj[i][j]!=null && ElementManager.getElementManager().rectNext[i][j]==null){ return true; } if(ElementManager.getElementManager().rectObj[i][j]==null && ElementManager.getElementManager().rectNext[i][j]!=null){ return true; } } } return false; } public void copySet(RectObject[][] dst, RectObject[][] src) { // TODO Auto-generated method stub for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ dst[i][j]=src[i][j]; } } } public void clearList(RectObject[][] s){ for(int i=0;i<s.length;i++){ for(int j=0;j<s[i].length;j++){ s[i][j]=null; } } } public static void refreshBest() { try { int best=0; File f=new File("BestRecord"); RandomAccessFile file; if(f.exists()){ file=new RandomAccessFile(f,"rw"); best=file.readInt(); file.seek(0); }else{ file=new RandomAccessFile(f,"rw"); } //System.out.println("The Best score is "+best); int cur=Integer.parseInt(MyJFrame.scoreLabel.getText()); if(cur>best){ file.writeInt(cur); } file.close(); } catch (FileNotFoundException e1) { e1.printStackTrace(); }catch(IOException e2){ e2.printStackTrace(); } } public static void saveRecord(){ try{ RandomAccessFile file=new RandomAccessFile(new File("LASTRECORD"),"rw"); int score=Integer.parseInt(MyJFrame.scoreLabel.getText()); file.writeInt(score); for(int i=0;i<4;i++){ for(int j=0;j<4;j++){ if(ElementManager.getElementManager().rectObj[i][j]!=null){ file.writeInt(ElementManager.getElementManager().rectObj[i][j].value); }else{ file.writeInt(0); } } } }catch(FileNotFoundException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); } } }
package game;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JPanel;
public class GameSuccessJPanel extends JPanel {
public GameSuccessJPanel(int w,int h){
setSize(w,h);
//setOpaque(false);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Font font=new Font("TimesRoman",Font.BOLD,80);
g.setFont(font);
FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
int width=fm.stringWidth("Success!");
int height=fm.getHeight();
g.setColor(new Color(255,0,0));
g.drawString("Success!", getWidth()/2-width/2, getHeight()/2-height/2);
}
}
package game;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Toolkit;
import javax.swing.JPanel;
import manager.ElementManager;
public class My2048JPanel extends JPanel implements Runnable{
public static final int WID=150,SP=10;
private int[] xindex={SP,2*SP+WID,3*SP+2*WID,4*SP+3*WID};
private int[] yindex={SP,2*SP+WID,3*SP+2*WID,4*SP+3*WID};
public void paintComponent(Graphics g){
//background
super.paintComponent(g);
for(int i=0;i<xindex.length;i++){
for(int j=0;j<yindex.length;j++){
g.setColor(Color.WHITE);
g.drawRoundRect(xindex[i], yindex[j], WID, WID, WID/5, WID/5);
g.setColor(new Color(197,183,129));
g.fillRoundRect(xindex[i], yindex[j], WID, WID, WID/5, WID/5);
}
}
//paint rectangle
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(ElementManager.getElementManager().rectObj[i][j]!=null){
g.setColor(Color.WHITE);
g.drawRoundRect(yindex[j], xindex[i], WID, WID, WID/5, WID/5);
if(ElementManager.getElementManager().rectObj[i][j].value<128){
g.setColor((Color)MyJFrame.cmap.get(ElementManager.getElementManager().rectObj[i][j].value));
}else{
g.setColor((Color)MyJFrame.cmap.get(128));
}
g.fillRoundRect(yindex[j], xindex[i], WID, WID, WID/5, WID/5);
g.setColor(Color.BLACK);
Font font=new Font("TimesRoman",Font.BOLD,50);
g.setFont(font);
FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
int len=fm.stringWidth(""+ElementManager.getElementManager().rectObj[i][j].value);
int hg=fm.getHeight();
g.drawString(""+ElementManager.getElementManager().rectObj[i][j].value, yindex[j]+WID/2-len/2, xindex[i]+WID/2+hg/4);
if(ElementManager.getElementManager().rectObj[i][j].value==2048 && MyJFrame.successFlag==false){
MyJFrame.successFlag=true;
}
}
}
}
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.repaint();
}
}
}
package game;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import element.RectObject;
import manager.ElementManager;
public class MyJFrame extends JFrame {
public static final int UP=0,DOWN=1,LEFT=2,RIGHT=3;
public static boolean isLeft = false;
public static boolean isRight = false;
public static boolean isUp = false;
public static boolean isDown = false;
public static boolean isReset = false;
public static boolean isGoBack = false;
public static final int WID=150,SP=10;
public int scores=0;
public static JLabel scoreLabel;
public static boolean change,CheckMode=false,gameOverFlag=false,successFlag=false;
public int[] label={2,4,8,16,32,64,128};
public Color[] clo={
new Color(200,200,200),new Color(228,228,160),new Color(214,163,92),
new Color(234,124,72),new Color(240,84,77),new Color(255,68,53),new Color(200,200,64)
};
public static Map cmap=new HashMap();
public static My2048JPanel myp;
public static LinkedList saveList=new LinkedList();
private JButton goBackButton;
public MyJFrame() {
//saveTheStep();
for(int i=0;i<7;i++){
cmap.put(label[i], clo[i]);
}
init();
}
KeyListener kl=new KeyListener(){
public void keyPressed(KeyEvent e){
saveTheStep();
goBackButton.setVisible(true);
if(gameOverFlag==true){
return;
}
int key=e.getKeyCode();
switch(key){
case KeyEvent.VK_UP:
change=false;
isUp = true;
break;
case KeyEvent.VK_DOWN:
change=false;
isDown = true;
break;
case KeyEvent.VK_LEFT:
change=false;
isLeft = true;
break;
case KeyEvent.VK_RIGHT:
change=false;
isRight = true;
break;
}
//saveTheStep();
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
};
public class goBackListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if(saveList.size()==0){
goBackButton.setVisible(false);
return;
}
isGoBack = true;
repaint();
}
}
public class resetListener implements ActionListener{
public void actionPerformed(ActionEvent e){
isReset = true;
repaint();
}
}
public void saveTheStep(){
if(saveList.size()<20){
ArrayList arr=new ArrayList();
int score=Integer.parseInt(scoreLabel.getText());
arr.add(score);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(ElementManager.getElementManager().rectObj[i][j]!=null){
arr.add(ElementManager.getElementManager().rectObj[i][j].value);
}else{
arr.add(0);
}
}
}
saveList.addLast(arr);
}else{
saveList.removeFirst();
saveTheStep();
}
}
public void init() {
// TODO Auto-generated method stub
Container cp=getContentPane();
cp.setLayout(null);
cp.setFocusable(true);
cp.addKeyListener(kl);
Font font=new Font("TimesNewman",Font.BOLD,30);
JLabel sl=new JLabel();
sl.setLayout(new GridLayout(2,1));
JLabel sllb=new JLabel("Scores");
sllb.setFont(font);
scoreLabel=new JLabel("0");
scoreLabel.setFont(font);
sl.add(sllb);
sl.add(scoreLabel);
int best=0;
try{
File file=new File("BestRecord");
if(file.exists()){
RandomAccessFile f=new RandomAccessFile(file,"rw");
best=f.readInt();
f.close();
}
}catch(FileNotFoundException e){
best=0;
e.printStackTrace();
}catch(IOException e){
best=0;
e.printStackTrace();
}
JLabel bsl=new JLabel();
bsl.setLayout(new GridLayout(2,1));
JLabel jl=new JLabel("Best");
jl.setFont(font);
JLabel jl1=new JLabel(""+best);
jl1.setFont(font);
bsl.add(jl);
bsl.add(jl1);
myp=new My2048JPanel();
goBackButton=new JButton("UNDO");
goBackButton.setFont(font);
goBackButton.addActionListener(new goBackListener());
goBackButton.addKeyListener(kl);
JButton jb=new JButton("RESET");
jb.setFont(font);
jb.addActionListener(new resetListener());
jb.addKeyListener(kl);
sl.setBounds(500,20,200,80);
bsl.setBounds(300,20,200,80);
myp.setBounds(0,90,700,700);
goBackButton.setBounds(700,250,150,60);
jb.setBounds(700,450,150,60);
cp.add(sl);
cp.add(bsl);
cp.add(myp);
cp.add(goBackButton);
cp.add(jb);
File f=new File("LASTRECORD");
if(f.exists()){
try{
RandomAccessFile file=new RandomAccessFile(f,"rw");
int num=file.readInt();
scoreLabel.setText(""+num);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
num=file.readInt();
if(num!=0){
ElementManager.getElementManager().rectObj[i][j]=new RectObject();
ElementManager.getElementManager().rectObj[i][j].value=num;
}
}
}
file.close();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}else{
ElementManager.getElementManager().getARandomRect();
ElementManager.getElementManager().getARandomRect();
}
}
public void gameShow() {
this.setVisible(true);
new Thread((Runnable)myp).start();
new GameRunThread().start();
}
}
package game;
public class TzfeStart {
public static MyJFrame jf;
public static void main(String[] args) {
jf = new MyJFrame();
jf.gameShow();
}
}
package manager;
import java.util.ArrayList;
import java.util.Random;
import element.Point;
import element.RectObject;
//單例模式
public class ElementManager {
private static ElementManager elementManager = null;
public static RectObject rectObj[][] = null;
public RectObject rectNext[][] = null;
private ElementManager() {
rectObj = new RectObject[4][4];
rectNext = new RectObject[4][4];
}
public static synchronized ElementManager getElementManager() {
if(elementManager==null) {
elementManager = new ElementManager();
}
return elementManager;
}
public void getARandomRect() {
ArrayList list = new ArrayList();
for(int i = 0;i<4;i++) {
for(int j = 0;j<4;j++)
{
if(rectObj[i][j]==null)
{
list.add(new Point(i,j));
//System.out.println(list.get(0));
}
}
}
Random rand=new Random();
int index=rand.nextInt(list.size());
Point loc=(Point) list.get(index);
index=rand.nextInt(2);
ElementManager.getElementManager().rectObj[loc.x][loc.y]=new RectObject();
if(index==1){
ElementManager.getElementManager().rectObj[loc.x][loc.y].value=4;
}else{
ElementManager.getElementManager().rectObj[loc.x][loc.y].value=2;
}
}
}
package element; public class Point { public int x; public int y; public Point(int x, int y) { this.x = x; this.y = y; } }
package element;
public class RectObject {
public int value;
public RectObject() {
value = 0;
}
public RectObject(RectObject obj) {
this.value = obj.value;
}
@Override
public boolean equals(Object iobj) {
// TODO Auto-generated method stub
RectObject obj = (RectObject)iobj;
if(this.value == obj.value)
{
return true;
}
return false;
}
}
這種遊戲可能不適合用這種方式程式設計,還要繼續學習。