难道我只会做贪吃蛇了?!
好吧我这里说明一下 贪吃蛇是最容易实现的游戏之一,初学者实现起来很容易。还可以复习链表的知识。
其实在练习时,重要的不是学习别人的逻辑结构 是学习别人的写法
逻辑算法这个东西要自己去想,才能深刻理解
不过废话了,简要说一下这个双人版贪吃蛇的规则
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();
}
}