難道我只會做貪喫蛇了?!
好吧我這裏說明一下 貪喫蛇是最容易實現的遊戲之一,初學者實現起來很容易。還可以複習鏈表的知識。
其實在練習時,重要的不是學習別人的邏輯結構 是學習別人的寫法
邏輯算法這個東西要自己去想,才能深刻理解
不過廢話了,簡要說一下這個雙人版貪喫蛇的規則
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();
}
}