initial commit
This commit is contained in:
@@ -1,4 +1 @@
|
|||||||
<router-outlet></router-outlet>
|
<app-board></app-board>
|
||||||
<app-square value="X"></app-square>
|
|
||||||
<app-square value="O"></app-square>
|
|
||||||
<app-square value="X"></app-square>
|
|
||||||
@@ -1,3 +1,15 @@
|
|||||||
:host {
|
p {
|
||||||
|
font-family: Lato;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
h1 {
|
||||||
|
|
||||||
|
transition: color .2s;
|
||||||
|
|
||||||
|
}
|
||||||
|
h1 :leave {
|
||||||
|
transition: display 4s;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
margin-top: 100px;
|
||||||
|
}
|
||||||
@@ -13,14 +13,16 @@ import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
|||||||
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { SquareComponent } from './square/square.component';
|
import { BoardModule } from './board/board.module';
|
||||||
|
|
||||||
|
|
||||||
// AoT requires an exported function for factories
|
// AoT requires an exported function for factories
|
||||||
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [AppComponent, SquareComponent],
|
declarations: [AppComponent],
|
||||||
imports: [
|
imports: [
|
||||||
|
BoardModule,
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
|
|||||||
12
src/app/board/board.component.html
Normal file
12
src/app/board/board.component.html
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<section w-full>
|
||||||
|
<h1>Tic-Tac-Toe</h1>
|
||||||
|
</section>
|
||||||
|
<section w-full>
|
||||||
|
<p><button (click)="resetGame()">Neues Spiel!<br /></button><br /></p>
|
||||||
|
<h1>current player: {{ player }}</h1>
|
||||||
|
<h2 *ngIf="winner">Gewinner: {{ winner }}<br /></h2><br />
|
||||||
|
</section>
|
||||||
|
<section w-full>
|
||||||
|
<app-square class="square-container h-48" *ngFor="let val of fields; let i=index" [value]="val"
|
||||||
|
(click)="playerPress(i)"></app-square>
|
||||||
|
</section>
|
||||||
36
src/app/board/board.component.scss
Normal file
36
src/app/board/board.component.scss
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// :host {
|
||||||
|
|
||||||
|
// display: grid;
|
||||||
|
// grid-template-columns: 200px 200px 200px;
|
||||||
|
// grid-gap: 0px;
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
app-square {
|
||||||
|
|
||||||
|
border: 2px black solid;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
width: 600px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin: 7% auto 50px auto;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.square-container {
|
||||||
|
flex: 0 0 32%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: greenyellow;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
45
src/app/board/board.component.spec.ts
Normal file
45
src/app/board/board.component.spec.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { BoardComponent } from './board.component';
|
||||||
|
|
||||||
|
describe('BoardComponent', () => {
|
||||||
|
let component: BoardComponent;
|
||||||
|
let fixture: ComponentFixture<BoardComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [BoardComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(BoardComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('left top right horizontal test', () => {
|
||||||
|
component.playerPress(0);
|
||||||
|
component.playerPress(3);
|
||||||
|
component.playerPress(1);
|
||||||
|
component.playerPress(4);
|
||||||
|
component.playerPress(2);
|
||||||
|
expect(component.calculateWinner()).not.toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('left top bottom right diagonal test', () => {
|
||||||
|
component.playerPress(0);
|
||||||
|
component.playerPress(1);
|
||||||
|
component.playerPress(4);
|
||||||
|
component.playerPress(5);
|
||||||
|
component.playerPress(8);
|
||||||
|
expect(component.calculateWinner()).not.toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
76
src/app/board/board.component.ts
Normal file
76
src/app/board/board.component.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-board',
|
||||||
|
templateUrl: './board.component.html',
|
||||||
|
styleUrls: ['./board.component.scss'],
|
||||||
|
})
|
||||||
|
export class BoardComponent implements OnInit {
|
||||||
|
winner: string;
|
||||||
|
draw: boolean;
|
||||||
|
xIsNext: boolean;
|
||||||
|
fields: any[];
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.resetGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
resetGame() {
|
||||||
|
this.winner = null;
|
||||||
|
this.draw = false;
|
||||||
|
this.xIsNext = true;
|
||||||
|
this.fields = Array(9).fill(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
get player() {
|
||||||
|
return this.xIsNext ? 'X' : 'O';
|
||||||
|
}
|
||||||
|
|
||||||
|
playerPress(i: number) {
|
||||||
|
if(this.winner != null) {
|
||||||
|
this.resetGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.fields[i]) {
|
||||||
|
this.fields.splice(i, 1, this.player);
|
||||||
|
|
||||||
|
this.xIsNext = !this.xIsNext;
|
||||||
|
this.calculateWinner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateWinner() {
|
||||||
|
const winners = [
|
||||||
|
[0, 1, 2],
|
||||||
|
|
||||||
|
[3, 4, 5],
|
||||||
|
|
||||||
|
[6, 7, 8],
|
||||||
|
|
||||||
|
[0, 3, 6],
|
||||||
|
|
||||||
|
[2, 4, 7],
|
||||||
|
|
||||||
|
[2, 5, 8],
|
||||||
|
|
||||||
|
[0, 4, 8],
|
||||||
|
|
||||||
|
[2, 4, 6],
|
||||||
|
];
|
||||||
|
for (let i = 0; i < winners.length; i++) {
|
||||||
|
const [a, b, c] = winners[i];
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.fields[a] &&
|
||||||
|
this.fields[a] === this.fields[b] &&
|
||||||
|
this.fields[a] === this.fields[c]
|
||||||
|
) {
|
||||||
|
this.winner = this.fields[a];
|
||||||
|
return this.fields[a];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/app/board/board.module.ts
Normal file
13
src/app/board/board.module.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { BoardComponent } from './board.component';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
import { SquareModule } from '../square/square.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [BoardComponent],
|
||||||
|
imports: [CommonModule, SharedModule, SquareModule],
|
||||||
|
exports: [BoardComponent]
|
||||||
|
})
|
||||||
|
export class BoardModule {}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
{{ 'PAGES.HOME.TITLE' | translate }}
|
{{ 'PAGES.HOME.TITLE' }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<a routerLink="/detail">{{ 'PAGES.HOME.GO_TO_DETAIL' | translate }}</a>
|
<a routerLink="/detail">{{ 'PAGES.HOME.GO_TO_DETAIL' }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,11 +3,22 @@ import { Component, Input, OnInit } from '@angular/core';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-square',
|
selector: 'app-square',
|
||||||
template: `
|
template: `
|
||||||
<p>
|
|
||||||
<button>{{ value }}</button>
|
<button>{{ value }}</button>
|
||||||
</p>
|
|
||||||
`,
|
`,
|
||||||
styles: [
|
styles: [
|
||||||
|
`
|
||||||
|
:host {
|
||||||
|
border: 1px grey solid;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
|
||||||
|
}
|
||||||
|
`
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SquareComponent {
|
export class SquareComponent {
|
||||||
|
|||||||
12
src/app/square/square.module.ts
Normal file
12
src/app/square/square.module.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
import { SquareComponent } from '../square/square.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [SquareComponent],
|
||||||
|
imports: [CommonModule, SharedModule],
|
||||||
|
exports: [SquareComponent]
|
||||||
|
})
|
||||||
|
export class SquareModule {}
|
||||||
Reference in New Issue
Block a user