java写贪吃蛇
两个包:GamePanel和Snake
import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JPanel; public class GamePanel extends JPanel { private static final long serialVersionUID = 1L; Snake snakehead = null;// 蛇头 Snake snakebody = null;// 蛇身 Snake food = null;// 食物 static JFrame mf = null;// 主窗体 GameThread gt = new GameThread();// 主线程 ArrayList<Point> snakeroad = new ArrayList<>();// 蛇走过的路径数组 ArrayList<Snake> snakes = new ArrayList<>();// 蛇头及蛇身的数组 static int width = 600;// 窗体大小 int row = width / 20;// 按窗体大小及蛇的大小分成上下左右各30格 int col = row; int step = 1;// 蛇每次移动间隔 int threadspeed = 150;// 主线程sleep间隔 int score = 0; // 分数 boolean dir = false;// 蛇移动方向 boolean gameflag = false;// 游戏暂停或开始判断 boolean dead = false;// 游戏失败判断 // 构造函数 public GamePanel() { setBounds(0, 0, width, width);// 窗体大小 setOpaque(false);// 窗体透明 createKeyListener();// 监听键盘 gt.start();// 线程开始 init();// 初始化 } // 入口 public static void main(String[] args) { mf = new JFrame();// frame实例化 mf.setSize(width + 18, width + 15 + 30);// frame大小 mf.setLocationRelativeTo(null);// 屏幕居中显示 mf.setLayout(null);// 布局无 mf.setTitle("Sanke");// 标题 mf.setResizable(false);// 不可放大 mf.getContentPane().setBackground(new Color(0, 139, 0));// 设置背景色 GamePanel gp = new GamePanel();// panel实例化 mf.add(gp);// panel加入frame mf.setVisible(true);// 显示frame } // 初始化 void init() { // 蛇头存在就产生身体 if (snakes.size() > 0) { snakebody = new Snake(snakes.get(snakes.size() - 1).x, snakes.get(snakes.size() - 1).y, this); snakes.add(snakebody); } else { snakehead = new Snake(1, 1, this);// 蛇头实例化 snakes.add(snakehead); } // food随机产生 food = new Snake((int) (Math.random() * row), (int) (Math.random() * row), this); } // 画蛇,食物,提示 @Override public void paint(Graphics g) { super.paint(g); // 蛇头 if (snakes != null) { snakes.get(0).drawhead(g); } // 蛇身体 if (snakes != null) { for (int i = 1; i < snakes.size(); i++) { snakes.get(i).draw(g); } } // food if (food != null) { food.drawfood(g); } // 游戏失败提示 if (dead) { g.setColor(new Color(255, 255, 255, 255)); g.setFont(new Font("仿宋", Font.BOLD, 30)); g.drawString("游戏失败!按“空格键”继续", width / 2 - 180, width / 2); } // 游戏暂停提示 if (!gameflag) { g.setColor(new Color(255, 255, 255, 255)); g.setFont(new Font("仿宋", Font.BOLD, 30)); g.drawString("游戏暂停!按“P”键开始", width / 2 - 170, width / 2); } // 分数和速度显示 g.setFont(new Font("Arial", Font.BOLD, 14)); g.setColor(new Color(255, 255, 255, 255)); g.drawString("SCORE", 3, width - 5); g.drawString(String.valueOf(score), 60, width - 5);// 显示分数 g.drawString("SPEED", 100, width - 5); g.drawString(String.valueOf(threadspeed), 155, width - 5);// 显示速度 g.setFont(new Font("仿宋", Font.BOLD, 14)); g.drawString("按“R”重新开始游戏", width - 150, width - 5);// 重新开始游戏 //画格子 for(int i=0;i<row;i++) { for(int j=0;j<col;j++) { g.setColor(new Color(173,216,230,25)); g.drawRect(j*20, i*20, 20, 20); } } repaint(); } // 主线程 class GameThread extends Thread { @Override public void run() { while (true) { try { Thread.sleep(threadspeed);// 间隔150毫秒 } catch (InterruptedException e) { e.printStackTrace(); } if (snakehead != null & !dead & gameflag) { // 蛇头移动坐标录入snakeroad数组 snakeroad.add(new Point(snakehead.x, snakehead.y)); if (snakeroad.size() == snakes.size()) { snakeroad.remove(0);// 控制snakeroad数组长度 } // 蛇移动 snakehead.movebody(dir, step); outofBoard();// 边界穿透 dead();// 游戏失败判断 hit();// 吃food判断 } } } } // 边界穿透 void outofBoard() { Snake snake = null; // 四边界限 for (int i = 0; i < snakes.size(); i++) { snake = snakes.get(i); if (snake.getY() < 0) { snake.setY(row - 1); } else if (snake.getY() > row - 1) { snake.setY(0); } else if (snake.getX() < 0) { snake.setX(row - 1); } else if (snake.getX() > row - 1) { snake.setX(0); } } } // 吃food void hit() { if (food.getX() == snakehead.x & food.getY() == snakehead.y) { init();// 新增food和蛇加长 score++;// 分数增加 } } // 蛇头碰到蛇身体则失败 void dead() { for (int i = 0; i < snakes.size(); i++) { for (int j = 0; j < snakes.size(); j++) { if (i != j) { if (snakes.get(j).getX() == snakes.get(i).getX() && snakes.get(j).getY() == snakes.get(i).getY()) { dead = true; } } } } } // 重新开始游戏 void restart() { snakehead = null; food = null; snakes.clear(); snakeroad.clear(); threadspeed = 150; score = 0; dir = false; gameflag = false; dead = false; init(); } // 键盘监听 private void createKeyListener() { KeyAdapter l = new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch (key) { case KeyEvent.VK_P:// 按p键控制游戏暂停或开始 if (!gameflag) { gameflag = true; } else { gameflag = false; } break; // 空格 case KeyEvent.VK_SPACE: dead = false; break; // 向上 case KeyEvent.VK_UP: case KeyEvent.VK_W: dir = false; step=-1; break; // 向右 case KeyEvent.VK_D: case KeyEvent.VK_RIGHT: dir = true; step=1; break; // 向下 case KeyEvent.VK_S: case KeyEvent.VK_DOWN: dir = false; step=1; break; // 向左 case KeyEvent.VK_A: case KeyEvent.VK_LEFT: dir = true; step=-1; break; case KeyEvent.VK_1: threadspeed += 5;// 按1速度减慢5 break; case KeyEvent.VK_2: if (threadspeed > 0) { threadspeed -= 5;// 按2速度加快5 } break; case KeyEvent.VK_R: restart(); break; } } }; mf.addKeyListener(l);// 主窗体增加键盘监听 } }
import java.awt.Color; import java.awt.Graphics; public class Snake { private GamePanel panel = null; int x = 0; int y = 0; public Snake(int x, int y, GamePanel panel) { this.x = x; this.y = y; this.panel = panel; } // 画蛇身 void draw(Graphics g) { g.setColor(new Color(255, 255, 255)); g.fillRect(x * 20, y * 20, 19, 19); } // 画食物 void drawfood(Graphics g) { g.setColor(new Color(255, 255, 255,255)); g.fillOval(x * 20+5, y * 20+5, 10, 10); } // 画蛇头 void drawhead(Graphics g) { g.setColor(new Color(255, 0, 0)); g.fillRect(x * 20, y * 20, 19, 19); } // 蛇头移动 void move(boolean dir, int step) { if (dir) { x+=step; }else { y+=step; } panel.repaint(); } //蛇移动 public void movebody(Boolean dir, int step) { // 蛇头移动 panel.snakehead.move(dir, step); // 蛇身移动 for (int i = 1; i < panel.snakes.size(); i++) { panel.snakes.get(i).x = panel.snakeroad.get(panel.snakeroad.size()-i).x; panel.snakes.get(i).y = panel.snakeroad.get(panel.snakeroad.size()-i).y; } panel.repaint(); } 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; } }