JSFiddle - React, Tailwind, and code Playground
by bowheart
HTML
<div id="wrapper"></div>
SCSS
body {
align-items: center;
display: flex;
height: 100vh;
font-size: 0;
justify-content: center;
margin: 0;
}
#wrapper {
position: relative;
}
.room {
border: 1px solid #eee;
display: inline-block;
font-size: 11px;
height: 50px;
position: absolute;
width: 50px;
&:after, &:before {
background: #ccc;
content: '';
position: absolute;
}
}
.crit {
background: repeating-linear-gradient(135deg, #fff 0, #fff 6px, #ccc 7px, #ccc 8px, #fff 9px);
}
.end {
background: rgba(255, 150, 150, 0.2);
}
.start {
background: rgba(150, 255, 150, 0.2);
}
.a:before {
height: 10px;
right: 0;
top: 20px;
width: 30px;
}
.b:before {
bottom: 0;
height: 30px;
left: 20px;
width: 10px;
}
.c:before {
height: 10px;
left: 0;
top: 20px;
width: 30px;
}
.d:before {
height: 30px;
left: 20px;
top: 0;
width: 10px;
}
.e:before {
height: 10px;
left: 0;
top: 20px;
width: 50px;
}
.f:before {
height: 50px;
left: 20px;
top: 0;
width: 10px;
}
.g {
&:after {
height: 10px;
right: 0;
top: 20px;
width: 30px;
}
&:before {
height: 30px;
left: 20px;
top: 0;
width: 10px;
}
}
.h {
&:after {
height: 10px;
right: 0;
top: 20px;
width: 30px;
}
&:before {
height: 30px;
left: 20px;
bottom: 0;
width: 10px;
}
}
.i {
&:after {
height: 10px;
left: 0;
top: 20px;
width: 30px;
}
&:before {
height: 30px;
left: 20px;
bottom: 0;
width: 10px;
}
}
.j {
&:after {
height: 10px;
left: 0;
top: 20px;
width: 30px;
}
&:before {
height: 30px;
left: 20px;
top: 0;
width: 10px;
}
}
.k {
&:after {
height: 10px;
right: 0;
top: 20px;
width: 30px;
}
&:before {
height: 50px;
left: 20px;
top: 0;
width: 10px;
}
}
.l {
&:after {
height: 10px;
right: 0;
top: 20px;
width: 50px;
}
&:before {
height: 30px;
...
JavaScript
const a = { type: 'a', right: true }
const b = { type: 'b', bottom: true }
const c = { type: 'c', left: true }
const d = { type: 'd', top: true }
const e = { type: 'e', right: true, left: true }
const f = { type: 'f', bottom: true, top: true }
const g = { type: 'g', right: true, top: true }
const h = { type: 'h', right: true, bottom: true }
const i = { type: 'i', bottom: true, left: true }
const j = { type: 'j', left: true, top: true }
const k = { type: 'k', right: true, bottom: true, top: true }
const l = { type: 'l', right: true, bottom: true, left: true }
const m = { type: 'm', bottom: true, left: true, top: true }
const n = { type: 'n', right: true, left: true, top: true }
const o = { type: 'o', right: true, bottom: true, left: true, top: true }
const deadEndRooms = [a, b, c, d]
const pathRooms = [e, f, g, h, i, j, k, l, m, n, o]
const allRooms = [...deadEndRooms, ...pathRooms]
const checkRoom = (coords, rooms, neededRooms) => {
const roomStr = coords.join(',')
if (rooms[roomStr] | neededRooms[roomStr]) return false
return coords
}
const chooseRoomType = (numRoomsLeft, numRooms, coords, dirToPrevRoom, rooms, neededRooms) => {
const allAvailableRoomTypes = numRoomsLeft === numRooms
? allRooms // the first room can be any type
: numRoomsLeft === 1
? deadEndRooms // the last room must be a dead end
: pathRooms
// can only pick rooms that have exits pointing to the previous room (if any)
let availableRoomTypes = dirToPrevRoom
? allAvailableRoomTypes.filter(room => room[dirToPrevRoom])
: allAvailableRoomTypes
let roomType
// keep picking room types until we find one that works or we run out of options
while (availableRoomTypes.length) {
roomType = pick(availableRoomTypes)
if (isValidRoomType(roomType, coords, dirToPrevRoom, rooms, neededRooms)) break
// nope - remove this room type from the list of available room types and try another
availableRoomTypes =...