2020-12-26

项目3 Java实现迷宫小游戏源代码

package dong.MyMigong;
import java.awt.Color;

import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import java.util.Stack;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

class grid {//构造函数设置是否可以走的路径初始值
  static final int going1 = 1;//可以前进
  static final int ungoing = 0;//不可以前进
  public static int going;
  private int x = -1;//定义x坐标
  private int y = -1;//定义y坐标
  private int flag = ungoing;//表示遍历节点的标志位
  private grid father = null;//下一个节点的前继节点
  public grid(int xx, int yy) {//初始化格子大小
    x = xx;
    y = yy;
  }
  public int getX() {//建立x坐标
    return x;
  }
  public int getY() {//建立y坐标
    return y;
  }
  public int getFlag() {
    return flag;
  }
  public grid getFather() {
    return father;
  }
  public void setFather(grid f) {
    father = f;
  }
  public void setFlag(int f) {
    flag = f;
  }
  public String toString() {
    return new String("(" + x + "," + y + ")\n");//获取坐标确定方向
  }
}
public class Maze extends JPanel {//设置界面控制台
  private static final long serialVersionUID = -8300339045454852626L;
  private int NUM, width, padding;// width 每个格子的宽度和高度
  private grid[][] maze;//用二维数组存放地图中的格子
  private int ballX, ballY;//定义出发位置
  private boolean drawPath = false;//路径不可以改变
  Maze(int m, int wi, int p) {//构造函数初始化格子
    NUM = m;
    width = wi;
    padding = p;
    maze = new grid[NUM][NUM];
    for (int i = 0; i <= NUM - 1; i++)
      for (int j = 0; j <= NUM - 1; j++)
        maze[i][j] = new grid(i, j);//遍历完数组之后再赋值
    createMaze();
    setKeyListener();//设置监听通过键盘控制方向
    this.setFocusable(true);
  }
  private void init() {//初始化迷宫
    for (int i = 0; i <= NUM - 1; i++)
      for (int j = 0; j <= NUM - 1; j++) {
        maze[i][j].setFather(null);
        maze[i][j].setFlag(grid.ungoing);
      }
    ballX = 0;
    ballY = 0;
    drawPath = false;
    createMaze();
    // setKeyListener();
    this.setFocusable(true);
    repaint();
  }
  public int getCenterX(int x) {//获取格子的中间X坐标
    return padding + x * width + width / 2;
  }
  public int getCenterY(int y) {//获取每个格子中间的Y坐标
    return padding + y * width + width / 2;
  }
 
  public int getCenterX(grid p) {
    return padding + p.getY() * width + width / 2;
  }
  public int getCenterY(grid p) {
    return padding + p.getX() * width + width / 2;
  }
  private void checkIsWin() {//检查是否走出成功
    if (ballX == NUM - 1 && ballY == NUM - 1) {
      JOptionPane.showMessageDialog(null, "逃脱成功!", "恭喜走出迷宫。",
          JOptionPane.PLAIN_MESSAGE);
      init();
    }
  }
  synchronized private void move(int c) {//键盘控制的四个移动方向
    int tx = ballX, ty = ballY;
    // System.out.println(c);
    switch (c) {
      case KeyEvent.VK_LEFT :
        ty--;
        break;
      case KeyEvent.VK_RIGHT :
        ty++;
        break;
      case KeyEvent.VK_UP :
        tx--;
        break;
      case KeyEvent.VK_DOWN :
        tx++;
        break;
      case KeyEvent.VK_SPACE :
        if (drawPath == true) {
          drawPath = false;
        } else {
          drawPath = true;
        }
        break;
      default :
    }
    if (!isOutOfBorder(tx, ty)//判断是否出界
        && (maze[tx][ty].getFather() == maze[ballX][ballY]
            || maze[ballX][ballY].getFather() == maze[tx][ty])) {
      ballX = tx;
      ballY = ty;
    }
  }
  private void setKeyListener() {//设置监听事件
    this.addKeyListener(new KeyAdapter() {
      public void keyPressed(KeyEvent e) {
        int c = e.getKeyCode();
        move(c);
        repaint();
        checkIsWin();
 
      }
    });
  }
  private boolean isOutOfBorder(grid p) {//判断可走路径
    return isOutOfBorder(p.getX(), p.getY());
  }
  private boolean isOutOfBorder(int x, int y) {
    return (x > NUM - 1 || y > NUM - 1 || x < 0 || y < 0) ? true : false;
  }
  private grid[] getNeis(grid p) {//设置可走路径
    final int[] adds = {-1, 0, 1, 0, -1};// 顺序为上右下左
    if (isOutOfBorder(p)) {
      return null;
    }
    grid[] ps = new grid[4];// 顺序为上右下左
    int xt;
    int yt;
    for (int i = 0; i <= 3; i++) {
      xt = p.getX() + adds[i];
      yt = p.getY() + adds[i + 1];
      if (isOutOfBorder(xt, yt))
        continue;
      ps[i] = maze[xt][yt];
    }
    return ps;
  }
  private void createMaze() {//构建迷宫
    Random random = new Random();
    int rx = Math.abs(random.nextInt()) % NUM;//随机生成小圆点x坐标
    int ry = Math.abs(random.nextInt()) % NUM;//随机生成小圆点有坐标
    Stack<grid> s = new Stack<grid>();
    grid p = maze[rx][ry];//更新坐标
    grid neis[] = null;
    s.push(p);
    while (!s.isEmpty()) {//检查是否遍历完成
      p = s.pop();
      p.setFlag(grid.going1);
      neis = getNeis(p);
      int ran = Math.abs(random.nextInt()) % 4;
      for (int a = 0; a <= 3; a++) {
        ran++;
        ran %= 4;
        if (neis[ran] == null || neis[ran].getFlag() == grid.going1)
          continue;
        s.push(neis[ran]);
        neis[ran].setFather(p);
      }
    }
    // changeFather(maze[0][0],null);
  }
  @SuppressWarnings("unused")
private void changeFather(grid p, grid f) {//改变该节点的前继节点,寻找该节点的下一个前继节点
    if (p.getFather() == null) {
      p.setFather(f);
      return;
    } else {
      changeFather(p.getFather(), p);
    }
  }
  private void clearFence(int i, int j, int fx, int fy, Graphics g) {
    int sx = padding + ((j > fy ? j : fy) * width),
        sy = padding + ((i > fx ? i : fx) * width),
        dx = (i == fx ? sx : sx + width),
        dy = (i == fx ? sy + width : sy);
    if (sx != dx) {
      sx++;
      dx--;
    } else {
      sy++;
      dy--;
    }
    g.drawLine(sx, sy, dx, dy);//寻找下一个节点完毕
  }
  protected void paintComponent(Graphics g) {//重新绘制此容器中的每个组件
    super.paintComponent(g);//调用父类中的方法
    for (int i = 0; i <= NUM; i++) {
      g.drawLine(padding + i * width, padding, padding + i * width,
          padding + NUM * width);
    }
    for (int j = 0; j <= NUM; j++) {
      g.drawLine(padding, padding + j * width, padding + NUM * width,
          padding + j * width);
    }
    g.setColor(this.getBackground());
    for (int i = NUM - 1; i >= 0; i--) {
      for (int j = NUM - 1; j >= 0; j--) {
        grid f = maze[i][j].getFather();
        if (f != null) {
          int fx = f.getX(), fy = f.getY();
          clearFence(i, j, fx, fy, g);
        }
      }
    }
    g.drawLine(padding, padding + 1, padding, padding + width - 1);
    int last = padding + NUM * width;
    g.drawLine(last, last - 1, last, last - width + 1);
    g.setColor(Color.BLACK);//小圆点为黑色
    g.fillOval(getCenterX(ballY) - width / 3, getCenterY(ballX) - width / 3,
        width / 2, width / 2);
    if (drawPath == true)
      drawPath(g);
  }
  private void drawPath(Graphics g) {//使用此方法绘制可寻走的路径
    Color PATH_COLOR = Color.GREEN, BOTH_PATH_COLOR = Color.YELLOW;
    if (drawPath == true)
      g.setColor(PATH_COLOR);
    else
      g.setColor(this.getBackground());
   grid p = maze[NUM - 1][NUM - 1];
    while (p.getFather() != null) {
      p.setFlag(2);
      p = p.getFather();
    }
    g.fillOval(getCenterX(p) - width / 3, getCenterY(p) - width / 3,
        width / 2, width / 2);
    p = maze[0][0];
    while (p.getFather() != null) {
      if (p.getFlag() == 2) {
        p.setFlag(3);
        g.setColor(BOTH_PATH_COLOR);
      }
      g.drawLine(getCenterX(p), getCenterY(p), getCenterX(p.getFather()),
          getCenterY(p.getFather()));
      p = p.getFather();
    }
    g.setColor(PATH_COLOR);
    p = maze[NUM - 1][NUM - 1];
    while (p.getFather() != null) {
      if (p.getFlag() == 3)
        break;
      g.drawLine(getCenterX(p), getCenterY(p), getCenterX(p.getFather()),
          getCenterY(p.getFather()));
      p = p.getFather();
    }
  }
  public static void main(String[] args) {
    final int n = 30, width = 600, padding = 20, LX = 200, LY = 100;
    JPanel p = new Maze(n, (width - padding - padding) / n, padding);
    JFrame frame = new JFrame("我的迷宫小游戏");
    frame.getContentPane().add(p);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(width + padding, width + padding + padding);
    frame.setLocation(LX, LY);
    frame.setVisible(true);
  }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值