“现实会告诉你,不努力就会被生活给踩死。无需找什么借口,一无所有,就是拼的理由。”
01.游戏整体设计
游戏应具有的对象:
1.蛇类
2.食物类
3.游戏控制类
4.节点类
5.游戏界面类
效果:
02.蛇类设计(Snake)
1.属性:
蛇身:用双向链表表示蛇身每一个节点的逻辑坐标,和对应节点的颜色。节点的数量也就代表了蛇的长度。
方向:蛇头的方向。
生长标记:生长标记,用于判断蛇是否吃到食物,判断其是否生长。
2.方法:
方法 | 方法名和参数 | 实现方法 |
---|---|---|
初始化 | pulic Snake(int length) | |
移动 | public void move() | 加头去尾 |
生长 | public void grow() | 设置成长标记,如果为生长,则不去尾部 |
转向 | public void | |
判断蛇是否吃到食物 | public boolean eatFood(Food food) | |
判断蛇是否吃到自己 | public boolean eatSelf() | |
判断蛇是否碰到墙 | public boolean meetWall(Grid grid) |
package HomeWork.GreedySnake;
import java.awt.*;
import java.util.LinkedList;
public class Snake {
public final static byte UP = 1;
public final static byte DOWN = -1;
public final static byte LEFT= 2;
public final static byte RIGHT = -2;
private LinkedList<Node> body;//蛇身(节点的集合)
private byte direction;//蛇头当前移动的方向
private static boolean growFlag = false;
/**
* 构造函数,初始化一条指定长度,并且向右移动的蛇
* @param length 蛇的长度
*/
public Snake(int length) {
body = new LinkedList<>();
for(int col = length-1;col>=0;col--){
Color color = col==length-1?Color.YELLOW:Color.BLUE;
Node node = new Node(0,col,color);
body.add(node);
}
direction = RIGHT;
}
/**
* 移动
*/
public void move(){
//思路加头去尾
//加头(1)复制头(2)根据方向调整位置 (3)加入蛇身
Node head = body.getFirst();
Node newHead = new Node(head);
head.color = Color.BLUE;
switch (direction){
case UP:
newHead.row--;break;
case DOWN:
newHead.row++;break;
case LEFT:
newHead.col--;break;
case RIGHT:
newHead.col++;break;
}
body.addFirst(newHead);
if(growFlag) {//根据生长标记,判断是否生长
growFlag = false;//将生长标记回置,让蛇只长一次
} else {
body.removeLast();//去尾
}
}
/**
* 生长
*/
public void grow(){
/**
* 思路:头部加可能越界
* 尾部加又无法确定三种情形到底是哪一种
* 所以考虑设置生长标记,当有生长标记时,我们只加头不去尾
* 当没有生长标记时,加头去尾
*/
growFlag = true;
}
/**
* 转向
* @param d 新的方向
*/
public void turn(byte d){
if(direction != -d) {
direction = d;
}
}
/**
* 判断蛇是否吃到食物
* @param food 食物
* @return true吃到了,false没有吃到
*/
public boolean eatFood(Food food){
Node head = body.getFirst();
Node node = food.getNode();
return head.equals(node);
}
/**
* 判断蛇是否吃到自己
* @return true吃到了,false没有吃到
*/
public boolean eatSelf(){
Node head = body.getFirst();
for (int i=1;i<body.size();i++){
Node node = body.get(i);
if(node.equals(head)){
return true;
}
}
return false;
}
/**
* 判断蛇是否碰到墙
* @param grid 网格对象
* @return true碰到了,false没有碰到
*/
public boolean meetWall(Grid grid){
/* int rows = grid.getRows();
int cols = grid.getCols();
Node head = body.getFirst();
return head.row<0||head.row>=rows||head.col<0||head.col>=cols;*/
return grid.outOfBound(body.getFirst());
}
public LinkedList<Node> getBody() {
return body;
}
}
03.食物类设计(Food)
属性:食物用一个节点表示。
方法:食物随机初始化。
程序代码:
package HomeWork.GreedySnake;
import java.awt.*;
import java.util.List;
public class Food {
private Node node;//节点
/**
* 食物的随机初始化
* @param maxRow 最大行号
* @param maxCol 最大列号
* @param nodes 不能出现的节点集合(蛇的节点)
*/
public Food(int maxRow, int maxCol, List<Node> nodes){
boolean flag = true;
while(flag){
int row = (int)(Math.random()*(maxRow+1));
int col = (int)Math.random()*(maxCol+1);
node =new Node(row,col, Color.RED);
flag = false;
for(Node node1:nodes){
if (node.equals(node1)){//如果食物出现的位置在蛇身的位置
flag = true;
break;
}
}
}
}
public Node getNode() {
return node;
}
}
04.节点类(Node)
属性 | 属性名 |
---|---|
行号 | row |
列号 | col |
颜色 | color |
方法:
重写equals方法
程序代码:
package HomeWork.GreedySnake;
import java.awt.*;
import java.util.Objects;
public class Node {
public int row;//行号
public int col;//列号
public Color color;//颜色
public Node(int row, int col, Color color) {
this.row = row;
this.col = col;
this.color = color;
}
/**
* 拷贝构造函数
* @param node 节点
*/
public Node (Node node){
this.row = node.row;
this.col = node.col;
this.color = node.color;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node node = (Node) o;
return row == node.row &&
col == node.col;
}
@Override
public int hashCode() {
return Objects.hash(row, col, color);
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
05.游戏界面类(Grid)
属性 | 属性名 |
---|---|
行数 | rows |
列数 | cols |
格子大小 | size |
边距 | margin |
package HomeWork.GreedySnake;
public class Grid {
private int rows;//行数
private int cols;//列数
private int size;//格子大小
public Grid(int rows, int cols, int size) {
this.rows = rows;
this.cols = cols;
this.size = size;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getCols() {
return cols;
}
public void setCols(int cols) {
this.cols = cols;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public boolean outOfBound(Node head) {
return head.row<0||head.row>=rows||head.col<0||head.col>=cols;
}
public int getWidth() {
return size *cols;
}
public int getHight() {
return size*rows;
}
}
06.游戏控制类(Game)
游戏类继承Thread类
属性 | 属性名 |
---|---|
蛇 | snake |
食物 | food |
网格 | grid |
窗口 | frame |
画布 | canvas |
绘图对象 | graphics |
按钮 | button |
方法 | 方法名 |
---|---|
绘制网格 | drawGrid() |
绘制蛇 | drawSnake() |
绘制食物 | drawFood() |
绘制节点 | drawNode() |
线程方法 | run() |
在这里插入代码片package HomeWork.GreedySnake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
public class Game extends Thread{
private Snake snake;//蛇
private Food food;//食物
private Grid grid;//网格
private static Frame frame;//窗体
private static Canvas canvas;//画布
private Graphics graphics;//绘图对象
private Button button;//按钮
public static void main(String[] args) {
Game game = new Game(30,30,25,5);
}
@Override
public void run() {
while (true){
snake.move();
drawGrid();
drawFood();
drawSnake();
if(snake.eatFood(food)){//吃食物
snake.grow();
food = new Food(grid.getRows()-1,grid.getCols()-1,snake.getBody());
}
if(snake.eatSelf()||snake.meetWall(grid)){
JOptionPane.showMessageDialog(null, "游戏结束!", "游戏结束",JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
//结束
break;
}
try {
int scores = snake.getBody().size();
switch (scores){
case 7:Thread.sleep(100);break;
case 10:Thread.sleep(50);break;
case 15:Thread.sleep(30);break;
case 25:Thread.sleep(20);break;
case 35:Thread.sleep(10);break;
}
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 游戏构造函数
* @param rows 行数
* @param cols 列数
* @param size 格子大小
* @param length 初始长度
*/
public Game(int rows, int cols,int size,int length) {
grid = new Grid(rows,cols,size);
snake = new Snake(length);
food = new Food(rows-1,cols-1,snake.getBody());
//初始化窗口
int width = grid.getWidth();
int height = grid.getHight();
frame = new Frame("贪吃蛇");
frame.setSize(width,height+100);
frame.setLayout(new FlowLayout());
frame.setVisible(true);//显示窗体
//准备画布
canvas = new Canvas();
canvas.setSize(width,height);//指定尺寸
frame.add(canvas);
//监听按键
canvas.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();//获取按键编码
switch (keyCode){
case KeyEvent.VK_UP:snake.turn(Snake.UP);break;
case KeyEvent.VK_DOWN:snake.turn(Snake.DOWN);break;
case KeyEvent.VK_LEFT:snake.turn(Snake.LEFT);break;
case KeyEvent.VK_RIGHT:snake.turn(Snake.RIGHT);break;
}
super.keyPressed(e);
}
});
//增加按钮
button = new Button("Start Game");
button.setSize(50,25);
frame.add(button);
//响应按钮
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent mouseEvent) {
graphics = canvas.getGraphics();
canvas.requestFocus();//画布获取焦点
drawGrid();//绘制界面
drawSnake();//绘制蛇
drawFood();//绘制食物
start();//开启线程
}
});
//增加按钮
button = new Button("Exit Game");
button.setSize(50,25);
frame.add(button);
//响应按钮
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent mouseEvent) {
graphics = canvas.getGraphics();
frame.setVisible(false);//退出窗体
System.exit(0);//退出程序
super.mouseClicked(mouseEvent);
}
});
}
/**
* 开始游戏
*/
/**
* 绘制游戏网格
*/
public void drawGrid(){
graphics.setColor(Color.gray);
graphics.fillRect(0,0,grid.getWidth(),grid.getHight());
}
/**
* 绘制蛇
*/
public void drawSnake(){
LinkedList<Node> nodes = snake.getBody();
for(Node node:nodes){
drawNode(node);
}
}
private void drawNode(Node node){
int size = grid.getSize();
int x = node.col*size;
int y = node.row*size;
graphics.setColor(node.color);
graphics.fillRect(x,y,size,size);
}
/**
* 绘制食物
*/
public void drawFood(){
drawNode(food.getNode());
}
}
“把别人的嘲讽当成你起飞的跑道,传奇,总是从平凡开始的!我要飞,不管你信或者不信!”