Javaはヘビを食いしん坊にするゲームを編纂する


ヘビを食べるゲームのルール:ヘビが卵を食べると、ヘビの体が長くなり、移動中に自分と壁にぶつかることができません.プロジェクト構築:Snake(蛇):Snakeにはint x、int yがあるウィンドウのx、y点の位置とdirection運動方向の3つの属性がある.移動(Dir dir))と卵(eat(Box))の2つの方法があります.Box(卵):Boxにはint x、int yがあるウィンドウのx、y点の位置があり、boolean live属性設定が食べられるかどうかがあります.
Snode(蛇の尾):int x,int yがあるウィンドウのx,y点の位置
Yard(芝生):Yardにはint width、int height幅と高さの属性があります.
Dir(方向):蛇の移動には4つの方向、下、左、右があり、列挙タイプは有限変数を定義するタイプであるため、列挙タイプを定義することができる.プロジェクト分析:YardとSnakeは重合関係であり、一対一である.BoxとYardは組み合わせ関係であり、一対一でもある.SnakeがBoxを食べるのは関連関係であり,SnakeとSnodeは組合せ関係であり,一対の多関係である.
YardとBoxはコンビネーション関係であり、YardでBOXのsetLive()メソッドを呼び出すことができ、BOXカラーとヘビは関連関係であり、関連関係ではBOXのsetメソッドを呼び出してBoxの属性値を変更することができるが、ソフトウェアプログラミングの考え方に合致せず、関連関係については観察者モードを用いて関連関係オブジェクトの属性値を変更するのが一般的である.だから観察者モードを使って卵を作ることができて、蛇が彩卵を食べる时に通知を出して、それからBoxは自动的に彩卵を作ることができて、この方式はYardの中のpaintComponentの方法で彩卵を得る机能を减らして、Yardの中のpaintComponentの方法は多すぎる任务を引き受けて、横線を描くだけではなくて、縦線を描くこともできて、彩卵を描くこともできて、また卵を得ることができます!これは比較的重いタスク型の方法です.だから観察者モードを使って、蛇は卵を食べた後、Boxに通知を出して、Boxに彩卵の新しい座標点を産生させます;
snakeにSerializableインタフェースを実装し、閉じるボタンをクリックしてヘビを貪る運転状態をファイルに保存し、再起動するとファイルから前回ヘビを貪る状態を取得します.box.java
import java.util.Observable;
import java.util.Observer;
import java.util.Random;
public class Box implements Observer{
	/**********Begin:    :    :End******************/
    private int x;
    private int y;
    private boolean live;
   /*********End:    ******************/
    /**********Begin:      :**********************/
    private Box(){
    	Random random=new Random();
    	this.live=true;
    	//Box      10   ,             
    	x = random.nextInt(80)*10; 
		y = random.nextInt(60)*10;
    }
    /*******Begin:set/get  *****************************************/
	public int getX() {return x;}
	public void setX(int x) {this.x = x;}
	public int getY() {return y;}
	public void setY(int y) {this.y = y;}
	public boolean isLive() {return live;}
	public void setLive(boolean live) {this.live = live;}

	/*******End:set/get  *****************************************/
	/**********************Begin:     ,               **********/
	
	/**********************End:     ,               *****************/
	/************* Begin:  toString   *******************************************************/
	public String toString() {
		// hashcode        
		return  String.valueOf(Integer.toHexString(hashCode())).toUpperCase();
	}
	/************* End:  toString   **********************************************************/
	private static  Box box;
	public static Box takeBox(){
		if(box==null){
		    synchronized(Object.class){
			if(box==null){
			    box=new Box();
			}
		    }
		}
		return box;
	}
	//     ,      ,       。
	public void update(Observable o, Object obj) {
		if(live==false){
			Random random=new Random();
			this.x=random.nextInt(80)*10; 
			this.y=random.nextInt(60)*10;
			this.setLive(true);
		}
	}
}

dir.java移動の方向
public enum Dir {
	LEFT,RIGHT,UP,DOWN,STOP;
}
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Observable;
public class Snake extends Observable implements Serializable{
	/**********Begin:    ******************/
	private int x=50;
	private int y=50;
    private Dir dir;    
	private ArrayList<Snode> snodeBox=new ArrayList<Snode>();
	private boolean run;
	/**********End:    ******************/
	/**********Begin:      **********************/
	public Snake() {
		//         
		this.dir=Dir.RIGHT;
		this.run=true;
		snodeBox.add(new Snode());
	}
	/**********End:      **********************/
   /**********Begin :  set/get  *******************/
	public int getX() {return x;}
	public void setX(int x) {this.x = x;}
	public int getY() {return y;}
	public void setY(int y) {this.y = y;}
	public ArrayList<Snode> getSnodeBox() {return snodeBox;}
	public void setSnodeBox(ArrayList<Snode> snodeBox) {this.snodeBox = snodeBox;}
	public Dir getDir() {return dir;}
	public void setDir(Dir dir) {this.dir = dir;}
	public boolean isRun() {
		return run;
	}
	public void setRun(boolean run) {
		this.run = run;
	}
   /************End:  set/get  ******************************/
	
	
	
	/***********Begin:       x、y  *********************/
	public void move(Dir dir){
		switch (dir) {
		case UP:
			y-=10;
			break;
		case DOWN:
			y+=10;
			break;
		case LEFT:
			x-=10;
			break;
		case RIGHT:
			x+=10;
			break;
		}
		//                  
		for (int j = snodeBox.size() - 1; j > 0; j--) {
			snodeBox.get(j).setX(snodeBox.get(j - 1).getX()); // 2  1 2
			snodeBox.get(j).setY(snodeBox.get(j - 1).getY());
		}
		//           
		snodeBox.get(0).setX(this.x);
		snodeBox.get(0).setY(this.y);
	}
	/***********End:       x、y  *********************/
	 /*******Begin:    :     ,                 :End**********/
	public void eat(Box box){
		Snode snode = new Snode();
		snodeBox.add(snode);
		setChanged();
		addObserver(box);
		notifyObservers();
	}
}

ヘビのノードクラスsonde.java
import java.io.Serializable;

public class Snode implements Serializable {
	private int x;
	private int y;
	/*****Begin:  set/get  **********************/
	public int getX() {return x;}
	public void setX(int x) {this.x = x;}
	public int getY() {return y;}
	public void setY(int y) {this.y = y;}
	/*****End:  set/get  **********************/
}

定数クラス
public class Variables {
	public static final int WIDTH=800;
	public static final int HEIGHT=600;
}

yard類は再描画と蛇の移動が2つの方法であるため、2つのスレッドの中に置くべきで、1つのスレッドは再描画を担当し、1つのスレッドは蛇を移動することを担当し、このようにソフトウェアエンジニアリングのプログラミング思想に合致する.フェアロックを使用して、スレッドとヘビを再描画してスレッドを「1人1回」移動させることができます.
package snake;
import java.awt.Color;
import java.awt.Graphics;
import java.io.File;
import java.util.concurrent.locks.ReentrantLock;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Yard extends JPanel {
	private Snake snake;
	private Box box;
	public Yard(final Snake snake) {
		box = Box.takeBox();
		this.snake = snake;
		this.setSize(Variables.WIDTH, Variables.HEIGHT);
		this.setBackground(Color.white);
		final ReentrantLock lock = new ReentrantLock(true);
		/********** Begin:          repaint   **************************/
		new Thread(new Runnable() {
			public void run() {
				//     
				try {
					while (true) {
						Thread.sleep(5);
						while (snake.isRun() == true) {
							lock.lock();
							Thread.sleep(30);
							repaint();
							lock.unlock();
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		/*************End:    :   *************************************/
		/*************Begin:      *******/
		/**
       ,               ,                                Thread.sleep(5), snake.isRun()       ,        snake.isRun()            ;            Thread.sleep(5)   ,  snake.isRun()       ,     while    snake.isRun()     ;		
*/
		new Thread(new Runnable() {
			public void run() {
				try {
				while (true) {
					Thread.sleep(5);
					while (snake.isRun() == true) {
							lock.lock();
							Thread.sleep(30);
							snake.move(snake.getDir());
							lock.unlock();
					}
				}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		new Thread(new Runnable() {
			public void run() {
				try {
					while(true){
						Thread.sleep(2);
						//          4   
						for (int j = 5;j<snake.getSnodeBox().size();j++) {
							Snode head=snake.getSnodeBox().get(0);
							//         , Snake move  ,                 ,
							//                   ,     if   ;              
							Thread.sleep(2);
							Snode snode=snake.getSnodeBox().get(j);
							//          ,         ,       XY        ,      5     
							if( Math.abs(head.getX()-snode.getX())<=5&&Math.abs(head.getY()-snode.getY())<=5){
								 snake.setRun(false);
								 Thread.sleep(5);
								 int option = JOptionPane.showConfirmDialog(Yard.this,"    ,    ?"); 
								switch (option) {
								case JOptionPane.OK_OPTION:
									snake.setRun(true);
									break;
								case JOptionPane.NO_OPTION:
									new File("D:/snake.data").delete();
									break;
								}
							
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		 /***********End:      ************************************************/
	}

	/****************Begin:  sankeMove  ************************************/
	public void snakeMove(Dir dir) {
		switch (dir) {
		case UP:
			if (snake.getDir() != Dir.DOWN) {
				snake.setDir(Dir.UP);
			} 
			break;
		case DOWN:
			if (snake.getDir() != Dir.UP) {
				snake.setDir(Dir.DOWN);
			}
			break;
		case LEFT:
			if (snake.getDir() != Dir.RIGHT) {
				snake.setDir(Dir.LEFT);
			}
			break;
		case RIGHT:
			if (snake.getDir() != Dir.LEFT) {
			snake.setDir(Dir.RIGHT);
			}
			break;
		case STOP:
			snake.setRun((snake.isRun() == true) ? false : true);
			break;
		}
		//snake.move(snake.getDir());
	}
	/****************Begin:  sankeMove  ************************************/
	
	/*************** Begin:  paintComponet  : new Yard() ,      ***************/
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		//    
		for (int i = 0; i <= (Variables.HEIGHT / 10); i++) {
			g.drawLine(0, 10 * i, Variables.WIDTH, 10 * i);
		}
		//    
		for (int i = 0; i <= Variables.WIDTH / 10; i++) {
			g.drawLine(10 * i, 0, 10 * i, Variables.HEIGHT);
		}
		//            
		for (int i = 0; i < snake.getSnodeBox().size(); i++) {
			g.fillOval(snake.getSnodeBox().get(i).getX(), snake.getSnodeBox().get(i).getY(), 10, 10);
		}
		//   
		// box = Box.takeBox();
		g.setColor(Color.pink);
		g.fillOval(box.getX(), box.getY(), 10, 10);
		//     
		if (box.getX() == snake.getX() && box.getY() == snake.getY()) {
			box.setLive(false);
			snake.eat(box);
		}
	}
	/***************** End:  paintComponet  : new Yard() ,      *******************************/
}

main.java
package snake;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.swing.JFrame;
public class Main {
	public static void main(String[] args) {
		try {
		JFrame win = new JFrame("   ");
		win.setSize(Variables.WIDTH, Variables.HEIGHT);
		final File file =new File("D:/snake.data");
		Object data=null;
		if(file.length()!=0){
		    final ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
		    data = oin.readObject();
		    oin.close();
		}
		final Snake snake =(data==null)?new Snake():(Snake)data;
		 /************Begin:         End*********************************************/
		win.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent event) {
			  try {
				ObjectOutputStream ow=new ObjectOutputStream(new FileOutputStream(file));
				ow.writeObject(snake);
				ow.close();
			    } catch (Exception e) {
				e.printStackTrace();
			    }
			    System.exit(0);
			}
		});
		 /************Begin:         *********************************************/
		final Yard yard = new Yard(snake);
		  /***********************Begin:   、 、 、     *******************************/
		win.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				switch (e.getKeyCode()) {
				//   
				case KeyEvent.VK_UP:
					yard.snakeMove(Dir.UP);
					break;
					//   
				case KeyEvent.VK_DOWN:
					 yard.snakeMove(Dir.DOWN);
					break;
					//   
				case KeyEvent.VK_LEFT:
					yard.snakeMove(Dir.LEFT);
					break;
					 //   
				case KeyEvent.VK_RIGHT:
					yard.snakeMove(Dir.RIGHT);
					break;
				case KeyEvent.VK_SPACE:
					yard.snakeMove(Dir.STOP);
					break;
				}
			}
		});
		/*********************End:   、 、 、     *******************************/
		win.setLocationRelativeTo(null);
		win.add(yard);
		win.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}