| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A Chess Game Developed using TypeScript and Angular. Play with your friend in the same browser or against a computer which uses Stockfish API
Project Deployed as a web app on firebase: https://chess-game-using-typescript.web.app/Chess-Game-Using-TypeScript/
This project is not top-tier or perfect, but it’s sufficient for its intended use.
| Topics Covered |
|---|
| Demo of the Project |
| Overview of the Project Model |
| Some Basic Concepts of Angular used in this project |
| Functionalities of Some Important Functions |
| Stockfish API Endpoint |
| How to Run it |
Forsyth–Edwards Notation (FEN) is a standard notation used to describe a particular board position of a chess game. It allows a game to be restarted from any given position by providing all necessary information in a concise format.
FEN provides a way to describe a chess position in a single line of text using ASCII characters. This notation is essential for recording game positions and resuming play from a specific point. However, FEN does not include information about threefold repetition or draw offers; for these, a different format like Extended Position Description (EPD) is needed.
A FEN string consists of six fields, each separated by a space:
Piece Placement Data:
Active Color:
Castling Availability:
En Passant Target Square:
Halfmove Clock:
Fullmove Number:
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1
rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2
rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2
Angular directives are special markers in the DOM that tell Angular to do something with a DOM element (e.g., apply behavior or transformation). Directives can be categorized into three types: Component Directives, Structural Directives, and Attribute Directives.
Component directives are the most common type, created with the @Component decorator.
import { Component } from '@angular/core';
@Component({
selector: 'app-example',
template: '<h1>Hello, World!</h1>'
})
export class ExampleComponent { }Structural directives change the DOM layout by adding or removing elements. Common structural directives are *ngIf, *ngFor, and *ngSwitch.
Conditionally includes a template based on the value of an expression.
<div *ngIf="isVisible">Visible Content</div>Repeats a template for each item in a list.
<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>Switches between alternative views.
<div [ngSwitch]="value">
<p *ngSwitchCase="'A'">Case A</p>
<p *ngSwitchCase="'B'">Case B</p>
<p *ngSwitchDefault>Default Case</p>
</div>Attribute directives change the appearance or behavior of an element, component, or another directive. Common attribute directives are ngClass, ngStyle, and custom attribute directives.
Dynamically adds or removes CSS classes.
<div [ngClass]="{'active': isActive, 'disabled': isDisabled}">Styled Content</div>Dynamically sets inline styles.
<div [ngStyle]="{'color': color, 'font-size': fontSize + 'px'}">Styled Content</div>Custom directives are created using the @Directive decorator.
import { Directive, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef, renderer: Renderer2) {
renderer.setStyle(el.nativeElement, 'backgroundColor', 'yellow');
}
}Lifecycle hooks in Angular are special methods that allow you to tap into different phases of a component or directive's lifecycle. These hooks provide opportunities to execute custom logic at key moments in the lifecycle, such as when a component is created, initialized, updated, or destroyed.
Here are the main lifecycle hooks provided by Angular:
Optional: As I continue to expand the Domain of my Knowledge I recently did Basics of Angular and Typescript. In my opinion Knowing JavaScript and a statically-typed language like Java or C++ can make learning TypeScript significantly easier. Concepts like Single Page Application, Structure of Angular Project, Concepts like Directives, lifecycle hooks are really Important. This video from FCC helped in completion of this Game. Learned a lot about TypeScript, Angular and Logic Building through this video.
The OnInit interface is used to define the ngOnInit method, which is a lifecycle hook called by Angular to indicate that the component has been initialized.
To use OnInit:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-example',
template: `<p>Example component</p>`,
})
export class ExampleComponent implements OnInit {
constructor() { }
ngOnInit(): void {
// Initialization logic here
console.log('Component initialized');
}
}
In this example, ngOnInit is called after the component has been initialized, allowing you to perform any necessary setup.
The OnDestroy interface is used to define the ngOnDestroy method, which is a lifecycle hook called by Angular just before the component is destroyed.
To use OnDestroy:
import { Component, OnDestroy } from '@angular/core';
@Component({
selector: 'app-example',
template: `<p>Example component</p>`,
})
export class ExampleComponent implements OnDestroy {
constructor() { }
ngOnDestroy(): void {
// Cleanup logic here
console.log('Component destroyed');
}
}
In this example, ngOnDestroy is called just before the component is destroyed, allowing you to clean up any resources or subscriptions.
It is common to use both OnInit and OnDestroy in a component to handle initialization and cleanup tasks.
import { Component, OnInit, OnDestroy } from '@angular/core';
@Component({
selector: 'app-example',
template: `<p>Example component</p>`,
})
export class ExampleComponent implements OnInit, OnDestroy {
constructor() { }
ngOnInit(): void {
// Initialization logic here
console.log('Component initialized');
}
ngOnDestroy(): void {
// Cleanup logic here
console.log('Component destroyed');
}
}
FUNCTION findSafeSquares(): Map of player available squares Initially define empty map for player available squares [new Map<string, Coords[]>();] [key = x + "," + y] Foreach square in chess board if square does not have piece or piece on square has difference color than current player: CONTINUE define list of coordinates for piece safe squares Foreach direction of piece directions: declare newX and newY Coordinates if coordinates are out of range: CONTINUE declare piece on new coordinates as newPiece if newPiece is not null AND newPiece.color === piece.color: CONTINUE if (position is SAFE after move) THEN update piece safe squares list Checking if there is possibility for en passant and castling if piece have safe squares append it to the player map RETURN Map of player safe squares
Loop through each piece of opposite color Loop through each of its attacking sqaure if one of the attacking square contains king with the opposite color of piece that is attacking THEN position is in check if no such a square exist there is no check
FUNCTION selectingPiece(x: number, y: number): void IF game is over: RETURN DECLARE piece as the piece at (x, y) IF no piece or piece is not the player's piece: RETURN DECLARE isSameSquareClicked as boolean indicating if the same square was clicked again CALL unmarkingPreviouslySelectedAndSafeSquares() IF isSameSquareClicked: RETURN SET selectedSquare to the piece and its coordinates SET pieceSafeSquares to the list of safe squares for the selected piece from safeSquares map
FUNCTION placingPiece(newX: number, newY: number): void IF no piece is selected: RETURN IF new coordinates are not safe for the selected piece: RETURN DECLARE isPawnSelected as boolean indicating if the selected piece is a pawn DECLARE isPawnOnLastRank as boolean indicating if the pawn is on the last rank DECLARE shouldOpenPromotionDialog as boolean indicating if the promotion dialog should be opened IF shouldOpenPromotionDialog: CLEAR pieceSafeSquares SET isPromotionActive to true SET promotionCoords to the new coordinates RETURN DECLARE prevX and prevY as the previous coordinates of the selected piece CALL updateBoard(prevX, prevY, newX, newY, promotedPiece)
FUNCTION updateBoard(prevX: number, prevY: number, newX: number, newY: number, promotedPiece: FENChar | null): void CALL chessBoard.move(prevX, prevY, newX, newY, promotedPiece) UPDATE chessBoardView with the new state of the board CALL markLastMoveAndCheckState(lastMove, checkState) CALL unmarkingPreviouslySelectedAndSafeSquares() UPDATE chessBoardState$ observable with the new board state INCREMENT gameHistoryPointer
FUNCTION promotePiece(piece: FENChar): void IF no promotion coordinates or no piece is selected: RETURN SET promotedPiece to the selected piece DECLARE newX and newY as the new coordinates from promotionCoords DECLARE prevX and prevY as the previous coordinates of the selected piece CALL updateBoard(prevX, prevY, newX, newY, promotedPiece)
FUNCTION markLastMoveAndCheckState(lastMove: LastMove | undefined, checkState: CheckState): void SET lastMove to the provided lastMove SET checkState to the provided checkState IF lastMove exists: CALL moveSound(lastMove.moveType) ELSE: CALL moveSound(new Set<MoveType>([MoveType.BasicMove]))
FUNCTION showPreviousPosition(moveIndex: number): void DECLARE board, checkState, and lastMove from the game history at the provided index UPDATE chessBoardView with the board state CALL markLastMoveAndCheckState(lastMove, checkState) SET gameHistoryPointer to the provided move index
FUNCTION moveSound(moveType: Set<MoveType>): void DECLARE moveSound as a new Audio object with the default move sound IF moveType contains MoveType.Promotion: SET moveSound source to promotion sound ELSE IF moveType contains MoveType.Capture: SET moveSound source to capture sound ELSE IF moveType contains MoveType.Castling: SET moveSound source to castling sound ELSE IF moveType contains MoveType.CheckMate: SET moveSound source to checkmate sound ELSE IF moveType contains MoveType.Check: SET moveSound source to check sound PLAY moveSound
FUNCTION flipBoard(): void TOGGLE flipMode boolean
FUNCTION isSquareDark(x: number, y: number): boolean RETURN ChessBoard.isSquareDark(x, y)
FUNCTION isSquareSelected(x: number, y: number): boolean IF no piece is selected: RETURN false RETURN true if the selected square coordinates match (x, y)
FUNCTION isSquareSafeForSelectedPiece(x: number, y: number): boolean RETURN true if pieceSafeSquares contains coordinates (x, y)
FUNCTION isSquareLastMove(x: number, y: number): boolean IF no lastMove: RETURN false RETURN true if the square coordinates match either the previous or current coordinates of the lastMove
FUNCTION isSquareChecked(x: number, y: number): boolean RETURN true if checkState is active and the coordinates match (x, y)
FUNCTION isSquarePromotionSquare(x: number, y: number): boolean IF no promotionCoords: RETURN false RETURN true if the coordinates match promotionCoords
FUNCTION unmarkingPreviouslySelectedAndSafeSquares(): void RESET selectedSquare to null CLEAR pieceSafeSquares IF isPromotionActive: SET isPromotionActive to false RESET promotedPiece and promotionCoords to null
FUNCTION closePawnPromotionDialog(): void CALL unmarkingPreviouslySelectedAndSafeSquares()
https://stockfish.online/api/s/v2.php
GET
{
"success": true,
"evaluation": 1.36,
"mate": null,
"bestmove": "bestmove b7b6 ponder f3e5",
"continuation": "b7b6 f3e5 h7h6 g5f6 f8f6 d2f3"
}Install Node JS from their Official Site Angular CLI: npm install -g @angular/cli
ng new my-project-name --no-standalone
ng add @angular/material Choose Custom theme Set up global Angular Material typography styles: No Do not include animations
git clone this_repo_url
Compare the strucuture of your Angular Project and the one you cloned. Add the missing folders and files.
| Back | FazBrowse Home | New Git URL |