package com.snake.controller;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class SnakeJPanel extends JPanel implements ActionListener{
private boolean start;//当前游戏状态
private boolean exist;//当前是否存在食物
private int foodType;//食物种类
private ArrayList<int[]> localList;//蛇
public String direction;//方向
private String direction2;//引导方向
Random rand = new Random();
private int score;//当前得分情况
private int num;//吃到的食物个数
// private Image offScreenImage; //图形缓存
public void paint(Graphics g) {
g.fillRect(0, 0, 900, 700);
// g.drawRect(25, 30, 800, 75);
title.paintIcon(this, g, 25, 10);
g.fillRect(25, 75, 850, 600);
if(!exist) {//如果当前不存在豆子,随机绘制一个豆子
boolean isProduce = true;
x = rand.nextInt(33) * 25 + 25;
y = rand.nextInt(23) * 25 + 75;
for (int[] arr:localList) {
if(x == arr[0] && y == arr[1]) {
System.out.println(x + "---" + y);
// g.fillRect(x, y, 25, 25);
g.drawImage(food.getImage(),x, y, 25, 25,null);
g.fillRect(x, y, 25, 25);
// g.drawImage(food.getImage(),x, y, 25, 25,null);
// g.fillRect(localList.get(0)[0], localList.get(0)[1], 25, 25);
if(direction.equals("R")) {
}else if(direction.equals("L")) {
}else if(direction.equals("U")) {
}else if(direction.equals("D")) {
// g.drawImage(head.getImage(), localList.get(0)[0], localList.get(0)[1], 25, 25,null);
head.paintIcon(this, g,localList.get(0)[0], localList.get(0)[1]);
for (int i = 1; i < localList.size(); i++) {
// g.fillRect(localList.get(i)[0], localList.get(i)[1], 25, 25);
// g.drawImage(body.getImage(), localList.get(i)[0], localList.get(i)[1], 25, 25,null);
body.paintIcon(this, g, localList.get(i)[0], localList.get(i)[1]);
// g.fillRect(localList.get(1)[0], localList.get(1)[1], 25, 25);
// g.fillRect(localList.get(2)[0], localList.get(2)[1], 25, 25);
g.setFont(new Font("宋体", Font.BOLD, 18));
g.drawString("长度:" + (localList.size() - 1), 25, 30);
g.drawString("分数:" + score, 25, 48);
if(!start) {//如果游戏未启动,结束移动和重绘
g.setFont(new Font("宋体", Font.BOLD, 30));
g.drawString("暂停/开始(请按任意键开始,空格键暂停)", 150, 300);
// //如果为JFrame 为重量级 程序不会调用update()方法
// //如果为Frame 为轻量级 重写update()方法 做双缓冲
// public void update(Graphics g)
// System.out.println("update");
// if(offScreenImage == null)
// offScreenImage = this.createImage(900, 700); //新建一个图像缓存空间,这里图像大小为800*600
// Graphics gImage = offScreenImage.getGraphics(); //把它的画笔拿过来,给gImage保存着
// paint(gImage); //将要画的东西画到图像缓存空间去
// g.drawImage(offScreenImage, 0, 0, null); //然后一次性显示出来
public void actionPerformed(ActionEvent e) {
// private void speed() {
// Thread.sleep(speed);//控制移动速度
// } catch (InterruptedException e) {
private void drawImage() {
up = new ImageIcon("images/4.png");
down = new ImageIcon("images/4.png");
right = new ImageIcon("images/4.png");
left = new ImageIcon("images/4.png");
body = new ImageIcon("images/4.png");
food = new ImageIcon("images/kun.jpg");
title = new ImageIcon("images/5.png");
if(localList.get(0)[0] == x && localList.get(0)[1] == y) {//如果当前蛇头吃到了豆子
System.out.println("eat");
score += (rand.nextInt(5) * 10 + 10);
int last = localList.size() - 1;//蛇尾
localList.add(new int[] {localList.get(last)[0],localList.get(last)[1]});
System.out.println("game over");
JOptionPane.showMessageDialog(null,"游戏已结束!");
if(flag && localList != null) {//如果长度不为空且游戏未结束
int last = localList.size() - 1;//记录蛇尾
for (int i = last; i > 0; i--) {//从蛇尾开始,每节身体移动到前一节身体的位置上
localList.set(i,new int[] {localList.get(i - 1)[0],localList.get(i - 1)[1]});
int[] local = localList.get(0);
//判断当前方向,并进行模拟移动,判断是否与边界重合
if(direction.equals("R")) {
}else if(direction.equals("L")) {
}else if(direction.equals("U")) {
}else if(direction.equals("D")) {
private boolean isbody() {
int x = localList.get(0)[0];
int y = localList.get(0)[1];
//判断当前方向,并进行模拟移动,判断是否与边界重合
if(direction.equals("R")) {
}else if(direction.equals("L")) {
}else if(direction.equals("U")) {
}else if(direction.equals("D")) {
for (int i = 1; i < localList.size(); i++) {
if(localList.get(i)[0] == x && localList.get(i)[1] == y) {
// private boolean isborder() {
// int x = localList.get(0)[0];
// int y = localList.get(0)[1];
// //判断当前方向,并进行模拟移动,判断是否与边界重合
// if(direction.equals("R")) {
// }else if(direction.equals("L")) {
// }else if(direction.equals("U")) {
// }else if(direction.equals("D")) {
// if(x < 25 || x > (33 * 25 + 25)) {
// return true;//当x坐标超出边界,则返回true
// if(y < 105 || y > (23 * 25 + 105)) {
// return true;//当y坐标超出边界,则返回true
// return false;//蛇头移动后未超出边界,返回false
public SnakeJPanel(int speed) {
this.speed = speed; //初始化速度
moveByKey();//给界面添加一个键盘监听
* 保证不会因为在短时间内快速变换方向导致蛇头逆向转向
private void moveByKey() {
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(!direction.equals("R")) {
if(!direction.equals("D")) {
if(!direction.equals("L")) {
if(!direction.equals("U")) {
case KeyEvent.VK_SPACE:{//如果当前键盘输入为空格
System.out.println("暂停/开始");
if(!start && key != KeyEvent.VK_SPACE) {//如果当前状态为暂停状态,且键盘输入不是空格
localList = new ArrayList<int[]>();
localList.add(0,new int[] {75,125});//蛇头
localList.add(1,new int[] {75,150});//蛇身1
localList.add(2,new int[] {75,175});//蛇身2
//通过循环保证当前生成的食物不在身体所在的坐标上
boolean isProduce = true;
while(isProduce) {//循环生成食物坐标
isProduce = false;//结束本次循环
x = rand.nextInt(33) * 25 + 25;
y = rand.nextInt(23) * 25 + 75;
for (int[] arr:localList) {//循环遍历蛇头及蛇身的坐标
if(x == arr[0] && y == arr[1]) {//如果食物坐标和蛇的某一节坐标重合
isProduce = true;//跳转循环状态,继续下一次食物生成
time = new Timer(speed, this);
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import com.snake.controller.SnakeJPanel;
public class Snakestart {
public static void main(String[] args) {
String showInputDialog = null;//初始化时间
showInputDialog = JOptionPane.showInputDialog("蛇移动速度(1 - 5)","3");
if(showInputDialog == null) {
showInputDialog = "3";//默认速度
if(showInputDialog.length() > 1) {
char[] a = showInputDialog.toCharArray();
if(a[0] >= '1' && a[0] <= '5') {
speed = Integer.parseInt(showInputDialog) * 50;
SnakeJPanel snakeJPanel = new SnakeJPanel(speed);
//创建一个JFrame窗口,将游戏面板添加进行窗口中
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.setSize(920, 750);
jFrame.setLocationRelativeTo(null);