Java ,實現貪喫蛇小遊戲

初學Java GUI編程。所以做個貪喫蛇遊戲來練習一下學習的東西。

 

對於Java這種面向對象的編程語言來說,在編寫程序之前一定要做相應的分析,要分析需要研究哪些對象,這些對象中會有哪些屬性和方法。

 

對與貪喫蛇這個小遊戲,會包含這幾種對象: 蛇、食物、遊戲控制器、遊戲面板。

下面我們就要分析在這些對象中都包含哪些屬性和方法。

首先,先分析蛇這個對象:

         蛇會具有的屬性爲: 蛇的身體,蛇身體的顏色,蛇身體的長度,蛇的生命,蛇的運動方向

         在貪喫蛇這個小遊戲中,是通過蛇在各個方向的運動尋找食物喫然後增長身體來保證遊戲的正常進行的。

         這時在蛇這個對象中就會存在這樣幾個方法:蛇移動的方法,蛇喫東西的方法

然後分析食物這個對象:

         食物會有顏色和位置這兩個屬性,和生成食物的方法

初步的代碼規劃會這這個樣子:

//Snake.java
package org.sysit.game.snake;

import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

public class Snake {
	private int length;
	private Color color;
	private List<Point> body = new ArrayList();
	private boolean life = true;	

	/**
	 * 蛇運動方向
	 * @author ZHANGBING
	 *
	 */
	enum dir{
		UP, RIGHT, DOWN, LEFT
	};
	private dir snakeDir;
	

	/**
	 * 初始化蛇
	 * @param length 蛇身長度
	 */
	public Snake(int length) {
	}
	
	
	public void move(){
	}
	/**
	 * 判斷蛇是否喫到食物
	 * @param head	蛇頭
	 * @return
	 */
	public boolean isSnakeEatFood(Point head){
		return true;
		
	}
}


//Food.java
package org.sysit.game.snake;

import java.awt.Color;
import java.awt.Point;

public class Food {

	private Color color;
	private Point location;

	/**
	 * 生成食物的位置
	 * @param snake
	 * @return	返回Point
	 */
	public Point setLocation(Snake snake) {
		return null;
	}

}

接下來就是向各個方法中添加實現的代碼了:

在蛇這個對象中,首先應該先將把蛇初始化的代碼完成,在這裏,我是以點的形式將蛇的身體的每個一節存入到蛇身體的List中

	/**
	 * 初始化蛇
	 * @param length 蛇身長度
	 */
	public Snake(int length) {
		
		this.length = length;
		this.color = Color.YELLOW;
		for(int i = length ; i > 0 ; i--){
			body.add(new Point(0, i-1));
		}
		snakeDir = dir.RIGHT;
	
	}

接下來最核心的應該算是蛇移動的方法了,我的代碼還有很大一部分還需改進,我的方法是將多個操作合併到一個方法中了,大家和自己進行修改

	public void move(){
		Point head = new Point(body.get(0).x, body.get(0).y);
		switch(snakeDir){
		case UP:
			head.x --;
			break;
		case DOWN:
			head.x ++;
			break;
		case LEFT:
			head.y --;
			break;
		case RIGHT:
			head.y ++;
			break;
		}
		int canvas_width = SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH - 2;
		int canvas_height = SysConfig.CANVAS_HEIGHT/ SysConfig.STONE_HEIGHT - 2;
		if( head.x < 0  ||  head.x > canvas_height-1 ||  head.y < 0  ||  head.y > canvas_width-1 ){
			life = false;	//蛇die
			JOptionPane.showMessageDialog(null, "遊戲結束");
			return;
		} else {
			body.add(0, head);
			if(isSnakeEatFood(head)){
				//沒有喫到食物
				body.remove(body.size()-1);
			} else {
				getFood().setLocation(this);
				setScore(getScore()+10);
			}
			for(int i = 1 ; i <= body.size()-1 ; i++){
				Point point = body.get(i);
				if(point.x == head.x && point.y == head.y){
					life = false;
					JOptionPane.showMessageDialog(null, "撞到自己啦~遊戲結束");
					//System.exit(0);
					return;
				}
				
			}
		}
	}
/**
	 * 判斷蛇是否喫到食物
	 * @param head	蛇頭
	 * @return
	 */
	public boolean isSnakeEatFood(Point head){
		
		if(this.food.getLocation().x == head.x && this.food.getLocation().y == head.y)
			return false;
		return true;
		
	}

然後在食物這個對象中,我們需要實現的只有聲稱食物的方法:

	/**
	 * 生成食物的位置
	 * @param snake
	 * @return	返回Point
	 */
	public Point setLocation(Snake snake) {
		location = new Point();
		
		int canvas_width = SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH - 2;
		int canvas_height = SysConfig.CANVAS_HEIGHT/ SysConfig.STONE_HEIGHT - 2;
		int temp = (int) (Math.random() * 1000) ;
	
		int rand = temp% (canvas_width * canvas_height - snake.getBody().size()) + 1;
		//int rand = temp% 50 + 1;
		boolean flag ;
		for(int i = 0 ; i < canvas_height ; i++){
			for(int j = 0 ; j < canvas_width ; j++){
				flag = true;
				for(Point point : snake.getBody()){
					//System.out.println("point: ("+ point.x + "," + point.y + ")");
					if(i == point.x && j == point.y){
						flag = false;
						break;
					}
				}
				if(flag){
					rand--;
					if(rand == 0){
						location.x = i;
						location.y = j;
						return location;
					}
				}
			}
		}
		return null;
	}


其他剩下來的操作就都是一些將蛇和食物聯繫起來的代碼:

//GameController.java
package org.sysit.game.snake;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JTextField;
import javax.swing.Timer;

public class GameController {
	

	private Ground ground;
	private Snake snake ;
	private Food food ;
	private Timer timer;
	private boolean pause = false;
	private int score = 0;
	private JTextField txtScore;

	
	
	public JTextField getTxtScore() {
		return txtScore;
	}
	public void setTxtScore(JTextField txtScore) {
		this.txtScore = txtScore;
	}
	public GameController(final Snake snake, Food food, final Ground ground) {
		this.snake = snake;
		this.food = food;
		this.ground = ground;
		timer = new Timer(200, new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(snake.isLife()){
					snake.move();
					if(snake.isLife()){
						score = snake.getScore();
						getTxtScore().setText(score + "");
						ground.repaint();
					} else {
						timer.stop();
					}
				}
			}
		});
	}
	/**
	 * 遊戲初始化
	 */
	public void init(){
		getTxtScore().setText("0");
		
	}
	
	/**
	 * 開始遊戲
	 */
	public void startGame(){
		init();
		timer.start();
		ground.requestFocus();
	}
	
	/**
	 * 暫停遊戲
	 */
	public void pauseGame() {
		if(!pause){
			timer.stop();
			pause = true;
		}
		ground.requestFocus();
	}

	/**
	 * 繼續遊戲
	 */
	public void resumeGame() {
		if(pause){
			timer.restart();
			pause = false;
		}
		ground.requestFocus();
	}
	
	
	public boolean isPause() {
		return pause;
	}

	public void setPause(boolean pause) {
		this.pause = pause;
	}
}

//Ground.java
package org.sysit.game.snake;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.List;

import org.sysit.game.snake.Snake.dir;

public class Ground extends Canvas {

	private Snake snake;
	private Food food;
	private Image iBuffer;
	
	public Ground() {
		setBounds(0, 0, SysConfig.CANVAS_WIDTH, SysConfig.CANVAS_HEIGHT);
		setBackground(Color.BLACK);
		addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				int keyCode = e.getKeyCode();
				switch(keyCode){
				case KeyEvent.VK_UP:
					snake.setSnakeDir(dir.UP);
					break;
				case KeyEvent.VK_DOWN:
					snake.setSnakeDir(dir.DOWN);
					break;
				case KeyEvent.VK_LEFT:
					snake.setSnakeDir(dir.LEFT);
					break;
				case KeyEvent.VK_RIGHT:
					snake.setSnakeDir(dir.RIGHT);
					break;
				}
			
			}
		
		});
	}

	public Snake getSnake() {
		return snake;
	}

	public void setSnake(Snake snake) {
		this.snake = snake;
	}

	public Food getFood() {
		return food;
	}

	public void setFood(Food food) {
		this.food = food;
	}
	
	/**
	 * 雙緩衝技術解決屏幕閃爍問題
	 */
	@Override
	public void update(Graphics g) {
		if(iBuffer == null){
			iBuffer = createImage(this.getSize().width, this.getSize().height);
			
		}
		//if(gBuffer == null){
		Graphics gBuffer = iBuffer.getGraphics();
		//}
		gBuffer.setColor(getBackground());
		gBuffer.fillRect(0, 0, this.getSize().width, this.getSize().height);
		paint(gBuffer);
		gBuffer.dispose();
		g.drawImage(iBuffer, 0, 0, this);
	}
	
	/**
	 * 畫牆
	 */
	public void drawWall(Graphics g) {

		g.setColor(Color.GRAY);
		int canvas_width = SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH;
		int canvas_height = SysConfig.CANVAS_HEIGHT / SysConfig.STONE_WIDTH;
		
		for (int i = 0; i < canvas_width ; i++) {
			g.fill3DRect(i * SysConfig.STONE_WIDTH, 0, SysConfig.STONE_WIDTH,
					SysConfig.STONE_HEIGHT, true);
		}
		for (int i = 0; i < canvas_width ; i++) {
			g.fill3DRect(i * SysConfig.STONE_WIDTH, SysConfig.CANVAS_HEIGHT
					- SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,
					SysConfig.STONE_HEIGHT, true);
		}

		for (int i = 0; i < canvas_height ; i++) {
			g.fill3DRect(0, i * SysConfig.STONE_WIDTH, SysConfig.STONE_WIDTH,
					SysConfig.STONE_HEIGHT, true);
		}

		for (int i = 0; i < canvas_height ; i++) {
			g.fill3DRect(SysConfig.CANVAS_WIDTH - SysConfig.STONE_WIDTH, i
					* SysConfig.STONE_WIDTH, SysConfig.STONE_WIDTH,
					SysConfig.STONE_HEIGHT, true);
		}
	}

	/**
	 * 畫草地
	 */
	public void drawGrass(Graphics g) {
		g.setColor(Color.DARK_GRAY);

		for (int i = 1; i < SysConfig.CANVAS_WIDTH / SysConfig.STONE_WIDTH - 1; i++) {
			for (int j = 1; j < SysConfig.CANVAS_HEIGHT
					/ SysConfig.STONE_HEIGHT - 1; j++) {
				g.fill3DRect(i * SysConfig.STONE_WIDTH, j
						* SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,
						SysConfig.STONE_HEIGHT, true);
			}
		}
	}

	/**
	 * 畫食物
	 */
	public void drawFood(Graphics g) {

		Point point = getFood().getLocation();
		//System.out.println("location : (" + point.x + "," +point.y +")");
		g.setColor(getFood().getColor());
		g.fill3DRect(( point.y + 1 ) * SysConfig.STONE_WIDTH, (point.x + 1)* SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,SysConfig.STONE_HEIGHT, true);

	}

	/**
	 * 畫蛇
	 */
	public void drawSnake(Graphics g) {
		g.setColor(getSnake().getColor());
		List<Point> body = getSnake().getBody();
		for (Point point : body) {
			g.fill3DRect((point.y + 1) * SysConfig.STONE_WIDTH, (point.x + 1)
					* SysConfig.STONE_HEIGHT, SysConfig.STONE_WIDTH,
					SysConfig.STONE_HEIGHT, true);
		}
	}

	@Override
	public void paint(java.awt.Graphics g) {
		drawWall(g);
		drawGrass(g);
		//snake.move();
		if(snake != null){
			drawSnake(g);
		}
		if(food != null){
			drawFood(g);
		}
	};
}

//MainFrame.java
package org.sysit.game.snake;

import java.awt.BorderLayout;

public class MainFrame extends JFrame {
	private JButton start;
	private JButton pause;
	private JPanel panel;
	private JPanel showScore;
	private JLabel lblNewLabel;
	private JTextField txtScore;
	public MainFrame() {

		super("貪喫蛇");
		
		getContentPane().setLayout(new BorderLayout());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		Ground ground = new Ground();
		//controller.setGround(ground);
		Snake snake = new Snake(3);
		ground.setSnake(snake);
		Food food = new Food();
		ground.setFood(food);
		snake.setFood(food);
		food.setLocation(snake);
			
		final GameController controller = new GameController(snake, food, ground);
			
		JPanel control = new JPanel();
		start = new JButton("開始");
		start.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				controller.startGame();
				pause.setEnabled(true);
			}
		});
		start.setSize(100, 50);
		
		pause = new JButton("暫停");
		pause.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if(controller.isPause()){
					pause.setText("暫停");
					controller.resumeGame();	
				}else{
					pause.setText("繼續");
					controller.pauseGame();
				}
			}
		});
		pause.setEnabled(false);
		pause.setSize(100, 50);
		
		control.add(start);
		control.add(pause);
		
		add(ground, BorderLayout.CENTER);
		add(control, BorderLayout.SOUTH);
		
		pack();
		
		panel = new JPanel();
		control.add(panel);
		panel.setLayout(null);
		
		showScore = new JPanel();
		getContentPane().add(showScore, BorderLayout.NORTH);
		showScore.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
		
		lblNewLabel = new JLabel("\u5206\u6570 : ");
		showScore.add(lblNewLabel);
		
		txtScore = new JTextField();
		showScore.add(txtScore);
		txtScore.setColumns(10);
		txtScore.setEditable(false);
		controller.setTxtScore(txtScore);
		
		Toolkit tool = Toolkit.getDefaultToolkit();
		Dimension dime = tool.getScreenSize();
		int screenWidth = dime.width;
		int screenHeight = dime.height;
		int frameWidth = SysConfig.CANVAS_WIDTH + 6;
		int frameHeight = SysConfig.CANVAS_HEIGHT + 94;
		
		setBounds((screenWidth - frameWidth)/2, (screenHeight - frameHeight)/2, frameWidth, frameHeight);
		setResizable(false);
		
		setVisible(true);
	}

	
	public static void main(String[] args) {
		new MainFrame();
	}
}

完整代碼:http://download.csdn.net/detail/zhang__bing/4377159

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章