先画好网格 游戏范围
public class Grid { //定义网格 public static int rows; //列数 public static int cols; //行数 public static int size; //格子大小 /** * 构造一个网格 * * @param rows 行数 * @param cols 列数 */ public Grid(int rows, int cols, int size) { this.rows = rows; this.cols = cols; this.size = size; } }再定义节点 根据节点来描述食物和蛇位置
public class Node { //定义节点 private int col; //col 列数 private int row; //row 行数 /** * 构造函数(初始化一个节点) * @param row * @param col */ public Node(int row,int col){ this.col = col; this.row = row; } /** * 拷贝构造函数 (用一个已经存在的对象复制出另一个对象) * @param node 待复制的节点 */ public Node(Node node) { this.row = node.getRow(); this.col = node.getCol(); } /** * 判断节点是否相等 * @param p * @return true-相等 false-不相等 */ public boolean isSame(Node p){ // return (p.col ==this.col && p.row ==this.row); } public int getCol() { return col; } public int getRow() { return row; } public void setCol(int col) { this.col = col; } public void setRow(int row) { this.row = row; } }
定义蛇这个类
import java.util.LinkedList; public class Snake { //蛇移动的方向 public static final byte LEFT = 1; public static final byte RIGHT = - 1; public static final byte UP = 2; public static final byte DOWN = - 2; public byte direction = RIGHT; //默认初始移动方向 public byte beforeDirection = RIGHT; private boolean isGrow = false; //默认不成长 public byte getDirection() { return direction; } public void setDirection( byte direction) { this. direction = direction; } private LinkedList<Node> snakeBody = new LinkedList<>(); //来一条蛇 /** * 初始化一条蛇 (位于左上角长度为4向右移动的蛇) */ public Snake(){ for ( int n = 1; n <= 4 ; n++) { Node node = new Node( 0, 4-n); snakeBody.add(node); } direction = RIGHT; } /** * 蛇的移动 */ public void move(){ /* 思路:加头去尾 * */ //加头:(1)复制当前的头 (2)根据方向跳整横坐标或纵坐标 // (3)插入到头部 Node head = snakeBody.getFirst(); //找到蛇头 Node newHead = new Node(head); switch ( direction){ case LEFT: //键盘改方向使蛇移动 newHead.setCol(newHead.getCol()- 1); break; case RIGHT: newHead.setCol(newHead.getCol()+ 1); break; case UP: newHead.setRow(newHead.getRow()- 1); break; case DOWN: newHead.setRow(newHead.getRow()+ 1); break; } snakeBody.addFirst(newHead); //移动的时候判断是否需要去尾(是否生长) if (! isGrow){ snakeBody.removeLast(); } else { isGrow = false; } } /** * 蛇的生长 */ public void grow(){ isGrow = true; } /** * 判断蛇是否吃到自己 * @return */ public boolean eatSelf(){ /** * 将蛇身的每个节点和舌头进行比较, * 只要有一个重合的则说明迟到了自己 */ Node head = snakeBody.getFirst(); //拿到蛇头 for ( int i = 1;i< snakeBody.size();i++){ //遍历循环和身体相比较 if ( snakeBody.get(i).isSame(head)){ return true; } } return false; } /** * 判断蛇是否撞到墙 * @return */ public boolean isCollide(){ if (getSnakeBody().getFirst().getCol()==Grid. cols||getSnakeBody().getFirst().getRow()==Grid. rows ||getSnakeBody().getFirst().getCol()< 0||getSnakeBody().getFirst().getRow()< 0){ return true; } return false; } public LinkedList<Node> getSnakeBody(){ return snakeBody; }}
定义食物这个类
import java.util.LinkedList; public class Food { //定义随机食物的点 private Node node; public Node getNode() { return node; } private static int x,y; // 写一个构造函数 public Food(Grid grid,Snake snake){ // 思路:(1)随机生成食物的位置(横纵坐标) (2) 判断食物有没有与蛇重叠 //(3)重复以上过程直到确定一个没有重叠的位置 while(true){ //随机生成一个横纵坐标 x = (int)(Math.random()*Grid.cols); y = (int)(Math.random()*Grid.rows); Node food = new Node(x,y); //判断是否与蛇身重叠 LinkedList<Node> body = snake.getSnakeBody(); boolean overlap = false; //蛇身与食物是否重叠的标记 for(Node node:body){ //遍历蛇的身体 if(food.equals(node)){ overlap = true; break; } } //如果没有重叠,则确定了位置,结束 if(!overlap){ this.node = food; break; } } } public int getX() { return x; } public int getY() { return y; } }定义游戏这个类 来操作游戏里的蛇
import javax.swing.*; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.LinkedList; public class Game { private Frame frame; //定义一个弹框 private Canvas canvas; //定义一个画布 private Graphics graphics; // 定义一个画笔 private Snake snake; //三个属性 成员 private Grid grid; private Food food; public Game(int rows, int cols, int size) { snake = new Snake(); //小程序.蛇 grid = new Grid(rows, cols, size); //网格 food = new Food(grid,snake); //食物 frame = new Frame("小程序/贪吃蛇"); //窗口名 frame.setSize(500, 500); //窗口大小 canvas = new Canvas(); //来一个新画布 frame.add(canvas); //把画布放在窗口里 frame.setVisible(true); //true-可见 false - 不可见 drawGrid(); //画出网格线 drawFood(); //画食物 drawSnake(); //画蛇 if (snake.eatSelf() || snake.isCollide()){ //如果蛇吃到自己或者碰到了墙游戏结束 int res=JOptionPane.showConfirmDialog(null, "是否继续游戏", "游戏结束", JOptionPane.YES_NO_OPTION); if(res==JOptionPane.YES_OPTION){ //点击“是”后执行这个代码块 }else{ System.exit(1); //点击“否”后执行这个代码块 return; } } if (isEatFood()){ //如果吃到了食物 蛇就生长 ,食物重新初始化 snake.grow(); food = new Food(grid,snake); } snake.move(); // 键盘事件 用来控制蛇的方向 canvas.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { handleKeyPress(e.getKeyCode()); } }); } /** * 画出网格线 游戏布局 */ public void drawGrid() { graphics = canvas.getGraphics(); graphics.setColor(Color.white); graphics.fillRect(0, 0, grid.rows * grid.size, grid.cols * grid.size); graphics.setColor(Color.BLACK); for (int i=0; i <= grid.rows; i++) { graphics.drawLine(0, i * grid.size, grid.rows * grid.size, i * grid.size); } for (int i = 0; i <= grid.cols; i++) { graphics.drawLine(i * grid.size, 0, i * grid.size, grid.cols * grid.size); } } /** * 判断蛇是否吃到食物 * @return 吃到食物 false-没有吃到食物 */ public boolean isEatFood(){ //拿到蛇的头部节点 Node head = snake.getSnakeBody().getFirst(); //判断蛇头的节点与食物的节点是否相等 return food.getNode().isSame(head); } /** * 画食物 */ public void drawFood() { drawNode(food.getNode(),Color.BLUE); /* graphics = canvas.getGraphics(); graphics.setColor(Color.RED); //拿到食物节点的坐标 graphics.fillRect(food.getX() * grid.size, food.getY() * grid.size, grid.size, grid.size); */ } /** * 画蛇 */ public void drawSnake() { LinkedList<Node> snakeBody = snake.getSnakeBody(); graphics = canvas.getGraphics(); for (int i = 0; i < snakeBody.size(); i++) { Node node = snakeBody.get(i); drawNode(node,0==i?Color.MAGENTA:Color.CYAN); // if (i == 0) { drawNode(node,Color.CYAN); } else { drawNode(node,Color.cyan); } } } /** * 绘制节点 * @param node 待绘制的节点 * @param color 待绘制的背景色 */ private void drawNode(Node node,Color color){ graphics = canvas.getGraphics(); graphics.setColor(color); graphics.fillRect(node.getCol() * grid.size, node.getRow() * grid.size, grid.size, grid.size); } /** *改变蛇的方向 * @param keyCode 按键键码 */ private void handleKeyPress(int keyCode) { int dir =snake.beforeDirection; switch (keyCode) { case KeyEvent.VK_SPACE: case KeyEvent.VK_LEFT: if (dir!= snake.RIGHT){ snake.setDirection(Snake.LEFT); snake.beforeDirection = snake.getDirection(); } break; case KeyEvent.VK_UP: //上 if (dir!= snake.DOWN){ snake.setDirection(Snake.UP); snake.beforeDirection = snake.getDirection(); } break; case KeyEvent.VK_RIGHT: // 右 if (dir!=snake.LEFT){ snake.setDirection(snake.RIGHT); snake.beforeDirection = snake.getDirection(); } break; case KeyEvent.VK_DOWN: // 下 if (dir!=snake.UP) { snake.setDirection(snake.DOWN); snake.beforeDirection = snake.getDirection(); } break; default: break; } } public static void main(String[] args) { Game game = new Game(25, 25, 20); game.start(); } public void start() { new Thread(){ @Override public void run() { LinkedList<Node> snakeBody = snake.getSnakeBody(); while (true) { snake.move(); //移动蛇 //如果蛇吃到自己或者碰到了墙游戏结束 if (snake.eatSelf() || snake.isCollide()){ int res=JOptionPane.showConfirmDialog(null, "是否继续游戏", "游戏结束", JOptionPane.YES_NO_OPTION); if(res==JOptionPane.YES_OPTION){ //点击“是”后执行这个代码块 System.out.println("重新2来过"); break; }else{ //点击“否”后执行这个代码块 System.exit(1); return; } } //如果吃到了食物 蛇就生长 if (isEatFood()){ snake.grow(); food = new Food(grid,snake); } drawGrid(); drawFood(); drawSnake(); try { //线程 延迟五百毫秒 也就是0.5秒动一下 sleep(150); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } }