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:
@@ -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>
|
||||
|
||||
11
src/app/pages/algorithms/conway-gol/conway-gol.models.ts
Normal file
11
src/app/pages/algorithms/conway-gol/conway-gol.models.ts
Normal 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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,4 +71,5 @@
|
||||
</div>
|
||||
|
||||
<canvas #gridCanvas></canvas>
|
||||
</mat-card-content>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
@@ -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%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user