【发布时间】:2018-01-31 00:43:58
【问题描述】:
我正在构建一个通过矩阵 (nxn) 运行的程序,以避免与某些障碍物发生碰撞。我在实现适用于所有可能的碰撞情况的通用算法时遇到问题,最终目标是遍历矩阵的所有点。
我构建的算法是循环的,无法完成矩阵。
注意:红色方块可以向任意方向移动(水平、垂直和对角线移动),但一次只能移动一个单元格(正方形)。
var WALL = 0;
var started = false;
var gridSize = 20;
class Agent {
constructor(x, y, charge, cap, distance) {
this.x = x;
this.y = y;
this.charge = charge;
this.cap = cap;
this.distance = distance;
}
}
$(function() {
var $grid = $("#search_grid");
var opts = {
gridSize: 20
};
var grid = new GraphSearch($grid, opts);
//Initializes the agent
$("#btnInit").click(function() {
if (!started) {
var agent = new Agent(0, 0, 100, 50, 0);
agent.initialize();
started = true;
}
});
});
//Initializes the matrix
function GraphSearch($graph, options) {
this.$graph = $graph;
this.opts = options;
this.initialize();
}
//Initializes the matrix
GraphSearch.prototype.initialize = function() {
this.grid = [];
$graph = this.$graph;
$graph.empty();
var cellWidth = ($graph.width() / this.opts.gridSize) - 2,
cellHeight = ($graph.height() / this.opts.gridSize) - 2,
lineHeight = (this.opts.gridSize >= 30 ? "9.px" : ($graph.height() / this.opts.gridSize) - 10 + "px"),
fontSize = (this.opts.gridSize >= 30 ? "10px" : "20px");
$cellTemplate = $("<span />").addClass("grid_item").width(cellWidth).height(cellHeight).css("line-height", lineHeight).css("font-size", fontSize);
for (var x = 0; x < this.opts.gridSize; x++) {
var $row = $("<div class='row' />");
for (var y = 0; y < this.opts.gridSize; y++) {
var id = "cell_" + x + "_" + y,
$cell = $cellTemplate.clone();
$cell.attr("id", id).attr("x", x).attr("y", y);
$row.append($cell);
var isWall = addWall(x, y, this.opts.gridSize);
if (isWall === 1) {
$cell.addClass("wall");
} else {
$cell.addClass('weight1');
}
}
$graph.append($row);
//Fix for stackoverflow snippet
if ($(window).width() < 700) {
$("#search_grid").css("width", "320px");
$("#main").css("width", "38%");
} else {
$("#search_grid").css("width", "300px");
$("#main").css("width", "20%");
}
}
};
//Where will be wall in the matrix
addWall = function(x, y, size) {
var limitPointLeftUp = [2, 3];
var limitPointRightUp = [2, size - 4];
var limitPointLeftDown = [size - 4, 2];
var limitPointRightDown = [size - 4, size - 4];
if ((x == 2 && y == 2) || (x == 2 && y == size - 3)) {
return 1;
}
if ((x == size - 3 && y == 2) || (x == size - 3 && y == size - 3)) {
return 1;
}
if (x >= 2 && (y == 3 && x >= limitPointLeftUp[0] && x <= limitPointLeftDown[0] + 1)) {
return 1;
}
if (x >= 2 && (y == size - 4 && x >= limitPointRightUp[0] && x <= limitPointRightDown[0] + 1)) {
return 1;
}
if ((x == 1 && y == 5) || (x == 9 && y == 17) || (x == 6 && y == 0) || (x == 9 && y == 7) || (x == 15 && y == 0) || (x == 15 && y == 2) || (x == 18 && y == 15)) {
return 1;
}
}
//Initializes the agent
Agent.prototype.initialize = function() {
var agent = this;
var lastDir = "right";
var tryTo = "";
var trying = false;
var right = true;
var up = false;
var down = false;
var left = false;
var timerId = 0;
//Simulates agent movement [Here is my problem]
timerId = setInterval(function() {
RemoveAgent();
var cell = $("#search_grid .row .grid_item[x=" + agent.x + "][y=" + agent.y + "]");
cell.css("background-color", "#e2e2e2");
cell.addClass("agent");
//start direction: right
if (right) {
lastDir = "right";
if (tryTo == "down" && trying) {
if (EmptySqm(agent.x + 1, agent.y)) {
trying = false;
right = false;
down = true;
agent.x++;
}
} else if (tryTo == "up" && trying) {
if (EmptySqm(agent.x - 1, agent.y)) {
trying = false;
right = false;
up = true;
agent.x--;
}
}
if (right) {
//check if is valid sqm
if (ValidSqm(agent.x, agent.y + 1)) {
//go right if empty
if (EmptySqm(agent.x, agent.y + 1)) {
agent.y++;
} else {
right = false;
//check up sqm
if (EmptySqm(agent.x - 1, agent.y)) {
up = true;
trying = true;
}
//check down
else if (EmptySqm(agent.x + 1, agent.y)) {
down = true;
trying = true;
}
}
} else {
agent.x++;
right = false;
left = true;
}
}
//left direction
} else if (left) {
lastDir = "left";
if (tryTo == "down" && trying) {
if (EmptySqm(agent.x + 1, agent.y)) {
trying = false;
left = false;
down = true;
agent.x++;
}
} else if (tryTo == "up" && trying) {
if (EmptySqm(agent.x - 1, agent.y)) {
trying = false;
left = false;
up = true;
agent.x--;
}
}
if (left) {
if (ValidSqm(agent.x, agent.y - 1)) {
if (EmptySqm(agent.x, agent.y - 1)) {
agent.y--;
} else {
left = false;
if (EmptySqm(agent.x + 1, agent.y)) {
down = true;
trying = true;
} else if (EmptySqm(agent.x - 1, agent.y)) {
up = true;
trying = true;
}
}
} else {
agent.x++;
right = true;
left = false;
}
}
//up direction
} else if (up) {
tryTo = "down";
if (lastDir == "left") {
if (EmptySqm(agent.x, agent.y - 1)) {
up = false;
left = true;
agent.y--;
}
} else if (lastDir == "right") {
if (EmptySqm(agent.x, agent.y + 1)) {
up = false;
right = true;
agent.y++;
}
}
if (up) {
if (ValidSqm(agent.x - 1, agent.y)) {
if (EmptySqm(agent.x - 1, agent.y)) {
agent.x--;
} else {
up = false;
//check left sqm
if (EmptySqm(agent.x, agent.y - 1)) {
left = true;
agent.y--;
}
//check right sqm
else if (EmptySqm(agent.x, agent.y + 1)) {
right = true;
agent.y++;
}
//check down sqm
else if (EmptySqm(agent.x + 1, agent.y)) {
down = true;
agent.x++;
}
}
} else {
agent.x++;
up = false;
down = true;
}
}
//down direction
} else if (down) {
tryTo = "up";
if (lastDir == "left") {
if (EmptySqm(agent.x, agent.y - 1)) {
down = false;
left = true;
agent.y--;
}
} else if (lastDir == "right") {
if (EmptySqm(agent.x, agent.y + 1)) {
down = false;
right = true;
agent.y++;
}
}
if (down) {
if (ValidSqm(agent.x + 1, agent.y)) {
if (EmptySqm(agent.x + 1, agent.y)) {
agent.x++;
} else {
down = false;
//check left sqm
if (EmptySqm(agent.x, agent.y - 1)) {
left = true;
agent.y--;
}
//check right sqm
else if (EmptySqm(agent.x, agent.y + 1)) {
right = true;
agent.y++;
}
//check up sqm
else if (EmptySqm(agent.x - 1, agent.y)) {
up = true;
agent.x--;
}
}
} else {
agent.x--;
up = true;
down = false;
}
}
}
}, 100);
var stopInterval = function() {
clearInterval(timerId);
};
};
EmptySqm = function(x, y) {
var bNotWall = !$("#search_grid .row .grid_item[x=" + x + "][y=" + y + "]").hasClass("wall");
return bNotWall;
}
RemoveAgent = function() {
$("#search_grid .row .grid_item").removeClass("agent");
}
ValidSqm = function(x, y) {
return ((x >= 0 && x < gridSize) && (y >= 0 && y < gridSize));
}
html,
body {
height: 100%;
margin: 0;
}
.buttons {
float: right;
position: relative;
right: 10px;
top: 10px;
}
.buttons a {
text-decoration: none;
}
#content {
margin: 0 auto;
width: 98%;
text-align: center;
}
#controls {
text-align: center;
margin-bottom: 25px;
padding: 5px;
}
#search_grid {
width: 320px;
height: 300px;
position: relative;
}
#main {
margin: auto;
width: 20%;
}
.grid_item {
display: block;
border: 1px solid #bbb;
float: left;
line-height: 12px;
font-size: 10px;
}
.grid_item.wall {
background-color: #000000;
}
.grid_item.weight1 {
background-color: #ffffff;
}
.agent {
text-align: center;
color: grey;
font-size: 20px;
background-color: red !important;
color: blue;
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="content">
<input type="button" id="btnInit" value="Start" /><br><br>
<div id="main">
<div id="search_grid">Loading...</div>
</div>
</div>
<div id="footer"></div>
</body>
【问题讨论】:
-
你有一个看起来很酷的例子,但是当前的代码很难理解算法和回答问题。您可以删除无关代码以获得重现问题的Minimal, Complete, and Verifiable example 吗?此外,如果您将葡萄牙语更改为英语,您可能会得到更多答案。
-
@styfle 我已经删除了一些内容以使其更简单并专注于我的问题所在,但我同意你的观点,我会尝试进一步清理代码。
-
您要实现什么特定的通用算法?为什么不使用 A* 之类的东西?
-
@zero298 如果我不能改进这个算法,我会尝试使用 A* 来解决我的问题,谢谢。
标签: javascript jquery collision