再次重写贪吃蛇代码(多线程,有游戏的小地图)

/*
 *12.24日,完成了蛇撞到自己的检测.修改方法是在蛇的初始化的时候,用双循环来置FALSE;
 * 在重写代码的时候,我借鉴了别人的思路:将整个游戏的界面定义为一个布尔型的二维数组.
 * 用一个LinkedList来储存蛇.当蛇移动的时候,在蛇的头部增加一个节点,然后删除最后一个节点.
 * 因为只是做练习,所以没做游戏界面,比如菜单栏,计分栏什么的.
 */
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Game {
 public static void main(String args[]) {
  GameFrame frame = new GameFrame();
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  frame.setResizable(false);
  frame.show();
  JOptionPane.showMessageDialog(null, "上,下左,右控制蛇的方向/n回车开始,S暂停");
 }
}

class GameFrame extends JFrame {
 public GameFrame() {
  setSize(294, 482);
  setTitle("贪吃蛇DEMO");
  this.setLocation(360, 100);
  Container c = getContentPane();
  GamePanel panel = new GamePanel();
  c.add(panel, BorderLayout.CENTER);
 }
}

class GamePanel extends JPanel implements KeyListener {
 static int panelWidth = 294;

 static int panelHeight = 450;

 int rectX = 15;

 int rectY = 15;

 Snake snake;

 Node n;

 public GamePanel() {
  snake = new Snake(this, panelWidth / rectX, panelHeight / rectY);
  setBackground(Color.WHITE);
  setSize(panelWidth, panelHeight);
  setFocusable(true);
  addKeyListener(this);
 }

 public void paintComponent(Graphics g) {
  super.paintComponent(g);
  Graphics2D g2 = (Graphics2D) g;
  LinkedList list = snake.snakeList;
  Iterator it = list.iterator();
  g2.setColor(Color.black);
  while (it.hasNext()) {
   n = (Node) it.next();
   drawNode(g2, n);
  }
  g2.setColor(Color.ORANGE);
  Node f = snake.food;
  drawNode(g2, f);
  snake.draw(g2);// 绘制地图
 }

 public void keyPressed(KeyEvent e) {
  int keycode = e.getKeyCode();
  if (keycode == KeyEvent.VK_ENTER) {
   begin();
  } else if (keycode == KeyEvent.VK_UP) {
   snake.changeDirection(Snake.up);
  } else if (keycode == KeyEvent.VK_DOWN) {
   snake.changeDirection(Snake.down);
  } else if (keycode == KeyEvent.VK_LEFT) {
   snake.changeDirection(Snake.left);
  } else if (keycode == KeyEvent.VK_RIGHT) {
   snake.changeDirection(Snake.right);
  } else if (keycode == KeyEvent.VK_S) {
   Snake.run = false;
  }
 }

 public void keyReleased(KeyEvent e) {
 }

 public void keyTyped(KeyEvent e) {
 }

 public void drawNode(Graphics2D g, Node n) {
  g.fillRect(n.x * rectX, n.y * rectY, rectX - 2, rectY - 2);
 }

 public void begin() {
  Snake.run = true;
  SnakeThread thread = new SnakeThread(snake);
  thread.start();
 }
}

class Node {
 int x;

 int y;

 public Node(int x, int y) {
  this.x = x;
  this.y = y;
 }
}

class SnakeThread extends Thread {
 Snake snake;

 public SnakeThread(Snake s) {
  snake = s;
 }

 public void run() {
  Snake.run = true;
  while (Snake.run) {
   try {
    snake.move();
    sleep(200);
   } catch (InterruptedException e) {
   }
  }
  Snake.run = false;
 }
}

class Snake {
 GamePanel panel;

 Node food;

 boolean[][] all;

 public static boolean run;

 int maxX;

 int maxY;

 public static int left = 1;

 public static int up = 2;

 public static int right = 3;

 public static int down = 4;

 int direction = 4;

 LinkedList snakeList = new LinkedList();

 public Snake(GamePanel p, int maxX, int maxY) {
  panel = p;
  this.maxX = maxX;
  this.maxY = maxY;
  all = new boolean[maxX][maxY];
  for (int i = 0; i < maxX; i++) {
   for (int j = 0; j < maxY; j++) {
    all[i][j] = false;
   }
  }
  int arrayLength = maxX > 20 ? 10 : maxX / 2;
  for (int i = 0; i < arrayLength; i++) {
   int x = maxX / 10 + i;
   int y = maxY / 10;
   snakeList.addFirst(new Node(x, y));
   all[x][y] = true;
  }
  food = createFood();
  all[food.x][food.y] = true;
 }

 public void move() {
  Node n = (Node) snakeList.getFirst();
  int x = n.x;
  int y = n.y;

  if (direction == 3) {
   x++;
  } else if (direction == 4) {
   y++;
  } else if (direction == 1) {
   x--;
  } else if (direction == 2) {
   y--;
  }

  if ((0 <= x && x <= GamePanel.panelWidth / 15 - 1)
    && (0 <= y && y <= GamePanel.panelHeight / 15 - 1)) {
   if (all[x][y]) {
    if (x == food.x && y == food.y) {
     snakeList.addFirst(food);
     food = createFood();
     all[food.x][food.y] = true;
    } else {
     JOptionPane.showMessageDialog(null, "你撞到自己了");
     System.exit(0);
    }
   } else {
    snakeList.addFirst(new Node(x, y));
    all[x][y] = true;
    Node l = (Node) snakeList.getLast();
    snakeList.removeLast();
    all[l.x][l.y] = false;
   }
  } else {
   JOptionPane.showMessageDialog(null, "越界了,游戏结束");
   System.exit(0);
  }
  panel.repaint();
 }

 public Node createFood() {
  int x = 0;
  int y = 0;
  do {
   Random r = new Random();
   x = r.nextInt(maxX - 10);
   y = r.nextInt(maxY - 10);

  } while (all[x][y]);
  return new Node(x, y);
 }

 public void changeDirection(int newDirection) {
  if (direction % 2 != newDirection % 2) {
   direction = newDirection;
  }
 }

 public void draw(Graphics2D g) {
  for (int i = 0; i < maxX; i++) {
   for (int j = 0; j < maxY; j++) {
    if (all[i][j] == true) {
     g.setColor(Color.red);
     g.fillRect(i, j, 4, 4);
    }
   }
  }
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

低音钢琴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值