【灌水帖】【图种】花了两天学习用Java编写了一个贪吃蛇小游戏
孟子名轲吧
全部回复
仅看楼主
level 8
APTX4869_aaa 楼主
一楼百度
2014年09月09日 19点09分 1
level 8
APTX4869_aaa 楼主
参考马士兵的视频自己进行优化和改编完成的
所以如有错误请多多包涵
希望有大神能给小弟挑错(包括优化方面)
下面开始贴代码
2014年09月09日 19点09分 3
level 8
APTX4869_aaa 楼主
窗体主类:Yard.java
package com.weibo.r4p0.snack;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JOptionPane;
public class Yard extends Frame {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final int ROWS = 20;
public static final int COLUMNS = 20;
public static final int CELL_WEIGHT = 20;
public boolean flag = true;
public boolean pause = true;
private Runnable refreshRunnable = new YardRunnable();
private Canvas canvas = new YardCanvas();
private Snake snake = null;
private Egg egg = null;
public static void main(String[] args) {
new Yard().launch();
}
/**
* 启动窗口
*/
private void launch() {
this.setTitle("My Snake");
// 添加键盘监听
this.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
keyPress(e);
}
});
this.setResizable(false);
this.setLayout(new BorderLayout());
// 新建画布对象,用来控制实际尺寸
MenuBar bar = new MenuBar();
Menu menu = new Menu("Help");
MenuItem helpItem = new MenuItem("How to play");
helpItem.setActionCommand("help");
menu.add(helpItem);
MenuItem aboutItem = new MenuItem("About Snake");
aboutItem.setActionCommand("about");
menu.add(aboutItem);
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
actionPress(e);
}
};
aboutItem.addActionListener(actionListener);
helpItem.addActionListener(actionListener);
bar.add(menu);
this.setMenuBar(bar);
canvas = new YardCanvas();
this.add(canvas);
// 自动适配窗口大小
this.pack();
// 居中计算
int width = this.getWidth();
int height = this.getHeight();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screenSize.width - width) / 2;
int y = (screenSize.height - height) / 2;
this.setLocation(x, y);
// 添加关闭窗口监听
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
// 显示窗口
this.setVisible(true);
restart();
pause = true;
}
/**
* 键盘事件处理
*/
private void keyPress(KeyEvent e) {
Dir head = snake.head.dir;
Dir change = null;
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
if (head != Dir.DOWN) {
change = Dir.UP;
} else {
return;
}
break;
case KeyEvent.VK_DOWN:
if (head != Dir.UP) {
change = Dir.DOWN;
} else {
return;
}
break;
case KeyEvent.VK_LEFT:
if (head != Dir.RIGHT) {
change = Dir.LEFT;
} else {
return;
}
break;
case KeyEvent.VK_RIGHT:
if (head != Dir.LEFT) {
change = Dir.RIGHT;
} else {
return;
}
break;
case KeyEvent.VK_F2:
this.restart();
return;
case KeyEvent.VK_SPACE:
pause = !pause;
return;
default:
return;
}
if (change == head && !pause) {
} else {
snake.head.dir = change;
}
snake.move();
snake.eat(egg);
}
/**
* 重新开始游戏
*/
private void restart() {
snake = new Snake(this);
egg = new Egg(snake);
if (!flag || pause) {
pause = false;
flag = true;
new Thread(refreshRunnable).start();
}
}
/**
* 停止游戏
*/
public void stop() {
flag = false;
while (!flag) {
int result = JOptionPane.showConfirmDialog(canvas, "Restart",
"Game Over", JOptionPane.OK_CANCEL_OPTION);
if (result == 0) {
restart();
} else {
int exit = JOptionPane.showConfirmDialog(canvas, "Exit",
"Exit", JOptionPane.OK_CANCEL_OPTION);
if (exit == 0) {
System.exit(0);
}
}
}
}
/**
* 处理ActionListener的事件
* @param e
*/
private void actionPress(ActionEvent e) {
MenuItem temp = (MenuItem) e.getSource();
String message = null, title = null;
if (temp.getActionCommand().equals("about")) {
message = "Author : Rain Yuan";
title = "About";
} else if (temp.getActionCommand().equals("help")) {
message = "Press direction key to move the snake\nPress F2 to restart\nPress spacebar to pause";
title = "Help";
}
JOptionPane.showMessageDialog(null, message, title,
JOptionPane.INFORMATION_MESSAGE);
}
/**
* 创建自定义画布类
*/
private class YardCanvas extends Canvas {
private static final long serialVersionUID = 1L;
private int width = COLUMNS * CELL_WEIGHT;;
private int height = ROWS * CELL_WEIGHT;;
private Image iBuffer;
private Graphics gBuffer;
/**
* 初始化画布
*/
public YardCanvas() {
this.setSize(width, height);
this.setBackground(Color.LIGHT_GRAY);
}
/**
* 绘制画布
*/
public void paint(Graphics g) {
Color c = g.getColor();
// 绘制网格
g.setColor(Color.BLACK);
for (int i = 1; i < ROWS; i++) {
g.drawLine(0, CELL_WEIGHT * i, width, CELL_WEIGHT * i);
}
for (int i = 1; i < COLUMNS; i++) {
g.drawLine(CELL_WEIGHT * i, 0, CELL_WEIGHT * i, height);
}
// 绘制蛇
snake.draw(g);
egg.draw(g);
snake.eat(egg);
g.setColor(c);
}
/**
* 用update方法实现图形双缓冲
*/
public void update(Graphics g) {
if (iBuffer == null) {
iBuffer = createImage(this.getWidth(), this.getHeight());
gBuffer = iBuffer.getGraphics();
}
gBuffer.setColor(getBackground());
gBuffer.fillRect(0, 0, this.getWidth(), this.getHeight());
paint(gBuffer);
g.drawImage(iBuffer, 0, 0, this);
}
}
/**
* 创建刷信用线程类
*/
private class YardRunnable implements Runnable {
private int updateFre = 1000 / 30;
public void run() {
while (flag) {
if (!pause) {
canvas.repaint();
}
try {
Thread.sleep(updateFre);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
2014年09月09日 19点09分 4
level 8
APTX4869_aaa 楼主
蛇的类:Snake.java
package com.weibo.r4p0.snack;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.ArrayList;
public class Snake {
private final long REFRESH = 15;
private long times = 0;
Node head = null;
Node tail = null;
public int length = 0;
private Yard yard = null;
public Snake(int x, int y, Dir dir) {
head = tail = new Node(x, y, dir);
this.length++;
}
public Snake(Yard yard) {
this(Yard.COLUMNS / 2, Yard.ROWS / 2, Dir.UP);
this.addToTail();
this.addToTail();
this.addToTail();
this.addToTail();
this.yard = yard;
}
/**
* 绘制Snake
* @param g
*/
public void draw(Graphics g) {
isAlive();
if (times == (Yard.COLUMNS * Yard.ROWS - length)*REFRESH/(Yard.COLUMNS * Yard.ROWS)) {
move();
times = 0;
} else {
times++;
}
for (Node node = head; node != null; node = node.next) {
node.draw(g);
}
}
/**
* 判断Snake是否活着
*/
public void isAlive() {
// 循环控制
boolean outOfWall = head.x < 0 || head.x > Yard.COLUMNS || head.y < 0 || head.y > Yard.ROWS;
if (outOfWall || this.isEatTail()) {
yard.stop();
}
return;
}
/**
* 判断Snake是否撞到尾巴
* @return
*/
private boolean isEatTail() {
Node node = this.head;
if (node == null) {
return false;
}
for (node = node.next; node != null; node = node.next) {
if (this.getRectangle().intersects(node.getRectangle())) {
return true;
}
}
return false;
}
/**
* 在头部添加节点
*/
public void addToHead() {
Node node = null;
switch (head.dir) {
case UP:
node = new Node(head.x, head.y - 1, head.dir);
break;
case DOWN:
node = new Node(head.x, head.y + 1, head.dir);
break;
case LEFT:
node = new Node(head.x - 1, head.y, head.dir);
break;
case RIGHT:
node = new Node(head.x + 1, head.y, head.dir);
break;
default:
break;
}
head.prev = node;
node.next = head;
head = node;
this.length++;
}
/**
* 在尾部添加节点
*/
public void addToTail() {
Node node = null;
switch (tail.dir) {
case UP:
node = new Node(tail.x, tail.y + 1, tail.dir);
break;
case DOWN:
node = new Node(tail.x, tail.y - 1, tail.dir);
break;
case LEFT:
node = new Node(tail.x + 1, tail.y, tail.dir);
break;
case RIGHT:
node = new Node(tail.x - 1, tail.y, tail.dir);
break;
default:
break;
}
tail.next = node;
node.prev = tail;
tail = node;
this.length ++;
}
/**
* Snake吃Egg
* @param egg
*/
public void eat(Egg egg) {
if (this.getRectangle().intersects(egg.getRectangle())) {
egg.reappear(this);
this.addToTail();
}
}
/**
* 获取Snake头结点的Rectangle
* @return
*/
public Rectangle getRectangle() {
return new Rectangle(head.x * Yard.CELL_WEIGHT, head.y
* Yard.CELL_WEIGHT, Yard.CELL_WEIGHT, Yard.CELL_WEIGHT);
}
/**
* 从尾巴删除一个节点
*/
public void deleteFromTail() {
if (head == null) {
return;
}
tail = tail.prev;
tail.next = null;
this.length --;
}
/**
* Snake向前移动一格
*/
public void move() {
if (head == null) {
return;
}
addToHead();
deleteFromTail();
}
/**
* 获取Snake每一个结点的ID
* @return
*/
public ArrayList<Integer> getIdList() {
ArrayList<Integer> arrayList = new ArrayList<>();
for (Node node = this.head; node != null; node = node.next) {
arrayList.add(new Integer(node.getId()));
}
return arrayList;
}
/**
* 实现双向链表Node类
* @author 陈晨
*
*/
class Node {
Node next = null;
Node prev = null;
Dir dir = null;
int x, y;
public Node(int x, int y, Dir dir) {
super();
this.x = x;
this.y = y;
this.dir = dir;
}
/**
* 绘制结点
* @param g
*/
public void draw(Graphics g) {
Color c = g.getColor();
// 绘制节点
g.setColor(Color.BLACK);
g.fillRect(x * Yard.CELL_WEIGHT, y * Yard.CELL_WEIGHT,
Yard.CELL_WEIGHT, Yard.CELL_WEIGHT);
g.setColor(c);
}
/**
* 获取当前结点的Rectangle
* @return
*/
public Rectangle getRectangle() {
return new Rectangle(this.x * Yard.CELL_WEIGHT, this.y
* Yard.CELL_WEIGHT, Yard.CELL_WEIGHT, Yard.CELL_WEIGHT);
}
/**
* 获取结点ID
* @return
*/
public int getId() {
return y * Yard.COLUMNS + x;
}
}
}
2014年09月09日 19点09分 5
level 8
APTX4869_aaa 楼主
蛋的类:Egg.java
package com.weibo.r4p0.snack;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
public class Egg {
private int x;
private int y;
private static Random r = new Random();
public Egg(int x, int y) {
super();
this.x = x;
this.y = y;
}
public Egg(Snake snake) {
this.reappear(snake);
}
/**
* 重新设置Egg的位置
* @param snake
*/
public void reappear(Snake snake) {
int random = r.nextInt(Yard.COLUMNS * Yard.ROWS - snake.length);
int i = 0, id;
for (id = 0; id < Yard.COLUMNS * Yard.ROWS; id++) {
if (snake.getIdList().contains(id)) {
continue;
}
if (i == random) {
break;
}
i++;
}
this.x = id % Yard.COLUMNS;
this.y = id / Yard.COLUMNS;
}
/**
* 获取Egg的Rectangle
* @return
*/
public Rectangle getRectangle() {
return new Rectangle(this.x * Yard.CELL_WEIGHT, this.y
* Yard.CELL_WEIGHT, Yard.CELL_WEIGHT, Yard.CELL_WEIGHT);
}
/**
* 绘制Egg
* @param g
*/
public void draw(Graphics g) {
Color c = g.getColor();
g.setColor(Color.BLACK);
g.fillOval(x * Yard.CELL_WEIGHT, y * Yard.CELL_WEIGHT,
Yard.CELL_WEIGHT, Yard.CELL_WEIGHT);
g.setColor(c);
}
}
2014年09月09日 19点09分 6
level 8
APTX4869_aaa 楼主
辅助:方向枚举类:Dir.java
package com.weibo.r4p0.snack;
public enum Dir {
UP, DOWN, LEFT, RIGHT;
}
2014年09月09日 19点09分 7
level 12
为何这么吊
2014年09月18日 04点09分 8
回复@孟子名轲 :我就是这么屌
2014年09月18日 16点09分
level 11
技术宅[啊]
2014年09月27日 06点09分 9
。。。我是渣渣。。。
2014年10月03日 14点10分
level 12
你为何这么屌。
2014年10月16日 08点10分 10
。。。我就是这么吊
2014年10月16日 10点10分
level 13
为何吊的一逼
2014年11月04日 16点11分 11
回复@0seven11 :我就是这么屌怎么了
2014年11月13日 18点11分
1