雙人版的貪喫蛇

難道我只會做貪喫蛇了?!

好吧我這裏說明一下 貪喫蛇是最容易實現的遊戲之一,初學者實現起來很容易。還可以複習鏈表的知識。

其實在練習時,重要的不是學習別人的邏輯結構 是學習別人的寫法

邏輯算法這個東西要自己去想,才能深刻理解

不過廢話了,簡要說一下這個雙人版貪喫蛇的規則

1.兩條蛇搶一個蘋果 沒喫一個蘋果得10分

2.兩條蛇可以互相咬斷對方,分數會加上咬斷的節數*10,被咬的不扣分

3.兩個蛇頭撞在一起或者蘋果投放大於20個的時候遊戲結束

4.誰的分數高誰就勝利

5.這個規則不是我想出來的 好像還有問題,請指教

/*
 * 貪喫蛇
 * 2011/10/05
 * LSN
 */
package com.lsn.Snake;

/**
 * JDK 1.6 Eclipse 3.6編譯通過
 * 操作方法:1.上下左右 移動蛇頭 
 * 			2. 回車暫停恢復遊戲
 * 
 * 待解決問題 :程序以applet方式運行時 不能自動設置焦點到applet
 */
import java.awt.Color;
import java.awt.Event;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;

import javax.imageio.ImageIO;
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class SnakeDouble extends JApplet implements Runnable, KeyListener {
	// 方向常量

	private static final int[] DIR_UP = { 0, -1 };
	private static final int[] DIR_DOWN = { 0, 1 };
	private static final int[] DIR_LEFT = { -1, 0 };
	private static final int[] DIR_RIGHT = { 1, 0 };

	// 屏幕的寬度和高度
	private static final int XBC = 31;
	private static final int YBC = 31;
	private static final int SCR_W = 16 * XBC + 32;
	private static final int SCR_H = 16 * YBC + 32;

	// 遊戲運行狀態
	private static final int GS_RUNNING = 1;
	private static final int GS_PAUSED = -1;
	

	class Snake {
		LinkedList<int[]> snake = new LinkedList<int[]>(); // 蛇體 用鏈表來存

		// 蛇頭位置和運動方向
		int snakeHeadPositionX;
		int snakeHeadPositionY;
		int[] snakeHeading;
		int score = 0;
	}

	private Snake[] sn = new Snake[2];

	private BufferedImage ofs; // 圖像緩衝 Off Screen Buffer
	private Image bg;
	// 果子的位置
	private int appleX;
	private int appleY;

	private boolean gameOver = false; // 遊戲結束的標誌
	private int hiscore = 0; // 最高得分

	private int gameStatus =GS_PAUSED; // 遊戲狀態
	private int appleCnt=0;

	@Override
	public void init() {

		for (int j = 0; j <= 1; j++) {
			// 初始化 蛇
			sn[j] = new Snake();
			for (int i = 0; i < 4; i++) {
				sn[j].snake.addFirst(DIR_UP);
			}
			// 初始化蛇頭
			sn[j].snakeHeading = DIR_UP;
			sn[j].snakeHeadPositionY = YBC / 2;
		}
		sn[0].snakeHeadPositionX = XBC / 2 - 3;
		sn[1].snakeHeadPositionX = XBC / 2 + 3;
		// 初始化遊戲狀態
		gameOver = false;
		ofs = new BufferedImage(SCR_W, SCR_H, BufferedImage.TYPE_4BYTE_ABGR);
		
		//背景
		try {
			bg=ImageIO.read((getClass().getResourceAsStream("/BG.png")));
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		// 隨機產生一個果子O(∩_∩)O~
		randomApple();

	}

	// 隨機產生果子
	private void randomApple() {

		appleX = (int) (Math.random() * XBC);
		appleY = (int) (Math.random() * YBC);
		for (int j = 0; j <= 1; j++) {
			if (appleX == sn[j].snakeHeadPositionX
					&& appleY == sn[j].snakeHeadPositionY)
				randomApple();
			if (onSnake(appleX, appleY, sn[j]) != 0)
				randomApple();
		}
		if (appleX == 0 || appleY == 0 || appleX == XBC + 1
				|| appleY == YBC + 1)
			randomApple();
		
		appleCnt++;
		if(appleCnt==20) gameOver=true;
	}

	// 判斷指定座標是否在蛇身上
	private int onSnake(int x, int y, Snake s) {

		Iterator<int[]> it = s.snake.iterator();

		int sx = s.snakeHeadPositionX;
		int sy = s.snakeHeadPositionY;
		int sc = 0;

		while (it.hasNext()) {
			sc++;
			int[] d = it.next();
			sx += d[0] * -1;
			sy += d[1] * -1;
			if (x == sx && y == sy)
				return sc;
		}

		return 0;
	}

	// 構造方法中加入鍵盤監聽器設置焦點
	public SnakeDouble() {
		addKeyListener(this);
		this.requestFocus();
	}

	@Override
	public void start() {
		new Thread(this).start();
	}

	// 主線程
	@Override
	public void run() {
		while (true) {
			while (!gameOver) {
				if (gameStatus == SnakeDouble.GS_RUNNING) {// 判斷遊戲是否運行中
					gameProcess();
				}
				this.repaint();
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {

					e.printStackTrace();
				}

			}
			// 遊戲結束處理
			JOptionPane.showMessageDialog(this, "遊戲結束\n藍色得分:" + sn[0].score
					+ "\n綠色得分:" + sn[1].score + "\n最高得分:" + hiscore, "貪喫蛇",
					JOptionPane.INFORMATION_MESSAGE);
			this.init();

		}
	}

	// 遊戲主處理
	private void gameProcess() {
		for (int j = 0; j <= 1; j++) {
			// 修正:蛇頭運動和蛇運動不能分開
			// 蛇頭運動
			sn[j].snakeHeadPositionX += sn[j].snakeHeading[0];
			sn[j].snakeHeadPositionY += sn[j].snakeHeading[1];
			// 蛇運動
			sn[j].snake.addFirst(sn[j].snakeHeading);
			sn[j].snake.removeLast();

			// 檢查蛇頭
			check(sn[j]);
		}

		int k = onSnake(sn[0].snakeHeadPositionX, sn[0].snakeHeadPositionY,
				sn[1]);
		if (k != 0) {
			eatSnake(sn[1], k);
			sn[0].score += (sn[1].snake.size() - k) * 10;
		}
		k = onSnake(sn[1].snakeHeadPositionX, sn[1].snakeHeadPositionY, sn[0]);
		if (k != 0) {
			eatSnake(sn[0], k);
			sn[1].score += (sn[0].snake.size() - k) * 10;
		}
		if (sn[0].snakeHeadPositionX == sn[1].snakeHeadPositionX
				&& sn[0].snakeHeadPositionY == sn[1].snakeHeadPositionY) {
			gameOver=true;
		}
	}

	private void eatSnake(Snake snake, int k) {
		for (int i = 0; i < snake.snake.size() - k; i++) {
			snake.snake.removeLast();
		}
	}

	// 檢查蛇頭
	private void check(Snake s) {
		int x = s.snakeHeadPositionX;
		int y = s.snakeHeadPositionY;

		if (x == 0 || y == 0 || x == XBC + 1 || y == YBC + 1
				|| onSnake(x, y, s) != 0) {
			gameOver = true;
		}
		if (appleX == x && appleY == y) {
			s.score += 10;
			if (hiscore < s.score) {
				hiscore = s.score;
			}
			s.snake.addFirst(s.snakeHeading);
			randomApple();
		}
		
	}

	// 繪製圖形
	@Override
	public void update(Graphics g) {
		paint(g);
	}

	@Override
	public void paint(Graphics g) {
		drawMap(ofs);
		g.drawImage(ofs, 0, 0, this);
	}

	private void drawMap(BufferedImage ofs2) {
		Graphics2D pen = ofs2.createGraphics();
		
		
		pen.setColor(Color.green);
		pen.clearRect(0, 0, SCR_W, SCR_H);
		pen.drawImage(bg, 64, 64, this);
		pen.setColor(Color.LIGHT_GRAY);
		for (int i = 0; i < XBC + 2; i++) {
			pen.fillRoundRect(i * 16, 0, 13, 13, 3, 3);
			pen.fillRoundRect(i * 16, SCR_H - 16, 13, 13, 3, 3);
			pen.fillRoundRect(0, i * 16, 13, 13, 3, 3);
			pen.fillRoundRect(SCR_W - 16, i * 16, 13, 13, 3, 3);
		}
		for (int j = 0; j <= 1; j++) {
			Iterator<int[]> it = sn[j].snake.iterator();

			// 畫蛇頭
			pen.setColor(Color.red);
			pen.fillRoundRect(sn[j].snakeHeadPositionX * 16,
					sn[j].snakeHeadPositionY * 16, 13, 13, 3, 3);

			int dx = sn[j].snakeHeadPositionX;
			int dy = sn[j].snakeHeadPositionY;
			// 畫蛇身
			if (j == 1) {
				pen.setColor(Color.green);
			} else {
				pen.setColor(Color.blue);
			}
			while (it.hasNext()) {
				int[] d = it.next();
				dx += d[0] * -1;
				dy += d[1] * -1;
				pen.fillRoundRect(dx * 16, dy * 16, 13, 13, 3, 3);
			}
		}
		// 畫蘋果
		pen.setColor(Color.orange);
		pen.fillRoundRect(appleX * 16, appleY * 16, 13, 13, 3, 3);
		
		if(gameStatus==GS_PAUSED){
			pen.setColor(Color.pink);
			pen.setFont(new Font("黑體",0, 30));
			pen.drawString("遊戲暫停,按任意鍵開始", 100,279);
		}

	}

	@Override
	public void keyTyped(KeyEvent e) {
	}

	// 處理鍵盤事件
	@Override
	public void keyPressed(KeyEvent e) {

		Snake n = sn[0];
		Snake s = sn[1];
		switch (e.getKeyCode()) {
		case KeyEvent.VK_UP:
			if (s.snakeHeading == DIR_UP || s.snakeHeading == DIR_DOWN) {
				break;
			} else {
				s.snakeHeading = DIR_UP;
			}
			break;
		case KeyEvent.VK_DOWN:
			s.snakeHeading = s.snake.getFirst();
			if (s.snakeHeading == DIR_UP || s.snakeHeading == DIR_DOWN) {
				break;
			} else {
				s.snakeHeading = DIR_DOWN;
			}
			break;
		case KeyEvent.VK_LEFT:
			s.snakeHeading = s.snake.getFirst();
			if (s.snakeHeading == DIR_LEFT || s.snakeHeading == DIR_RIGHT) {
				break;
			} else {
				s.snakeHeading = DIR_LEFT;
			}
			break;
		case KeyEvent.VK_RIGHT:
			s.snakeHeading = s.snake.getFirst();
			if (s.snakeHeading == DIR_LEFT || s.snakeHeading == DIR_RIGHT) {
				break;
			} else {
				s.snakeHeading = DIR_RIGHT;
			}
			break;
		case KeyEvent.VK_W:
			if (n.snakeHeading == DIR_UP || n.snakeHeading == DIR_DOWN) {
				break;
			} else {
				n.snakeHeading = DIR_UP;
			}
			break;
		case KeyEvent.VK_S:
			n.snakeHeading = n.snake.getFirst();
			if (n.snakeHeading == DIR_UP || n.snakeHeading == DIR_DOWN) {
				break;
			} else {
				n.snakeHeading = DIR_DOWN;
			}
			break;
		case KeyEvent.VK_A:
			n.snakeHeading = n.snake.getFirst();
			if (n.snakeHeading == DIR_LEFT || n.snakeHeading == DIR_RIGHT) {
				break;
			} else {
				n.snakeHeading = DIR_LEFT;
			}
			break;
		case KeyEvent.VK_D:
			n.snakeHeading = n.snake.getFirst();
			if (n.snakeHeading == DIR_LEFT || n.snakeHeading == DIR_RIGHT) {
				break;
			} else {
				n.snakeHeading = DIR_RIGHT;
			}
			break;
		case KeyEvent.VK_ESCAPE:
			System.exit(0);
			break;
		case KeyEvent.VK_ENTER:
			gameStatus = -gameStatus;
			break;
		}
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	// 主方法 處理application方式運行
	public static void main(String[] args) {
		new JFrame("貪喫蛇雙人版") {
			private void init() {
				this.setBounds(100, 100, SCR_W + 5, SCR_H + 25);

				SnakeDouble game = new SnakeDouble();
				game.init();
				game.start();

				this.add("Center", game);
				this.setVisible(true);
				game.requestFocus();
			}

			protected void processEvent(java.awt.AWTEvent e) {
				if (e.getID() == Event.WINDOW_DESTROY) {
					System.exit(0);
				}
			}
		}.init();
	}
}



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