Merge game-page to main: include dice views, images, and supporting types #7

Merged
MiguelMLorente merged 6 commits from game-page into main 2024-12-01 21:22:11 +00:00
43 changed files with 640 additions and 18 deletions

View File

@ -13,5 +13,7 @@ module.exports = {
jest: true, jest: true,
}, },
ignorePatterns: [".eslintrc.js", "dist/"], ignorePatterns: [".eslintrc.js", "dist/"],
rules: {}, rules: {
"@typescript-eslint/no-non-null-assertion": "off",
},
}; };

View File

@ -0,0 +1,4 @@
export enum InternalNodeType {
NONE = "NONE",
STATION = "STATION",
}

View File

@ -0,0 +1,412 @@
import { Piece } from "../types/Piece";
import { Direction } from "./Direction";
import { InternalNodeType } from "./InternalNodeType";
import { TrackType } from "./TrackType";
const STRAIGHT_RAIL: Piece = new Piece({
useInternalTracks: false,
trackDefinitions: [
{
startPoint: Direction.NORTH,
endPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
],
});
const TURN_RAIL: Piece = new Piece({
useInternalTracks: false,
trackDefinitions: [
{
startPoint: Direction.SOUTH,
endPoint: Direction.EAST,
type: TrackType.RAIL,
},
],
});
const FOUR_WAY_CROSS_RAIL: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.NONE,
trackDefinitions: [
{
startPoint: Direction.NORTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
type: TrackType.RAIL,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
],
});
const T_JUNCTION_RAIL: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.NONE,
trackDefinitions: [
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
type: TrackType.RAIL,
},
],
});
const DEAD_END_STATION_RAIL: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
],
});
const TURN_RAIL_TO_ROAD: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
],
});
const T_JUNCTION_WITH_ROAD_ON_SIDE: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
],
});
const FOUR_WAY_WITH_ONE_ROAD: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.NORTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
],
});
const T_JUNCTION_WITH_ROAD_AT_CENTER: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.NORTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
],
});
const STRAIGHT_TRACK_CHANGE: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
],
});
const DEAD_END_STATION_ROAD: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.EAST,
type: TrackType.RAIL,
},
],
});
const T_JUNCTION_WITH_RAIL_AT_CENTER: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.WEST,
type: TrackType.ROAD,
},
],
});
const FOUR_WAY_PERPENDICULAR_CROSSING: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.NORTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.WEST,
type: TrackType.ROAD,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
],
});
const FOUR_WAY_WITH_ONE_RAIL: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.NORTH,
type: TrackType.ROAD,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.WEST,
type: TrackType.ROAD,
},
],
});
const FOUR_WAY_TURNING_CROSSING: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.STATION,
trackDefinitions: [
{
startPoint: Direction.NORTH,
type: TrackType.ROAD,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
],
});
const LEVEL_CROSSING: Piece = new Piece({
useInternalTracks: false,
trackDefinitions: [
{
startPoint: Direction.NORTH,
endPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
endPoint: Direction.WEST,
type: TrackType.ROAD,
},
],
});
const STRAIGHT_ROAD: Piece = new Piece({
useInternalTracks: false,
trackDefinitions: [
{
startPoint: Direction.EAST,
endPoint: Direction.WEST,
type: TrackType.ROAD,
},
],
});
const T_JUNCTION_ROAD: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.NONE,
trackDefinitions: [
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.SOUTH,
type: TrackType.ROAD,
},
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
],
});
const FOUR_WAY_CROSS_ROAD: Piece = new Piece({
useInternalTracks: true,
internalNodeType: InternalNodeType.NONE,
trackDefinitions: [
{
startPoint: Direction.NORTH,
type: TrackType.ROAD,
},
{
startPoint: Direction.EAST,
type: TrackType.ROAD,
},
{
startPoint: Direction.SOUTH,
type: TrackType.ROAD,
},
{
startPoint: Direction.WEST,
type: TrackType.RAIL,
},
],
});
const DOUBLE_TURN_ROAD: Piece = new Piece({
useInternalTracks: false,
trackDefinitions: [
{
startPoint: Direction.NORTH,
endPoint: Direction.WEST,
type: TrackType.ROAD,
},
{
startPoint: Direction.EAST,
endPoint: Direction.SOUTH,
type: TrackType.ROAD,
},
],
});
const TURN_ROAD: Piece = new Piece({
useInternalTracks: false,
trackDefinitions: [
{
startPoint: Direction.NORTH,
endPoint: Direction.WEST,
type: TrackType.ROAD,
},
],
});
const DOUBLE_TURN_RAIL: Piece = new Piece({
useInternalTracks: false,
trackDefinitions: [
{
startPoint: Direction.NORTH,
endPoint: Direction.WEST,
type: TrackType.RAIL,
},
{
startPoint: Direction.EAST,
endPoint: Direction.SOUTH,
type: TrackType.RAIL,
},
],
});
export enum PieceId {
P01 = "P01",
P02 = "P02",
P03 = "P03",
P04 = "P04",
P05 = "P05",
P06 = "P06",
P07 = "P07",
P08 = "P08",
P09 = "P09",
P10 = "P10",
P11 = "P11",
P12 = "P12",
P13 = "P13",
P14 = "P14",
P15 = "P15",
P16 = "P16",
P17 = "P17",
P18 = "P18",
P19 = "P19",
P20 = "P20",
P21 = "P21",
P22 = "P22",
}
export const pieceMap: Record<PieceId, Piece> = {
[PieceId.P01]: STRAIGHT_RAIL,
[PieceId.P02]: TURN_RAIL,
[PieceId.P03]: FOUR_WAY_CROSS_RAIL,
[PieceId.P04]: T_JUNCTION_RAIL,
[PieceId.P05]: DEAD_END_STATION_RAIL,
[PieceId.P06]: TURN_RAIL_TO_ROAD,
[PieceId.P07]: T_JUNCTION_WITH_ROAD_ON_SIDE,
[PieceId.P08]: FOUR_WAY_WITH_ONE_ROAD,
[PieceId.P09]: T_JUNCTION_WITH_ROAD_AT_CENTER,
[PieceId.P10]: STRAIGHT_TRACK_CHANGE,
[PieceId.P11]: DEAD_END_STATION_ROAD,
[PieceId.P12]: T_JUNCTION_WITH_RAIL_AT_CENTER,
[PieceId.P13]: FOUR_WAY_PERPENDICULAR_CROSSING,
[PieceId.P14]: FOUR_WAY_WITH_ONE_RAIL,
[PieceId.P15]: FOUR_WAY_TURNING_CROSSING,
[PieceId.P16]: LEVEL_CROSSING,
[PieceId.P17]: STRAIGHT_ROAD,
[PieceId.P18]: T_JUNCTION_ROAD,
[PieceId.P19]: FOUR_WAY_CROSS_ROAD,
[PieceId.P20]: DOUBLE_TURN_ROAD,
[PieceId.P21]: TURN_ROAD,
[PieceId.P22]: DOUBLE_TURN_RAIL,
};

View File

@ -1,10 +1,15 @@
export * from "./constants/CellType"; export * from "./constants/CellType";
export * from "./constants/Direction"; export * from "./constants/Direction";
export * from "./constants/ExitType"; export * from "./constants/ExitType";
export * from "./constants/InternalNodeType";
export * from "./constants/Pieces";
export * from "./constants/TrackType"; export * from "./constants/TrackType";
export * from "./types/Border"; export * from "./types/Border";
export * from "./types/Cell"; export * from "./types/Cell";
export * from "./types/Exit"; export * from "./types/Exit";
export * from "./types/ExternalNode"; export * from "./types/ExternalNode";
export * from "./types/InternalNode";
export * from "./types/Piece";
export * from "./types/PlacedPiece";
export * from "./types/Node"; export * from "./types/Node";
export * from "./BoardBuilder"; export * from "./BoardBuilder";

View File

@ -8,6 +8,9 @@
"name": "interface", "name": "interface",
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": {
"uuid": "^11.0.3"
},
"devDependencies": { "devDependencies": {
"@eslint/js": "^8.0.0", "@eslint/js": "^8.0.0",
"@types/node": "^22.9.0", "@types/node": "^22.9.0",
@ -1855,6 +1858,19 @@
"punycode": "^2.1.0" "punycode": "^2.1.0"
} }
}, },
"node_modules/uuid": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz",
"integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist/esm/bin/uuid"
}
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -21,5 +21,8 @@
"globals": "^15.12.0", "globals": "^15.12.0",
"typescript": "^5.6.3", "typescript": "^5.6.3",
"typescript-eslint": "^8.15.0" "typescript-eslint": "^8.15.0"
},
"dependencies": {
"uuid": "^11.0.3"
} }
} }

View File

@ -19,6 +19,6 @@ export class Cell {
public getNodeAt(direction: Direction): ExternalNode { public getNodeAt(direction: Direction): ExternalNode {
const node = this.externalNodes.get(direction); const node = this.externalNodes.get(direction);
if (!node) throw Error(`Could not find node at ${direction}`); if (!node) throw Error(`Could not find node at ${direction}`);
return this.externalNodes.get(direction) as ExternalNode; return node!;
} }
} }

View File

@ -2,14 +2,14 @@ import { Direction } from "../constants/Direction";
import { Border } from "./Border"; import { Border } from "./Border";
import { Cell } from "./Cell"; import { Cell } from "./Cell";
import { Exit } from "./Exit"; import { Exit } from "./Exit";
import { Node } from "./Node";
export class ExternalNode extends Node { export class ExternalNode {
public readonly direction: Direction; public readonly direction: Direction;
private border?: Border; private border?: Border;
public readonly cell: Cell;
constructor(cell: Cell, direction: Direction) { constructor(cell: Cell, direction: Direction) {
super(cell); this.cell = cell;
this.direction = direction; this.direction = direction;
} }
@ -24,6 +24,6 @@ export class ExternalNode extends Node {
if (!this.border) { if (!this.border) {
throw Error(`Missing border for node`); throw Error(`Missing border for node`);
} }
return (this.border as Border).traverseFrom(this); return this.border.traverseFrom(this);
} }
} }

View File

@ -0,0 +1,12 @@
import { v4 as uuidv4 } from "uuid";
import { InternalNodeType } from "../constants/InternalNodeType";
export class InternalNode {
id: string;
type: InternalNodeType;
constructor(type: InternalNodeType) {
this.id = uuidv4();
this.type = type;
}
}

View File

@ -1,9 +1,4 @@
import { Cell } from "./Cell"; import { ExternalNode } from "./ExternalNode";
import { InternalNode } from "./InternalNode";
export abstract class Node { export type Node = ExternalNode | InternalNode;
public readonly cell: Cell;
constructor(cell: Cell) {
this.cell = cell;
}
}

89
interface/types/Piece.ts Normal file
View File

@ -0,0 +1,89 @@
import { Direction } from "../constants/Direction";
import { TrackType } from "../constants/TrackType";
import { Cell } from "./Cell";
import { InternalNode } from "./InternalNode";
import { PlacedPiece } from "./PlacedPiece";
import { Node } from "./Node";
import { InternalNodeType } from "../constants/InternalNodeType";
export interface PieceProps {
readonly useInternalTracks: boolean;
readonly internalNodeType?: InternalNodeType;
readonly trackDefinitions: {
readonly startPoint: Direction;
readonly endPoint?: Direction;
readonly type: TrackType;
}[];
}
type Track = {
readonly joinedPoints: {
readonly firstPoint: Direction;
readonly secondPoint: Direction | InternalNode;
};
readonly type: TrackType;
};
export class Piece {
readonly tracks: Set<Track>;
readonly internalNode?: InternalNode;
constructor(pieceProps: PieceProps) {
if (pieceProps.useInternalTracks) {
if (!pieceProps.internalNodeType) {
throw Error(
"Expected to find internal node type when useInternalTracks is set",
);
}
this.internalNode = new InternalNode(pieceProps.internalNodeType);
this.tracks = new Set(
pieceProps.trackDefinitions.map((trackDefinition) => {
return {
joinedPoints: {
firstPoint: trackDefinition.startPoint,
secondPoint: this.internalNode!,
},
type: trackDefinition.type,
};
}),
);
} else {
this.internalNode = undefined;
this.tracks = new Set(
pieceProps.trackDefinitions.map((trackDefinition) => {
if (!trackDefinition.endPoint) {
throw Error("Missing end point for non-internal track");
}
return {
joinedPoints: {
firstPoint: trackDefinition.startPoint,
secondPoint: trackDefinition.endPoint,
},
type: trackDefinition.type,
};
}),
);
}
}
toPlacedPiece(cell: Cell) {
return new PlacedPiece(
new Set(
Array.from(this.tracks).map((track) => {
return {
nodes: {
firstNode: cell.getNodeAt(track.joinedPoints.firstPoint),
secondNode:
track.joinedPoints.secondPoint instanceof Node
? (track.joinedPoints.secondPoint as Node)
: cell.getNodeAt(track.joinedPoints.secondPoint as Direction),
},
type: track.type,
};
}),
),
this.internalNode,
cell,
);
}
}

View File

@ -0,0 +1,29 @@
import { TrackType } from "../constants/TrackType";
import { Cell } from "./Cell";
import { InternalNode } from "./InternalNode";
import { Node } from "./Node";
export class PlacedPiece {
tracks: Set<{
nodes: {
firstNode: Node;
secondNode: Node;
};
type: TrackType;
}>;
internalNode?: InternalNode;
cell: Cell;
constructor(
tracks: Set<{
nodes: { firstNode: Node; secondNode: Node };
type: TrackType;
}>,
internalNodes: InternalNode | undefined,
cell: Cell,
) {
this.tracks = tracks;
this.internalNode = internalNodes;
this.cell = cell;
}
}

BIN
web/public/pieces/P01.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
web/public/pieces/P02.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
web/public/pieces/P03.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
web/public/pieces/P04.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
web/public/pieces/P05.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
web/public/pieces/P06.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
web/public/pieces/P07.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
web/public/pieces/P08.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
web/public/pieces/P09.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
web/public/pieces/P10.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
web/public/pieces/P11.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
web/public/pieces/P12.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
web/public/pieces/P13.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
web/public/pieces/P14.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
web/public/pieces/P15.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
web/public/pieces/P16.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
web/public/pieces/P17.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
web/public/pieces/P18.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
web/public/pieces/P19.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
web/public/pieces/P20.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
web/public/pieces/P21.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
web/public/pieces/P22.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -1,6 +1,3 @@
@use "node_modules/@picocss/pico/scss/pico" with ( @use "node_modules/@picocss/pico/scss/pico" with (
$theme-color: "pumpkin" $theme-color: "pumpkin"
); );
@import "./pages/game/GamePage.scss";
@import "./pages/game/components/GameBoard.scss";

View File

@ -1,5 +1,6 @@
import { io } from "socket.io-client"; import { io } from "socket.io-client";
import GamePage from "./pages/game/GamePage"; import GamePage from "./pages/game/GamePage";
import "./App.scss";
function App() { function App() {
const socket = io("http://localhost:3010"); const socket = io("http://localhost:3010");

View File

@ -1,7 +1,6 @@
import React from "react"; import React from "react";
import ReactDOM from "react-dom/client"; import ReactDOM from "react-dom/client";
import App from "./App"; import App from "./App";
import "./App.scss";
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement, document.getElementById("root") as HTMLElement,

View File

@ -3,3 +3,14 @@ h1 {
padding: 10px; padding: 10px;
margin: 0; margin: 0;
} }
.game-panel {
user-select: none; /* Standard syntax */
display: flex;
flex-direction: row;
.right-panel {
display: flex;
flex-direction: column;
}
}

View File

@ -1,5 +1,7 @@
import React from "react"; import React from "react";
import GameBoard from "./components/GameBoard"; import GameBoard from "./components/GameBoard";
import DiceSet from "./components/DiceSet";
import "./GamePage.scss";
const GamePage = () => { const GamePage = () => {
return ( return (
@ -7,6 +9,9 @@ const GamePage = () => {
<h1>Game Page Title</h1> <h1>Game Page Title</h1>
<div className="game-panel"> <div className="game-panel">
<GameBoard /> <GameBoard />
<div className="rigth-panel">
<DiceSet />
</div>
</div> </div>
</React.Fragment> </React.Fragment>
); );

View File

@ -0,0 +1,17 @@
.dice-set {
display: grid;
grid-template-columns: repeat(2, auto);
gap: 20px;
padding: 50px;
.dice {
height: 150px;
width: 150px;
border: 2px solid black;
border-radius: 10%;
img{
border-radius: 10%;
}
}
}

View File

@ -0,0 +1,22 @@
import { PieceId } from "interface";
import "./DiceSet.scss";
const DiceSet = () => {
const getRandomPieceId = () => {
const randomId = Math.floor(Math.random() * Object.keys(PieceId).length);
return Object.values(PieceId)[randomId];
};
const displayedPieceIds = [1, 2, 3, 4].map(getRandomPieceId);
return (
<div className="dice-set">
{displayedPieceIds.map((pieceId) => (
<div className="dice">
<img src={`pieces/${pieceId}.jpeg`}></img>
</div>
))}
</div>
);
};
export default DiceSet;

View File

@ -1,6 +1,8 @@
.game-board { .game-board {
height: 850px; height: 850px;
width: 850px; width: 850px;
min-height: 850px;
min-width: 850px;
display: grid; display: grid;
grid-template-columns: repeat(7, auto); grid-template-columns: repeat(7, auto);
gap: auto; gap: auto;

View File

@ -1,4 +1,5 @@
import { buildBoard, Cell, directions, Exit } from "interface"; import { buildBoard, Cell, directions, Exit } from "interface";
import "./GameBoard.scss";
const GameBoard = () => { const GameBoard = () => {
const board: Cell[][] = buildBoard(); const board: Cell[][] = buildBoard();