initial commit
This commit is contained in:
@@ -1,4 +1 @@
|
||||
<router-outlet></router-outlet>
|
||||
<app-square value="X"></app-square>
|
||||
<app-square value="O"></app-square>
|
||||
<app-square value="X"></app-square>
|
||||
<app-board></app-board>
|
||||
@@ -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 { SquareComponent } from './square/square.component';
|
||||
import { BoardModule } from './board/board.module';
|
||||
|
||||
|
||||
// AoT requires an exported function for factories
|
||||
const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent, SquareComponent],
|
||||
declarations: [AppComponent],
|
||||
imports: [
|
||||
BoardModule,
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
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">
|
||||
<h1 class="title">
|
||||
{{ 'PAGES.HOME.TITLE' | translate }}
|
||||
{{ 'PAGES.HOME.TITLE' }}
|
||||
</h1>
|
||||
|
||||
<a routerLink="/detail">{{ 'PAGES.HOME.GO_TO_DETAIL' | translate }}</a>
|
||||
<a routerLink="/detail">{{ 'PAGES.HOME.GO_TO_DETAIL' }}</a>
|
||||
</div>
|
||||
|
||||
@@ -3,11 +3,22 @@ import { Component, Input, OnInit } from '@angular/core';
|
||||
@Component({
|
||||
selector: 'app-square',
|
||||
template: `
|
||||
<p>
|
||||
|
||||
<button>{{ value }}</button>
|
||||
</p>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
:host {
|
||||
border: 1px grey solid;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
|
||||
}
|
||||
`
|
||||
]
|
||||
})
|
||||
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