您的位置:首页 > 编程语言 > Java开发

Java贪吃蛇,部分实现,适合作为新手练习作业。

2013-12-02 19:13 489 查看
一、概要设计

游戏规则:

由于基本都玩过,再次不在啰嗦。

游戏要素:

1、地图(map)

2、蛇(snake)

3、食物(food)

4、规则(rule)

输入设定:

1、通过键盘上的上、下、左、右进行游戏控制。

2、通过键盘的P控制游戏的暂停(pause)/开始(start)、N(new)控制新的一局的开始。

输出内容:(*为特定条件下激活)

1 、 游戏速度

2 、 游戏进行时间

3 、 贪吃蛇长度

4*、显示游戏结束信息

基本游戏默认参数:

1、地图大小(20X20)

2、地图单元格width = 20, height =20;

3、游戏速度为 (1051 - level*50)ms 初始等级为1,最高等级为20.

4、初始贪吃蛇长度为3

规则:

1、贪吃蛇碰触墙壁或者自身时,游戏结束。

2、贪吃蛇不能朝反方向进行移动。 ( 即:若当前贪吃蛇头部朝向的方向为南,则向北移动是无效的操作。)

3、贪吃蛇达到一定长度时,游戏结束。

4、食物位置随机生成。

未完成部分:

见Snack类中moveTo()方法的TODO标签处。

作业:

1、实现贪吃虫的自动移动。

2、增加游戏计时功能。(游戏时间)

3、增加暂停功能。

4、处理不同因移动造成的情况,进行相应处理

二、详细设计

画布类(Canvas):

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Vector;

import javax.swing.JPanel;

public class Canvas extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
/*画布参数*/
public static final int PADDING = 10; //画布内边距
public static final int CELL_SIZE = 20; //单元格大小
public static final int CELL_COLUMN = 20; //单元格列数
public static final int CELL_ROW = 20; //单元格行数
public static final Color BACKGROUND = Color.WHITE; //画布背景颜色
public int canvasWidth = 2*PADDING + CELL_SIZE*CELL_COLUMN;
public int canvasHeight = 2*PADDING + CELL_SIZE*CELL_ROW;
/*画布中的对象*/
public Snake snake; //贪吃蛇
private GameMap map; //地图(容器)
// ------------------------------------
// 构造方法
// ------------------------------------
public Canvas() {
setPreferredSize(null); //设置面板大小
startGame();
}

/*从Point坐标值转换为swing中的坐标值*/
public int transformX(int pointX){ return 0;}
public int transformY(int pointY){ return 0;}

/*开始游戏*/
public void startGame(){
map = new GameMap();
snake = new Snake(map);
/*初始化开始一条位置,并且长度为3的贪吃蛇*/
snake.enqueue(map.getPoint(10, 12));
snake.enqueue(map.getPoint(10, 11));
snake.enqueue(map.getPoint(10, 10));
map.randomFood(snake);
}

/*绘制界面*/
@Override
public void paint(Graphics g) {
super.paint(g);
/*绘制网格,测试用*/
//		for(int i=0;i<=CELL_COLUMN;i++)
//			g.drawLine(PADDING, PADDING+CELL_SIZE*i, PADDING +CELL_SIZE*CELL_COLUMN, PADDING+CELL_SIZE*i);
//		for(int i=0;i<=CELL_ROW;i++)
//			g.drawLine(PADDING + CELL_SIZE*i, PADDING, PADDING + CELL_SIZE*i, PADDING + CELL_SIZE*CELL_ROW);

/*画贪吃蛇*/
Vector<Point> body = snake.getBody();
for(int i=0;i<body.size();i++){
/*头部画黄色*/
Point p = body.get(i);
if(i == body.size()-1){
Color oldColor = g.getColor();
g.setColor(Color.yellow);
g.fillRect((int)p.getX(),(int) p.getY(), CELL_SIZE, CELL_SIZE);
g.setColor(oldColor);
}else
g.fillRect((int)p.getX(),(int) p.getY(), CELL_SIZE, CELL_SIZE);
}

/*画食物*/
Point food = map.getFood();
if(food != null){
//画食物
Color oldColor = g.getColor();
g.setColor(Color.red);
g.fillRect((int)food.getX(), (int)food.getY(), CELL_SIZE, CELL_SIZE);
g.setColor(oldColor);
}
}

/*重载设置面板大小*/
@Override
public void setPreferredSize(Dimension d) {
super.setPreferredSize(new Dimension(canvasWidth,canvasHeight));
}
}
地图类(GameMap):

import java.awt.Point;
import java.util.Random;

public class GameMap {

/*地图坐标*/
public Point[][] map;
/*食物坐标*/
private Point food;

/*构造方法*/
public GameMap() {
map = new Point[Canvas.CELL_ROW][Canvas.CELL_COLUMN];
for (int i=0;i<Canvas.CELL_ROW ;i++) {
for (int j=0;j<Canvas.CELL_COLUMN;j++) {
map[i][j] = new Point(Canvas.PADDING+Canvas.CELL_SIZE*i,Canvas.PADDING+Canvas.CELL_SIZE*j);
}
}
}

/*得到指定位置的X,Y坐标*/
public Point getPoint(int row,int column){
return map[row][column];
}

/*得到指定point所在map中的索引*/
public int[] pointAt(Point p){
int row = (int) ( (p.getX()-Canvas.PADDING) / Canvas.CELL_SIZE);
int column = (int)( (p.getY()-Canvas.PADDING) / Canvas.CELL_SIZE);
return new int[]{row,column};
}

/*随机生成食物坐标*/
public Point randomFood(Snake snake){
Random random = new Random();
int xPos = random.nextInt(Canvas.CELL_ROW);
int yPos = random.nextInt(Canvas.CELL_COLUMN);

while(true){
if( !snake.getBody().contains(getPoint(xPos, yPos)) ){
food = getPoint(xPos, yPos);
return food;
}else {
xPos = random.nextInt(Canvas.CELL_ROW);
yPos = random.nextInt(Canvas.CELL_COLUMN);
}
}
}

/*设置食物位置*/
public void setFood(Point food){
this.food = food;
}

/*得到食物位置*/
public Point getFood(){
return food;
}
}


贪吃蛇类(Snack):

import java.util.Vector;
import java.awt.Point;

public class Snake {

/*贪吃蛇在地图中的点集合,[0]元素为蛇头,[size-1]元素为蛇尾*/
private Vector<Point> body;
/*贪吃蛇所在地图*/
private GameMap map;

/*构造方法*/
public Snake(GameMap map){
this.map = map;
body = new Vector<Point>();
}

/*贪吃蛇移动或进食*/
public void enqueue(Point p) {
body.add(p);
}

/*判断贪吃蛇是否为空*/
public boolean isEmpty(){
return size() == 0;
}

/*返回贪吃蛇的长度*/
public int size() {
return body.size();
}

/*返回贪吃蛇头部的位置*/
public Point getHead() {
if(size()==0)
throw new RuntimeException("贪吃蛇无头部");
return body.get(size()-1);
}

/*返回贪吃蛇尾部的位置*/
public Point getTail() {
if(size()==0)
throw new RuntimeException("贪吃蛇无尾部");
return body.get(0);
}

/*返回头部后的第一个位置*/
public Point getHeadAfter(){
if(size()==1)
throw new RuntimeException("贪吃蛇只有头部");
return body.get(size()-2);
}

/*移除尾部*/
public void removeTail(){
body.remove(0);
}

/*返回整个贪吃蛇*/
public Vector<Point> getBody(){
return body;
}
// -----------------------------------
// 贪吃蛇行为
// -----------------------------------

/*是否为身体一部分*/
public boolean isBody(Point p){
if(body.contains(p))
return true;
return false;
}

/*贪吃蛇移动到地图指定点*/
public void moveTo(int row,int column) {
/*得到头部后第一个位置*/
Point afterHead = getHeadAfter();
/*判断要移动的位置是否有效*/
if(!moveValid(row, column)){
//TODO
//
//  添加你的处理方法,并将游戏结束
//
System.out.println("碰到墙壁了!");
return;
}
/*判断是否为无效反方向移动*/
if(map.getPoint(row, column).equals(afterHead)){
//TODO
//
//  添加你的处理方法,但游戏继续
//
System.out.println("无效的反方向操作!");
return;
}
/*判断是否碰到身体*/
if(isBody(map.getPoint(row, column))){
//TODO
//
//  添加你的处理方法,并将游戏结束
//
System.out.println("碰到身体了!");
return;
}
/*判断是否移动到食物上*/
if(map.getPoint(row, column).equals(map.getFood())){
/*将食物添加到贪吃蛇身体中*/
enqueue(map.getPoint(row, column));
/*重新生成食物*/
map.randomFood(this);
}else{
/*进行普通的移动*/
enqueue(map.getPoint(row, column));
removeTail();
}
}

/*贪吃蛇向左移动*/
public void moveLeft(){
/*得到头部位置*/
Point head = getHead();
int[] cood = map.pointAt(head);
moveTo(cood[0]-1, cood[1]);
}

/*贪吃蛇向右移动*/
public void moveRight(){
/*得到头部位置*/
Point head = getHead();
int[] cood = map.pointAt(head);
moveTo(cood[0]+1, cood[1]);

}
/*贪吃蛇向上移动*/
public void moveUp(){
/*得到头部位置*/
Point head = getHead();
int[] cood = map.pointAt(head);
moveTo(cood[0], cood[1]-1);

}
/*贪吃蛇向下移动*/
public void moveDown(){
/*得到头部位置*/
Point head = getHead();
int[] cood = map.pointAt(head);
moveTo(cood[0], cood[1]+1);
}
/*贪吃蛇移动是否有效*/
public boolean moveValid(int r,int c){
if( r < 0 || r >= Canvas.CELL_ROW || c < 0 || c >= Canvas.CELL_COLUMN)
return false;
return true;
}
}


游戏主界面类(GameFrame):

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class GameFrame extends JFrame implements KeyListener{

/**
*
*/
private static final long serialVersionUID = 1L;

private Canvas canvas;
/*构造方法*/
public GameFrame(){
init();
}

/*初始化*/
private void init(){
this.setTitle("贪吃蛇         by:luiyikeke");
canvas = new Canvas();
add(canvas); /*添加画布到主面板*/
pack();      /*自适应大小*/
setResizable(false);  /*禁止调整窗口大小*/
setLocationRelativeTo(null); /*窗口屏幕居中显示*/
this.addKeyListener(this);
}

public static void main(String[] args) {
new GameFrame().setVisible(true);
}

@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (38 == keyCode) {
canvas.snake.moveUp();
} else if (37 == keyCode) {
canvas.snake.moveLeft();
} else if (39 == keyCode) {
canvas.snake.moveRight();
} else if (40 == keyCode) {
canvas.snake.moveDown();
}
canvas.repaint();
}

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

}

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

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 贪吃蛇 GUI swing 原创