initial commit

This commit is contained in:
Baipyrus 2022-05-15 17:09:05 +02:00
commit bcafd62c26
4 changed files with 416 additions and 0 deletions

9
index.html Normal file
View File

@ -0,0 +1,9 @@
<html>
<head>
</head>
<body onload="startup()">
<script type="text/javascript" src="js/maze_generation.js"></script>
<script type="text/javascript" src="js/maze_solving.js"></script>
<script type="text/javascript" src="js/canvas.js"></script>
</body>
</html>

222
js/canvas.js Normal file
View File

@ -0,0 +1,222 @@
var canv, ctx, columns, rows, rectWidth, rectHeight, maze;
function display() {
ctx.fillStyle = "black";
ctx.fillRect(0,0,canv.width,canv.height);
maze = generate_maze(columns, rows);
startingCell = maze[0];
endingCell = maze[maze.length-1];
// Draw Grid in Grey (to see individual Cells)
ctx.strokeStyle = "rgb(60, 60, 60)";
for (var i = 0; i < columns; i++) {
var x = i*rectWidth;
for (var j = 0; j < rows; j++) {
var y = j*rectHeight;
ctx.beginPath();
ctx.rect(x,y,rectWidth,rectHeight);
ctx.closePath();
ctx.stroke();
}
}
// Display the Maze ontop of the indivudial Cells
ctx.strokeStyle = "white";
for (var i = 0; i < columns; i++) {
var sx = i*rectWidth;
var rx = (i+1)*rectWidth;
for (var j = 0; j < rows; j++) {
var sy = j*rectHeight;
var by = (j+1)*rectHeight;
var cell = maze[getIndex(i, j, columns)];
if (cell.walls[0]) {
ctx.beginPath();
ctx.moveTo(sx, sy);
ctx.lineTo(rx, sy);
ctx.closePath();
ctx.stroke();
}
if (cell.walls[1]) {
ctx.beginPath();
ctx.moveTo(rx, sy);
ctx.lineTo(rx, by);
ctx.closePath();
ctx.stroke();
}
if (cell.walls[2]) {
ctx.beginPath();
ctx.moveTo(sx, by);
ctx.lineTo(rx, by);
ctx.closePath();
ctx.stroke();
}
if (cell.walls[3]) {
ctx.beginPath();
ctx.moveTo(sx, sy);
ctx.lineTo(sx, by);
ctx.closePath();
ctx.stroke();
}
}
}
}
function startup() {
columns = 10;
rows = 5;
var div = document.createElement("div");
div.style.position = "absolute";
div.style.bottom = "0px";
div.style.color = "white";
div.style.fontFamily = "arial";
var wp = document.createElement("a");
wp.innerText = "Cells in column:"
div.appendChild(wp);
var wi = document.createElement("input");
wi.type="range";
wi.min = 10;
wi.max = 100;
wi.value = columns;
wi.oninput=function() {
columns = parseInt(this.value);
rectWidth = window.innerWidth/columns;
display();
}
div.appendChild(wi);
var hp = document.createElement("a");
hp.innerText = "Cells in row:"
div.appendChild(hp);
var hi = document.createElement("input");
hi.type="range";
hi.min = 5;
hi.max = 50;
hi.value = rows;
hi.oninput=function() {
rows = parseInt(this.value);
rectHeight = window.innerHeight/rows;
display();
}
div.appendChild(hi);
var pb = document.createElement("button");
pb.innerHTML = "Solve Maze";
pb.onclick = function() {
var startingCell = maze[0];
var endingCell = maze[maze.length-1];
var path = solve_maze(maze, columns, rows, startingCell, endingCell);
ctx.strokeStyle = "rgb(0,200,255)";
ctx.beginPath();
var first_x = path[0].i*rectWidth;
var first_y = path[0].j*rectHeight;;
ctx.moveTo(first_x+rectWidth/2, first_y+rectHeight/2);
for (var i = 1; i < path.length; i++) {
var cell = path[i];
var x = cell.i*rectWidth;
var y = cell.j*rectHeight;
ctx.lineTo(x+rectWidth/2, y+rectHeight/2);
}
ctx.stroke();
ctx.closePath();
}
div.appendChild(pb);
rectWidth = window.innerWidth/columns;
rectHeight = window.innerHeight/rows;
canv = document.createElement("canvas");
canv.width = window.innerWidth;
canv.height = window.innerHeight;
canv.style.position = "absolute";
canv.style.top = "0px";
canv.style.left = "0px";
ctx = canv.getContext("2d");
document.body.appendChild(canv);
document.body.appendChild(div);
display();}/*
mazeToGrid();
}
function mazeToGrid() {
var newColumns = columns*2-1;
var cellWidth = canv.width/newColumns;
var newRows = rows*2-1;
var cellHeight = canv.height/newRows;
var grid = Array(newColumns);
for (var i = 0; i < grid.length; i++) {
var row = Array(newRows);
for (var j = 0; j < rows.length; j++) {
row[j] = false;
}
grid.push(row);
}
var stack = Array();
var o = gridSet(grid, 0, 0, stack);
grid = o.g;
stack = o.s;
for (var i = 0; i < grid.length; i++) {
var x = i * cellWidth;
for (var j = 0; j < grid[i].length; j++) {
var y = j * cellHeight;
ctx.fillStyle = (grid[i][j]) ? "white" : "black";
ctx.fillRect(x,y,cellWidth,cellHeight);
}
}
}
function gridSet(g, x, y, s) {
var isInStack = false;
for (var i = 0; i < s; i++) {
if (s[i].x == x && s[i].y == y) {
isInStack = true;
}
}
if (!isInStack) {
var neighbors = Array();
for (var i = -1; i < -2; i++) {
var nx = x + i;
if (nx >= 0 && nx < columns) {
for (var j = -1; j < -2; j++) {
var ny = y + j;
if (ny >= 0 && ny < rows && !(nx == x && ny == y)) {
neighbors.push({x: nx, y: ny});
}
}
}
}
s.push({x, y});
// ALWAYS DO RIGHT AND BOTTOM
if (maze[x+y*columns].walls[1]) {
if (x*2+1 < newColumns) {
grid[x*2+1][y*2] = true;
}
}
if (maze[x+y*columns].walls[2]) {
if (y*2+1 < newRows) {
grid[x*2][y*2+1] = true;
}
}
if (neighbors.length > 0) {
for (var i = 0; i < neighbors.length; i++) {
var n = neighbors[i];
var o = gridSet(g, n.x, n.y, s);
g = o.g;
s = o.s;
}
}
}
return {g, s};
}*/

113
js/maze_generation.js Normal file
View File

@ -0,0 +1,113 @@
function generate_maze(cols, rows) {
var maze = Array(cols*rows);
for (var j = 0; j < rows; j++) {
for (var i = 0; i < cols; i++) {
var index = getIndex(i, j, cols);
maze[index] = new Cell(i, j);
}
}
var stack = Array();
var current = maze[0];
current.visited = true;
while (true) {
var next = current.choose_neighbor(maze, cols, rows);
if (next) {
stack.push(current);
current = current.remove_walls(next);
current.visited = true;
} else if (stack.length > 0) {
current = stack.pop();
}
var visitedAll = true;
for (var i = 0; i < maze.length; i++) {
if (!maze[i].visited) {
visitedAll = false;
break;
}
}
if (visitedAll && current == maze[0]) {
break;
}
}
return maze;
}
class Cell {
constructor(x, y) {
this.i = x;
this.j = y;
this.visited = false;
this.walls = [true, true, true, true];
this.previous = undefined;
}
choose_neighbor(maze, cols, rows) {
var neighbors = Array();
for (var i = -1; i < 2; i++) {
if (i != 0) {
var x_n_x = this.i+i;
var x_n_y = this.j;
var x_n_isInCols = x_n_x >= 0 && x_n_x < cols;
var x_n_isInRows = x_n_y >= 0 && x_n_y < rows;
if (x_n_isInCols && x_n_isInRows) {
var x_n_index = x_n_x+x_n_y*cols;
var x_neighbor = maze[x_n_index];
if (!x_neighbor.visited) {
neighbors.push(x_neighbor);
}
}
var y_n_x = this.i;
var y_n_y = this.j+i;
var y_n_isInCols = y_n_x >= 0 && y_n_x < cols;
var y_n_isInRows = y_n_y >= 0 && y_n_y < rows;
if (y_n_isInCols && y_n_isInRows) {
var y_n_index = y_n_x+y_n_y*cols;
var y_neighbor = maze[y_n_index];
if (!y_neighbor.visited) {
neighbors.push(y_neighbor);
}
}
}
}
if (neighbors.length > 0) {
var random_neighbor_index = Math.floor(Math.random()*neighbors.length);
var random_neighbor = neighbors[random_neighbor_index];
return random_neighbor;
}
}
remove_walls(other) {
var x_w = other.i - this.i;
if (x_w == 1) {
this.walls[1] = false;
other.walls[3] = false;
} else if (x_w == -1) {
this.walls[3] = false;
other.walls[1] = false;
}
var y_w = other.j - this.j;
if (y_w == 1) {
this.walls[2] = false;
other.walls[0] = false;
} else if (y_w == -1) {
this.walls[0] = false;
other.walls[2] = false;
}
return other;
}
}
function getIndex(x, y, w) {
return x + y * w;
}

72
js/maze_solving.js Normal file
View File

@ -0,0 +1,72 @@
function solve_maze(maze, cols, rows, start, end) {
var path = Array();
var openSet = Array(start);
var closedSet = Array();
var solved = false;
while (!solved) {
for (var i = openSet.length-1; i >= 0; i--) {
var current = openSet[i];
if (current == end) {
if (path.length == 0) {
path.push(current);
var temp = current.previous;
while (true) {
if (temp != start) {
path.push(temp);
temp = temp.previous;
} else {
path.push(start);
solved = true;
break;
}
}
}
break;
} else {
for (var j = 0; j < current.walls.length; j++) {
if (!current.walls[j]) {
var neighbor_index = indexFromWall(current, j, cols);
if (neighbor_index > -1) {
var neighbor = maze[neighbor_index];
var isInSet = false;
for (var k = 0; k < closedSet.length; k++) {
if (neighbor == closedSet[k]) {
isInSet = true;
break;
}
}
if (!isInSet) {
neighbor.previous = current;
openSet.push(neighbor);
}
}
}
}
closedSet.push(current);
openSet.splice(openSet.indexOf(current),1);
}
}
}
return path;
}
function indexFromWall(cell, wall_index, cols) {
var index = -1;
switch (wall_index) {
case 0:
index = getIndex(cell.i, cell.j-1, cols);
break;
case 1:
index = getIndex(cell.i+1, cell.j, cols);
break;
case 2:
index = getIndex(cell.i, cell.j+1, cols);
break;
case 3:
index = getIndex(cell.i-1, cell.j, cols);
break;
}
return index;
}