乐趣区

java贪吃蛇

在设计该游戏时,首先是做出一个主界面 即 SnakeUI 类,在该类中要对主界面的润饰,蛇的初始化,食物的初始化,键盘的监听事件,

1,SnakeUI 类

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.Rectangle;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import java.awt.image.BufferedImage;

import javax.swing.JFrame;

import javax.swing.JOptionPane;

public class SnakeUI extends JFrame implements KeyListener {

private BufferedImage uiImg = new BufferedImage(Constant.JFRAME_WIDTH,

Constant.JFRAME_HEIGHT, BufferedImage.TYPE_3BYTE_BGR);

private Rectangle rec;

private SNode food;

private Snake snake; // 定义蛇对象

private static int SPEED = Constant.SNAKE_NORMAL;

public SnakeUI() {

this.rec = Constant.rec;

this.food = new SNode(Color.BLUE);

this.snake = new Snake(this);// 初始化蛇对象

this.launchFrame();

}

// 取得以后界面的食物

public SNode getFood() {

return food;

}

private void launchFrame() {

this.setTitle(“ 贪吃蛇 V0.1”);

this.setBounds(200, 100, Constant.JFRAME_WIDTH, Constant.JFRAME_HEIGHT);

this.setVisible(true);

this.setResizable(false);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

new Thread(new UIUpdate()).start(); // 启动更新线程

this.addKeyListener(this); // 监听键盘事件

}

public void paint(Graphics g) {

// 1. 间接画入图形。g.drawRect 画入闪动成果 [不可取]

// 2. 将图形画入到缓存图片,再讲图片画入到 Frame 中,防止闪动成果

// 设置矩形的色彩,并绘入到 uiImg 图片,将此图片间接写入到内存

Graphics2D g2d = (Graphics2D) uiImg.getGraphics();

// 在缓存图片画红色背景

g2d.setColor(Color.WHITE);

g2d.fillRect(0, 0, this.getWidth(), this.getHeight());

// 设置边框色彩

g2d.setColor(Color.BLACK);

g2d.drawRect((int) this.rec.getX(), (int) this.rec.getY(),

(int) this.rec.getWidth(), (int) this.rec.getHeight());

// 设置两头方格

g2d.setColor(Color.CYAN);

int startx = (int) this.rec.getX();

int starty = (int) this.rec.getY();

for (int i = 0; i < 35; i++) {

for (int j = 0; j < 50; j++) {

g2d.drawRect(startx + j * Constant.FOOD_WIDTH, starty + i

* Constant.FOOD_HEIGHT, Constant.FOOD_WIDTH,

Constant.FOOD_HEIGHT);

}

}

// 设置版本文字

g2d.setColor(Color.RED);

g2d.setFont(new Font(“ 宋体 ”, Font.ITALIC, 16));// 设置字体

g2d.drawString(“ 版本文字 2019”, 580, 530);

// 画食物, 食物 paint 办法在 SNode 类定义,在 UI 界面中的 paint 办法被调用

this.food.paint(g2d);

// 画蛇

this.snake.paint(g2d);

// 蛇吃食物绘制: 蛇曾经在吃食物, 食物被吃完后从新定义一个食物对象,并与蛇的身材做重叠判断

if (this.snake.eat(this.food)) {

this.food = new SNode(Color.BLUE);

while (this.snake.hit(this.food)) {

this.food = new SNode(Color.BLUE);

}

}

g.drawImage(uiImg, 0, 0, null); // 写入到内存

}

public static void main(String[] args) {

new SnakeUI();

}

@Override

public void keyTyped(KeyEvent e) {

// TODO Auto-generated method stub

}

@Override

// 按压键盘次要目标更改蛇静止方向

public void keyPressed(KeyEvent e) {

int key = e.getKeyCode();

switch (key) {

case KeyEvent.VK_LEFT:

snake.setDir(Constant.L);

System.out.println(“dddl”);

break;

case KeyEvent.VK_RIGHT:

snake.setDir(Constant.R);

System.out.println(“dddr”);

break;

case KeyEvent.VK_UP:

snake.setDir(Constant.U);

System.out.println(“dddu”);

break;

case KeyEvent.VK_DOWN:

snake.setDir(Constant.D);

break;

case KeyEvent.VK_W:

SPEED = Constant.SNAKE_ADD;

break;

case KeyEvent.VK_D:

SPEED = Constant.SNAKE_NORMAL;

break;

case KeyEvent.VK_S:

SPEED = Constant.SNAKE_SUB;

break;

case KeyEvent.VK_T:

SPEED = Constant.SNAKE_SUPER;

break;

}

}

@Override

public void keyReleased(KeyEvent e) {

SPEED = Constant.SNAKE_NORMAL;

}

// 一直刷新界面的线程

class UIUpdate implements Runnable {

@Override

public void run() {

while (SnakeUI.this.snake.isLive()) {

System.out.println(“…………..thread….”);

SnakeUI.this.repaint();

// 为了减缓更新的速度,设定每一次绘制之后进展 1 秒。
外汇常见问题 https://www.fx61.com/faq

try {

Thread.sleep(SPEED);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

JOptionPane.showMessageDialog(SnakeUI.this, “ 游戏越界,game over.”);

}

}

}

2,Snake 蛇类

实例化蛇这个类,应用的是一个 list 汇合对蛇的各个局部进行存储以及显示,

import java.awt.Color;

import java.awt.Graphics2D;

import java.util.ArrayList;

import java.util.List;

import javax.swing.JOptionPane;

public class Snake {

private SNode snakeHead; // 蛇头结点

private int startx, starty; // 蛇头的坐标

private List nodes = new ArrayList(); // 整条蛇,由 SNode 结点组成:

// 线性表 List

private int dir; // 方位

private boolean isLive = true; // 蛇处于运行状态

// 给蛇增加运行速度, 每一次运行走 3 个像素

private int speed = 3;

// getter.setter 蛇的方向

public int getDir() {

return dir;

}

public void setDir(int dir) {

this.dir = dir;

}

// 传入蛇所在的界面,通过界面取得以后的食物对象

public Snake(SnakeUI ui) {

this.dir = Constant.U;

this.noOverride(ui.getFood());

}

// 随机产生蛇头的坐标与食物不反复

public void noOverride(SNode food) {

this.generateSnake();

while (this.hit(food)) {// 蛇与食物重叠

this.generateSnake();

}

}

private void generateSnake() {

int x = SNode.generate(50); // [0,49)

int y = SNode.generate(35);

if (x == 0) {

x += 1;

} else if (x == 49) {

x -= 1;

}

if (y == 0) {

y += 1;

} else if (y == 34) {

y -= 1;

}

this.startx = ((int) Constant.rec.getX() + x * Constant.FOOD_WIDTH);

this.starty = ((int) Constant.rec.getY() + y * Constant.FOOD_HEIGHT);

this.snakeHead = new SNode(this.startx, this.starty, Color.GREEN);

nodes.add(snakeHead);

this.addNode(); // 默认是 2 个结点,需再增加 1 个结点

}

// 断定蛇是否与食物是否重叠:true: 重叠 ,false:不重叠

public boolean hit(SNode food) {

boolean result = false;

for (SNode snode : nodes) {

boolean res = snode.getRec().intersects(food.getRec());

if (res) {

result = true;

break;

}

}

return result;

}

// 吃食物

public boolean eat(SNode food) {

boolean result = false;

for (SNode snode : nodes) {

boolean res = snode.getRec().intersects(food.getRec());

if (res) {

result = true;

if (nodes.size() >= 2) {// 1. 初始相遇,2. 在挪动中相遇

this.addNode(); // 蛇的身材增长 1

}

break;

}

}

return result;

}

// 给蛇的尾部增加一个结点,与蛇方位无关

private void addNode() {

int size = nodes.size();

switch (dir) {

case Constant.L: // 向左走, 则左边增加第 2 个结点,且没有碰壁

if (size == 1) {// 蛇静止,须要增加一个结点到蛇尾

int x = this.startx + Constant.FOOD_WIDTH;

int y = this.starty;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(snode); // 增加到汇合开端

} else {

int x = this.startx – Constant.FOOD_WIDTH;

int y = this.starty;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(0, snode);

this.snakeHead = snode;

this.startx = x;

this.starty = y;

// 判断蛇头左越界

if (this.startx < Constant.rec.getX()) {

this.isLive = false;

}

}

break;

case Constant.R:

if (size == 1) {// 蛇静止,须要增加一个结点到蛇尾

int x = this.startx – Constant.FOOD_WIDTH;

int y = this.starty;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(snode); // 增加到汇合开端

} else {

int x = this.startx + Constant.FOOD_WIDTH;

int y = this.starty;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(0, snode);

this.snakeHead = snode;

this.startx = x;

this.starty = y;

// 判断蛇头右越界

if (this.startx > Constant.GAME_WIDTH) {

this.isLive = false;

}

}

break;

case Constant.U:

if (size == 1) {// 蛇静止,须要增加一个结点到蛇尾

int x = this.startx;

int y = this.starty + Constant.FOOD_HEIGHT;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(snode); // 增加到汇合开端

} else {

int x = this.startx;

int y = this.starty – Constant.FOOD_HEIGHT;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(0, snode);

this.snakeHead = snode;

this.startx = x;

this.starty = y;

// 判断蛇头上越界

if (this.starty < Constant.rec.getY()) {

this.isLive = false;

}

}

break;

case Constant.D:

if (size == 1) {// 蛇静止,须要增加一个结点到蛇尾

int x = this.startx;

int y = this.starty – Constant.FOOD_HEIGHT;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(snode); // 增加到汇合开端

} else {

int x = this.startx;

int y = this.starty + Constant.FOOD_HEIGHT;

// int y = this.starty + this.speed;

SNode snode = new SNode(x, y, Color.GREEN);

nodes.add(0, snode);

this.snakeHead = snode;

this.startx = x;

this.starty = y;

// 判断蛇头下越界

if (this.starty > ((int)Constant.rec.getY()+ Constant.GAME_HEIGHT-Constant.FOOD_HEIGHT)) {

this.isLive = false;

}

}

break;

}

}

public boolean isLive() {

return isLive;

}

// 蛇的挪动,一直变换蛇头,删除蛇尾

private void move() {

this.addNode(); // 再增加一个新结点,删除开端结点

int len = nodes.size();

nodes.remove(len – 1);

}

// 画蛇及蛇的挪动

public void paint(Graphics2D g2d) {

// 对 nodes 结点顺次绘制

g2d.setColor(this.snakeHead.getColor());

// 对蛇的身材进行绘制

for (SNode snode : nodes) {

g2d.fillRect(snode.getX(), snode.getY(), Constant.FOOD_WIDTH,

Constant.FOOD_HEIGHT);

}

this.move();

}

}

3,SNode 食物类

设计食物类也能够说是对蛇类的一个简化

import java.awt.Color;

import java.awt.Graphics2D;

import java.awt.Rectangle;

// 食物类的定义:

public class SNode {

private int x,y; // 食物的起始坐标,与游戏的起始点关联

private Color color; // 食物的色彩

private Rectangle rec; // 食物的矩形区域

public Color getColor() {

return color;

}

public int getX() { // 读取数据

return x;

}

public void setX(int x) {

this.x = x;

}

public int getY() {

return y;

}

public void setY(int y) {

this.y = y;

}

public Rectangle getRec() {

return rec;

}

public void setRec(Rectangle rec) {

this.rec = rec;

}

// 随机产生某个地位的食物

public SNode(Color color) {

this.x = (int)Constant.rec.getX()+this.generate(50)*Constant.FOOD_WIDTH;

this.y = (int)Constant.rec.getY()+this.generate(35)*Constant.FOOD_HEIGHT;

this.rec = new Rectangle(this.x, this.y, Constant.FOOD_WIDTH, Constant.FOOD_HEIGHT);

this.color = color;

}

// 生成固定地位的结点,用于产生蛇头

public SNode(int x,int y,Color color) {

this.x = x;

this.y = y;

this.color = color;

this.rec = new Rectangle(this.x, this.y, Constant.FOOD_WIDTH, Constant.FOOD_HEIGHT);

}

// 随机产生数字

public static int generate(int number) {//[0,numbder)

int x = 0;

x = (int)(Math.random()*number);

return x;

}

// 定义画食物的办法:基于图形缓存画法 Graphics2D

public void paint(Graphics2D g2d) {

g2d.setColor(this.color);

g2d.fillRect(this.x, this.y, Constant.FOOD_WIDTH, Constant.FOOD_HEIGHT);

}

public static void main(String[] args) {

}

}

4,Constant 常量类

对须要应用到的常量保留下来,不便对整个界面的批改

import java.awt.Rectangle;

public class Constant {

public static final int FOOD_WIDTH = 15; // 食物的宽度和高度

public static final int FOOD_HEIGHT = 15;

public static final int GAME_WIDTH = FOOD_WIDTH*50;

public static final int GAME_HEIGHT = FOOD_HEIGHT*35;

public static final int JFRAME_WIDTH = FOOD_WIDTH*52;

public static final int JFRAME_HEIGHT = FOOD_HEIGHT*38+6;

public static final int L=1,R=2,U=3,D=4;

public static final int SNAKE_NORMAL = 500;

public static final int SNAKE_ADD = 180;

public static final int SNAKE_SUPER = 50;

public static final int SNAKE_SUB = 850;

// 游戏方格区域

public static final Rectangle rec = new Rectangle(FOOD_WIDTH, FOOD_HEIGHT*2+6, GAME_WIDTH, GAME_HEIGHT);

}

退出移动版