Created default build up

- next make grid be a own component with a lot of callbacks
- after this start the game implementtion
This commit is contained in:
2026-02-06 11:52:17 +01:00
parent da43213808
commit a22dd17869
8 changed files with 214 additions and 32 deletions

View File

@@ -4,5 +4,37 @@
</mat-card-header>
<mat-card-content>
<app-information [algorithmInformation]="algoInformation"/>
<div class="controls-panel">
<button mat-raised-button >
<mat-icon>play_arrow</mat-icon> {{ 'GOL.START' | translate }}
</button>
</div>
<div class="grid-size">
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'PATHFINDING.GRID_HEIGHT' | translate }}</mat-label>
<input
matInput
type="number"
[(ngModel)]="gridRows"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
(blur)="applyGridSize()"
(keyup.enter)="applyGridSize()"
/>
</mat-form-field>
<mat-form-field appearance="outline" class="grid-field">
<mat-label>{{ 'PATHFINDING.GRID_WIDTH' | translate }}</mat-label>
<input
matInput
type="number"
[(ngModel)]="gridCols"
[min]="MIN_GRID_SIZE"
[max]="MAX_GRID_SIZE"
(blur)="applyGridSize()"
(keyup.enter)="applyGridSize()"
/>
</mat-form-field>
</div>
<canvas #gridCanvas></canvas>
</mat-card-content>
</mat-card>

View File

@@ -0,0 +1,11 @@
export interface Node {
row: number;
col: number;
}
export const DEFAULT_GRID_ROWS = 100;
export const DEFAULT_GRID_COLS = 100;
export const MIN_GRID_SIZE = 20;
export const MAX_GRID_SIZE = 200;
export const MAX_GRID_PX = 1000;

View File

@@ -1,9 +1,14 @@
import { Component } from '@angular/core';
import {AfterViewInit, Component, ElementRef, ViewChild} from '@angular/core';
import {MatCard, MatCardContent, MatCardHeader, MatCardTitle} from "@angular/material/card";
import {TranslatePipe} from "@ngx-translate/core";
import {UrlConstants} from '../../../constants/UrlConstants';
import {Information} from '../information/information';
import {AlgorithmInformation} from '../information/information.models';
import {MatButton} from '@angular/material/button';
import {MatIcon} from '@angular/material/icon';
import {MatFormField, MatInput, MatLabel} from '@angular/material/input';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {DEFAULT_GRID_COLS, DEFAULT_GRID_ROWS, MAX_GRID_SIZE, MIN_GRID_SIZE, MAX_GRID_PX, Node} from './conway-gol.models';
@Component({
selector: 'app-conway-gol',
@@ -13,31 +18,136 @@ import {AlgorithmInformation} from '../information/information.models';
MatCardHeader,
MatCardTitle,
TranslatePipe,
Information
Information,
MatButton,
MatIcon,
MatFormField,
MatInput,
MatLabel,
ReactiveFormsModule,
FormsModule
],
templateUrl: './conway-gol.html',
styleUrl: './conway-gol.scss',
})
export class ConwayGol {
protected readonly UrlConstants = UrlConstants;
export class ConwayGol implements AfterViewInit {
algoInformation: AlgorithmInformation = {
title: 'PATHFINDING.EXPLANATION.TITLE',
title: 'GOL.EXPLANATION.TITLE',
entries: [
{
name: 'Dijkstra',
description: 'PATHFINDING.EXPLANATION.DIJKSTRA_EXPLANATION',
link: UrlConstants.DIJKSTRA_WIKI
},
{
name: 'A*',
description: 'PATHFINDING.EXPLANATION.ASTAR_EXPLANATION',
link: UrlConstants.ASTAR_WIKI
name: '',
description: 'GOL.EXPLANATION.EXPLANATION',
link: UrlConstants.CONWAYS_WIKI
}
],
disclaimer: 'PATHFINDING.EXPLANATION.DISCLAIMER',
disclaimer: 'GOL.EXPLANATION.DISCLAIMER',
disclaimerBottom: '',
disclaimerListEntry: []
disclaimerListEntry: ['GOL.EXPLANATION.DISCLAIMER_1', 'GOL.EXPLANATION.DISCLAIMER_2', 'GOL.EXPLANATION.DISCLAIMER_3', 'GOL.EXPLANATION.DISCLAIMER_4']
};
protected gridCols = DEFAULT_GRID_COLS;
protected gridRows = DEFAULT_GRID_ROWS;
protected readonly MIN_GRID_SIZE = MIN_GRID_SIZE;
protected readonly MAX_GRID_SIZE = MAX_GRID_SIZE;
nodeSize = 10;
grid: Node[][] = [];
@ViewChild('gridCanvas', { static: true })
canvas!: ElementRef<HTMLCanvasElement>;
private ctx!: CanvasRenderingContext2D;
ngAfterViewInit(): void {
this.ctx = this.getContextOrThrow();
this.applyGridSize();
}
applyGridSize(): void {
this.gridRows = this.clampGridSize(this.gridRows, DEFAULT_GRID_ROWS);
this.gridCols = this.clampGridSize(this.gridCols, DEFAULT_GRID_COLS);
this.nodeSize = this.computeNodeSize(this.gridRows, this.gridCols);
this.resizeCanvas();
if (this.gridRows === this.grid.length && this.gridCols === this.grid[0].length)
{
this.drawGrid();
return;
}
this.initializeGrid();
}
private initializeGrid(): void {
this.grid = this.createEmptyGrid();
this.drawGrid();
}
private createEmptyGrid(): Node[][] {
const grid: Node[][] = [];
for (let row = 0; row < this.gridRows; row++) {
const currentRow: Node[] = [];
for (let col = 0; col < this.gridCols; col++) {
currentRow.push(this.createNode(row, col));
}
grid.push(currentRow);
}
return grid;
}
private createNode(row: number, col: number): Node {
return {
row,
col
};
}
private drawGrid(): void {
this.ctx.clearRect(0, 0, this.canvas.nativeElement.width, this.canvas.nativeElement.height);
for (let row = 0; row < this.gridRows; row++) {
for (let col = 0; col < this.gridCols; col++) {
this.drawNode(this.grid[row][col]);
}
}
}
private drawNode(node: Node): void {
this.ctx.fillStyle = this.getNodeColor();
this.ctx.fillRect(node.col * this.nodeSize, node.row * this.nodeSize, this.nodeSize, this.nodeSize);
this.ctx.strokeStyle = '#ccc';
this.ctx.strokeRect(node.col * this.nodeSize, node.row * this.nodeSize, this.nodeSize, this.nodeSize);
}
private getNodeColor(): string {
return 'lightgray';
}
private getContextOrThrow(): CanvasRenderingContext2D {
const ctx = this.canvas.nativeElement.getContext('2d');
if (!ctx) {
throw new Error('CanvasRenderingContext2D not available.');
}
return ctx;
}
private clampGridSize(value: number, fallback: number): number {
const parsed = Math.floor(Number(value));
const safe = Number.isFinite(parsed) ? parsed : fallback;
return Math.min(Math.max(MIN_GRID_SIZE, safe), MAX_GRID_SIZE);
}
private computeNodeSize(rows: number, cols: number): number {
const sizeByWidth = Math.floor(MAX_GRID_PX / cols);
const sizeByHeight = Math.floor(MAX_GRID_PX / rows);
return Math.max(1, Math.min(sizeByWidth, sizeByHeight));
}
private resizeCanvas(): void {
const el = this.canvas.nativeElement;
el.width = this.gridCols * this.nodeSize;
el.height = this.gridRows * this.nodeSize;
}
}

View File

@@ -71,4 +71,5 @@
</div>
<canvas #gridCanvas></canvas>
</mat-card-content>
</mat-card-content>
</mat-card>

View File

@@ -21,13 +21,6 @@
}
}
.grid-size {
display: flex;
gap: 0.75rem;
align-items: center;
flex-wrap: wrap;
}
.grid-field {
width: 150px;
}
@@ -54,9 +47,3 @@
&.path { background-color: gold; }
}
}
canvas {
border: 1px solid #ccc;
display: block;
max-width: 100%;
}