Commit 827fccb0 authored by evgen moruzhenko's avatar evgen moruzhenko

initial commit

parents
Pipeline #23976 failed with stages
in 0 seconds
node_modules/
dist/
icon.png

24.2 KB

{
"collection": "@nestjs/schematics",
"sourceRoot": "src"
}
This diff is collapsed.
{
"name": "discord-tictactoe-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@nestjs/cli": "^7.6.0",
"@nestjs/common": "^7.6.15",
"@nestjs/config": "^1.0.1",
"@nestjs/core": "^7.6.15",
"@nestjs/platform-express": "^7.6.15",
"@nestjs/schematics": "^7.3.1",
"discord-nestjs": "^1.1.12",
"discord.js": "^12.5.3"
}
}
import { Module } from '@nestjs/common';
import { BotModule } from './bot/bot.module';
@Module({
controllers: [],
providers: [],
imports: [BotModule],
})
export class AppModule {}
import { Injectable, Logger } from '@nestjs/common';
import { Once, ClientProvider, Client, OnCommand } from 'discord-nestjs';
import { Message, MessageEmbed } from 'discord.js';
@Injectable()
export class BotGateway {
private readonly logger = new Logger(BotGateway.name);
private screen: Message;
private _Place = '\u2423';
Please register or sign in to reply
private xPlace = '\u2715';
private oPlace = '\u006F';
private gameActive = true;
private currentPlayer = this.xPlace;
private gameState = [
  • Лучше вынести состояние игры/доски в отдельный класс. Single-Responsibility !

    Edited by Vitaly Kuzmin
Please register or sign in to reply
this._Place, this._Place, this._Place,
this._Place, this._Place, this._Place,
this._Place, this._Place, this._Place
];
private winningMessage = () => `Player ${this.currentPlayer} has won!`;
Please register or sign in to reply
private drawMessage = () => `Game ended in a draw!`;
private currentPlayerTurn = () => `It's ${this.currentPlayer}'s turn`;
private winningConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
private gameStateToField(stateArray: string[]) {
Please register or sign in to reply
const field = [];
for (let i = 0; i < stateArray.length; i += 1) {
if (i == 2 || i == 5 || i == 8) {
const temp = [];
temp.push(stateArray[i - 2]);
temp.push(stateArray[i - 1]);
temp.push(stateArray[i]);
field.push(temp);
Please register or sign in to reply
}
}
return field;
}
private handleResultValidation() {
let roundWon = false;
for (let i = 0; i <= 7; i++) {
Please register or sign in to reply
const winCondition = this.winningConditions[i];
let a = this.gameState[winCondition[0]];
Please register or sign in to reply
let b = this.gameState[winCondition[1]];
let c = this.gameState[winCondition[2]];
if (a === this._Place || b === this._Place || c === this._Place) {
continue;
}
if (a === b && b === c) {
roundWon = true;
break
}
}
if (roundWon) {
this.screen.channel.send(this.winningMessage());
this.gameActive = false;
return;
}
let roundDraw = !this.gameState.includes(this._Place);
Please register or sign in to reply
if (roundDraw) {
this.screen.channel.send(this.drawMessage());
this.gameActive = false;
return;
}
this.handlePlayerChange();
}
private handlePlayerChange() {
this.currentPlayer = this.currentPlayer === this.xPlace ? this.oPlace : this.xPlace;
this.screen.channel.send(this.currentPlayerTurn());
if (this.currentPlayer === this.oPlace) this.doAction();
}
private handleRestartGame() {
this.gameActive = true;
this.currentPlayer = this.xPlace;
this.gameState = [
this._Place, this._Place, this._Place,
this._Place, this._Place, this._Place,
this._Place, this._Place, this._Place
];
this.screen.channel.send(this.currentPlayerTurn());
}
private handleCellPlayed(cellIndex: number) {
this.gameState[cellIndex] = this.currentPlayer;
}
private handleCellSelected(cellNumber: number) {
const cellIndex = cellNumber - 1;
if (this.gameState[cellIndex] !== this._Place || !this.gameActive) {
  • Не то место для проверки активности игры

Please register or sign in to reply
this.screen.reply('No-no-no! This place is placed!');
return;
}
this.handleCellPlayed(cellIndex);
this.handleResultValidation();
}
private doAction() {
let place = Math.floor(Math.random() * (9 - 1) + 1);
while (this.gameState[place - 1] !== this._Place) {
Please register or sign in to reply
place = Math.floor(Math.random() * (9 - 1) + 1);
}
this.handleCellSelected(place);
}
@Client()
discordProvider: ClientProvider;
@Once({ event: 'ready' })
onReady(): void {
this.logger.log(`Logged in as ${this.discordProvider.getClient().user!.tag}!`);
}
@OnCommand({ name: 'start' })
async onStart(message: Message): Promise<void> {
this.screen = message;
this.handleRestartGame();
const reply = new MessageEmbed().addFields({
name: this.currentPlayerTurn(),
value: this.gameStateToField(this.gameState) },
  • Зачем передавать поле в метод, когда это все в одном классе

Please register or sign in to reply
);
await message.channel.send(reply);
}
@OnCommand({ name: 'place' })
async onPlace(message: Message): Promise<void> {
const position: number = Number(message.toString().split(' ')[1]);
this.screen = message;
this.handleCellSelected(position);
const reply = new MessageEmbed().addFields({
name: this.currentPlayerTurn(),
value: this.gameStateToField(this.gameState) },
  • имя метода не отображает его функциональность

Please register or sign in to reply
);
await message.channel.send(reply);
}
}
import { Module } from '@nestjs/common';
import { DiscordModule } from 'discord-nestjs';
import { BotGateway } from './bot.gateway';
@Module({
imports: [
DiscordModule.forRoot({
token: 'ODY5NTY4MDE5NjIwMjk4Nzky.YQAGUw.kW8iDvISPRXZmD60GjoVpRRALZg',
Please register or sign in to reply
commandPrefix: '/',
}),
],
providers: [BotGateway],
})
export class BotModule {}
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
{
"extends": "./tsconfig.json",
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strict": true,
"strictPropertyInitialization": false,
"skipLibCheck": true
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment