双人版的贪吃蛇

难道我只会做贪吃蛇了?!

好吧我这里说明一下 贪吃蛇是最容易实现的游戏之一,初学者实现起来很容易。还可以复习链表的知识。

其实在练习时,重要的不是学习别人的逻辑结构 是学习别人的写法

逻辑算法这个东西要自己去想,才能深刻理解

不过废话了,简要说一下这个双人版贪吃蛇的规则

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();
	}
}



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