Skip to content

Commit

Permalink
added new algorithm and solved issue #13
Browse files Browse the repository at this point in the history
  • Loading branch information
shrutsureja committed Apr 12, 2024
1 parent 018d17c commit 6bc7f13
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 4 deletions.
57 changes: 57 additions & 0 deletions backend/docs/server.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Documentation of Backend Server

Holds the server documentation of the [repo - shrutsureja/Maze-Game](https://github.com/shrutsureja/Maze-Game)

## Algorithms Used

Currently only responds to 2 maze generation algorithm.

- Hunt and Kill
- Recursive Backtracking

## API routes

Contains input and output details of the API routes of the server.

### { route method : route name }

#### Body

```json
body : {
// contains the data
}
```

#### Response

**Status Code : {number}**

```json
{
// response structure
}
```

`Example`

```json
{
// example response data
}
```

### POST /api/generate

#### Body

rows: number,
columns: number,
animation: boolean,
algorithmName: String 'Hunt and kill' or 'Recursion'.

#### Response

maze: {2d array of cells},
solutionPath: {array of {row: number, column: number}},
generatedMazePath: {array of {row: number, column: number}}
3 changes: 2 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"scripts": {
"build": "npx tsc",
"start": "node dist/index.js",
"dev": "nodemon src/index.ts"
"dev": "npx ts-node src/index.ts",
"watch": "nodemon src/index.ts"
},
"author": "shrut sureja",
"license": "ISC",
Expand Down
89 changes: 89 additions & 0 deletions backend/src/Maze/Algorithms/RecursiveBacktracking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Cell } from '../Cell';
import { Path, Utils } from '../Utils';

class RecursiveBacktracking {
private cells: Cell[][] = [];
private animationPath: Path[] = [];
private randomRowNumbers: number[] = [];
private randomColNumbers: number[] = [];
private cellStack: Cell[] = [];

constructor(
public row: number,
public col: number,
public animation: boolean,
cells: Cell[][] = []
) {
this.cells = cells;

if (this.cells.length === 0) {
throw new Error('Number of Cells = 0');
}
for (let i = 0; i < row; i++) {
this.randomRowNumbers.push(i);
}
for (let i = 0; i < col; i++) {
this.randomColNumbers.push(i);
}
this.randomColNumbers = Utils.shuffleArray<number>(this.randomColNumbers);
this.randomRowNumbers = Utils.shuffleArray<number>(this.randomRowNumbers);
}

private addCellToAnimationPath(c: Cell) {
this.animationPath.push({ row: c.row, col: c.col });
}

// Algorithm
// Recursive Backtracking
// 1. Choose a random starting cell
// 2. Mark the current cell as visited
// 3. While the current cell has any unvisited neighbor cells
// 1. Choose one of the unvisited neighbors
// 2. Push the current cell to the stack
// 3. Remove the wall between the current cell and the chosen cell
// 4. Make the chosen cell the current cell and mark it as visited
// 4. If there are no unvisited neighbors
// 1. Pop a cell from the stack
// 2. Make it the current cell
// 5. Repeat until the stack is empty
// 6. Done
// Make

private recursiveBacktracking(): void {
// Selected Random Cell
let currentCell = this.cells[~~(Math.random() * this.row)][~~(Math.random() * this.col)];

currentCell.visited = true;
this.cellStack.push(currentCell);
this.addCellToAnimationPath(currentCell);

while (this.cellStack.length > 0) {
const next = currentCell.neighbors.find((c) => !c.visited);
if (next) {
// add cell to stack
this.cellStack.push(currentCell);
// remove wall between current cell and chosen cell
currentCell.connectTo(next);
// make chosen cell the current cell and mark it as visited
currentCell = next;
currentCell.visited = true;
this.addCellToAnimationPath(currentCell);
} else {
// Pop a cell from the stack
currentCell = this.cellStack.pop() as Cell;
this.addCellToAnimationPath(currentCell);
}
}
}

getGeneratedMaze(): Cell[][] {
this.recursiveBacktracking();
return this.cells;
}

getAnimationPath(): Path[] {
return this.animationPath;
}
}

export { RecursiveBacktracking };
12 changes: 11 additions & 1 deletion backend/src/Maze/GenerateMaze.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HuntAndKill } from './Algorithms/HuntAndKill';
import { RecursiveBacktracking } from './Algorithms/RecursiveBacktracking';
import { Cell } from './Cell';
import { Utils, Path } from './Utils';

Expand Down Expand Up @@ -55,7 +56,16 @@ class GenerateMaze {
animationPath = huntAndKillObj.getAnimationPath();
}
} else if (algorithmName === 'recursivebacktracking') {
// alog
const recursiveBacktrackingObj = new RecursiveBacktracking(
this.rows,
this.columns,
animation,
this.cells
);
maze = recursiveBacktrackingObj.getGeneratedMaze();
if (animation) {
animationPath = recursiveBacktrackingObj.getAnimationPath();
}
}
const jsonMaze = this.convertMazeToJSON(maze);
// combine all in one Maze, Animation, Solution
Expand Down
2 changes: 1 addition & 1 deletion backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import express, { Request, Response, NextFunction } from 'express';
import { GenerateMaze } from './Maze/GenerateMaze';
import z from 'zod';
import cors from 'cors';
import { MazeInputValidationFunction } from './utils';
import { MazeInputValidationFunction } from './validations/MazeInputValidation';
// const express = require('express');

const app = express();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ export function MazeInputValidationFunction(body: any) {
return { success: false, message: 'Not exact number of parameters.' };
}
const { algorithmName } = body;

if (!validate.success) {
return { success: false, message: validate.error };
}

if (
algorithmName.toLowerCase().split(' ').join('') !== 'huntandkill' &&
algorithmName.toLowerCase().split(' ').join('') !== 'recursivebacktracking'
Expand All @@ -27,6 +29,7 @@ export function MazeInputValidationFunction(body: any) {
'Algorithm does not match. ' + algorithmName.toLowerCase().split(' ').join(''),
};
}

return { success: true, message: 'Success' };
} catch (error) {
return { success: false, message: 'Error in validation.' };
Expand Down
1 change: 0 additions & 1 deletion frontend/src/Maze/MazeView/MazeOptions/HomeOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ export default function HomeOptions(props: any) {
Animation
</label>
<select
disabled
value={selectedAlgorithm ? selectedAlgorithm.id : ''}
required
onChange={(e) =>
Expand Down

0 comments on commit 6bc7f13

Please sign in to comment.