java 数据结构 迷宫_想知道Java数据结构用范型如何实现迷宫问题?

两天前看的问题,今天总算做出来了.当然,是利用的下班后和午休时间来做的这题.码农996不容易的.

从题意来看,就是利用栈(Stack)结构加上泛型来解决迷宫问题.如果说问题本身的话,其实没什么难的,无非就是利用栈来代替递归来实现寻址.基本上能写递归就能做这题了.

那有人可能问了,说起来简单,那你还花两天时间?其实呢,这两天时间我主要花在了别的方面,比如,生成迷宫,并将其在控制台中画出来.这样这题才会显得有趣一些么不是.

第一步,实现迷宫类

迷宫就是由一堆小格子(Cell)组成的,所以我们先定义Cell,节省版面,我把getter和setter去掉了:

public class Cell {

private boolean w;

private boolean e;

private boolean n;

private boolean s;

}

然后是迷宫类,里面是一堆小格子:

import java.util.LinkedList;

public class Migong {

private Cell[][] cells = null;

}

这里呢,我用CellGen类来随机创建迷宫里的小格子:

import java.util.*;

public class CellsGen {

public static Cell[][] random(int row, int col) {

Cell[][] cells = new Cell[row][col];

for (int i = 0; i < cells.length; i++) {

for (int j = 0; j < cells[i].length; j++) {

cells[i][j] = new Cell();

}

}

breakWalls(cells, row, col);

return cells;

}

private static void breakWalls(Cell[][] cells, int maxRow, int maxCol) {

// 利用算法将小格子的墙打破,形成迷宫;具体代码这里就不贴了,没优化过,太长太繁琐 }

}

第二步,迷宫的展示

主要是在控制台中展示迷宫,这里我利用了制表符号,这两天工作之余的时间主要就是在算这个了

private static final char FULL_SPACE = ' ';

private static StringBuilder toStringBuilder(Cell[][] cells) {

StringBuilder sline = new StringBuilder();

int maxRow = 0;

int maxCol = 0;

for (int r = 0; r < cells.length; r++) {

maxRow = cells.length;

for (int c = 0; c < cells[r].length; c++) {

maxCol = cells[r].length;

if (c == 0) {

if (r == 0) {

sline.append('┌');

} else {

sline.append('├');

}

} else {

if (r == 0) {

sline.append('┬');

} else {

sline.append('┼');

}

}

if (cells[r][c].isN()) {

sline.append(FULL_SPACE);

} else {

sline.append("─");

}

if (c == cells[r].length - 1) {

if (r == 0) {

sline.append('┐');

} else {

sline.append('┤');

}

}

}

sline.append("\n");

for (int c = 0; c < cells[r].length; c++) {

if (cells[r][c].isW()) {

sline.append(FULL_SPACE);

} else {

sline.append("│");

}

sline.append(FULL_SPACE);

if (c == cells[r].length - 1) {

sline.append('│');

}

}

sline.append("\n");

if (r == cells.length - 1) {

for (int c = 0; c < cells[r].length; c++) {

if (c == 0) {

sline.append('└');

} else {

sline.append('┴');

}

sline.append("─");

if (c == cells[r].length - 1) {

sline.append("┘");

}

}

}

}

// ☆★ int index = ((maxCol) * 2 + 2) + 1;

sline.replace(index, index + 1, "☆");

index = (maxRow * 2 - 1) * ((maxCol) * 2 + 2) + maxCol * 2 - 1;

sline.replace(index, index + 1, "★");

return sline;

}

效果还是挺好的.Windows下用新宋体查看效果更好:

┌─┬─┬─┬─┬─┬─┬─┐

│☆      │     │

├─┼─┼─┼ ┼ ┼─┼ ┤

│       │ │   │

├ ┼─┼─┼─┼ ┼ ┼─┤

│ │ │ │ │ │   │

├ ┼─┼─┼─┼ ┼─┼ ┤

│ │ │ │ │ │ │ │

├ ┼─┼─┼─┼─┼ ┼ ┤

│   │ │ │ │   │

├─┼ ┼─┼─┼─┼ ┼─┤

│ │   │ │   │ │

├─┼─┼ ┼─┼ ┼─┼ ┤

│ │ │ │ │ │   │

├─┼─┼ ┼─┼ ┼─┼ ┤

│ │ │        ★│

└─┴─┴─┴─┴─┴─┴─┘

这个是新宋体下的效果:

第三步,寻址算法

这个就是本题的主要问题了.

先定义栈的接口和实现类,实现类我偷懒了,本来应该用数组的(出题人应该就是想考察数组实现栈吧)

public interface MyStack {

T pop();

T peek();

void push(T t);

}

实现类,就是这么个意思吧.

import java.util.ArrayList;

import java.util.List;

public class MySequentialStack implements MyStack {

private final List list = new ArrayList<>();

@Override

public T pop() {

if (!list.isEmpty()) {

return list.remove(list.size() - 1);

}

return null;

}

public T peek() {

if (!list.isEmpty()) {

return list.get(list.size() - 1);

}

return null;

}

@Override

public void push(T t) {

list.add(t);

}

}

然后是寻址算法, 放在Migong类里面,因为要存储x/y坐标,所以我用了一个Point类,和题目里要求的Point类不是同一个意思(题目里的被我换成了Cell).主要思路就是遍历所有的可能路径,直到走到终点.(好像是废话,具体还是看代码吧)

public void findPaths() {

if (cells == null) {

return;

}

int maxRow = cells.length;

int maxCol = 0;

if (maxRow > 0) {

maxCol = cells[0].length;

}

MyStack pointStack = new MySequentialStack<>();

pointStack.push(new Point(0, 0));

Point point = null;

char lastTriedDirection = ' ';

while ((point = pointStack.pop()) != null) {

if (point.getX() == maxCol - 1 && point.getY() == maxRow - 1) {

paths = new LinkedList<>();

do {

paths.addFirst(point);

} while ((point = pointStack.pop()) != null);

return;

}

Cell cell = cells[point.getY()][point.getX()];

char fromDirection = direction(pointStack.peek(), point);

Point next = null;

if (lastTriedDirection < 'e' && cell.isE() && fromDirection != 'e') {

next = new Point(point.getX() + 1, point.getY());

}

if (lastTriedDirection < 'n' && next == null && cell.isN() && fromDirection != 'n') {

next = new Point(point.getX(), point.getY() - 1);

}

if (lastTriedDirection < 's' && next == null && cell.isS() && fromDirection != 's') {

next = new Point(point.getX(), point.getY() + 1);

}

if (lastTriedDirection < 'w' && next == null && cell.isW() && fromDirection != 'w') {

next = new Point(point.getX() - 1, point.getY());

}

if (next == null) {

lastTriedDirection = direction(point, pointStack.peek());

} else {

pointStack.push(point);

pointStack.push(next);

lastTriedDirection = ' ';

}

}

}

private char direction(Point from, Point to) {

if (from == null || to == null) {

return ' ';

}

if (from.getX() > to.getX()) {

return 'e';

}

if (from.getX() < to.getX()) {

return 'w';

}

if (from.getY() > to.getY()) {

return 's';

}

if (from.getY() < to.getY()) {

return 'n';

}

return ' ';

}

第四步,输出路径

具体代码这里就不贴了,也是占了大头的琢磨时间.

直接贴效果图吧,同样,用新宋体看是最舒服的.

源码我扔到github上了:https://github.com/minghua-li/zhihu-migong​github.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值