Skip to content

Commit

Permalink
色々修正
Browse files Browse the repository at this point in the history
  • Loading branch information
takenaka committed Oct 21, 2021
1 parent 5a95342 commit 608a5b2
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 71 deletions.
5 changes: 1 addition & 4 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import { StoneCreator } from './model/stone';

(async () => {
try {
const board = new Board();
const io = new IO(prompt);

const othello = new Othello(board, new StoneCreator, new PlayerCreator, io);
const othello = new Othello(new Board(), new StoneCreator(), new PlayerCreator(), new IO(prompt));
othello.start();
} catch (e) {
const _e = e as Error;
Expand Down
18 changes: 9 additions & 9 deletions src/model/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface IBoard {
size: number;
state: Array<IStone | null>[];
putStone: (coodinate: Coodinate, stone: IStone) => void;
canPutStone: (coodinate: Coodinate) => boolean;
isEmpty: (coodinate: Coodinate) => boolean;
getStone: (coodinate: Coodinate) => IStone | null;
countStone: (state: StoneState) => number;
isFull: () => boolean;
Expand Down Expand Up @@ -54,12 +54,12 @@ export class Board implements IBoard {
return false;
};

public canPutStone = (coodinate: Coodinate) => {
return this.existSpace(coodinate) && !Boolean(this._state[coodinate.y][coodinate.x]);
public isEmpty = (coodinate: Coodinate) => {
return this.existSquare(coodinate) && !Boolean(this._state[coodinate.y][coodinate.x]);
};

private existSpace = (coodinate: Coodinate) => {
// 範囲外
// マス目が存在するか
private existSquare = (coodinate: Coodinate) => {
if (this._state[coodinate.y] === undefined || this._state[coodinate.y][coodinate.x] === undefined) {
return false;
}
Expand All @@ -68,15 +68,15 @@ export class Board implements IBoard {
};

public putStone = (coodinate: Coodinate, stone: IStone) => {
if (!this.existSpace(coodinate) || !this.canPutStone(coodinate)) {
if (!this.existSquare(coodinate) || !this.isEmpty(coodinate)) {
throw new Error('置けないよ');
}

this._state[coodinate.y][coodinate.x] = stone;
};

public getStone = (coodinate: Coodinate) => {
if (!this.existSpace(coodinate)) {
if (!this.existSquare(coodinate)) {
throw new Error('範囲外だよ');
}

Expand All @@ -98,9 +98,9 @@ export class Board implements IBoard {

public isFull = () => {
if (this.countStone('white') + this.countStone('black') < this.size ** 2) {
return false
return false;
}

return true;
}
};
}
4 changes: 2 additions & 2 deletions src/model/io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import inquirer from 'inquirer';
import { Coodinate, IBoard } from './board';

export interface IIO {
message: (message: any) => void;
showMessage: (message: any) => void;
selectBoardSize: () => Promise<number>;
selectXYCoodinate: (board: IBoard) => Promise<Coodinate>;
showBoard: (board: IBoard) => void;
Expand All @@ -14,7 +14,7 @@ export class IO implements IIO {
public constructor(prompt: inquirer.PromptModule) {
this.prompt = prompt;
}
public message = (message: any) => {
public showMessage = (message: any) => {
console.log(message);
};

Expand Down
123 changes: 67 additions & 56 deletions src/model/othello.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface XYDirection {
x: Direction;
}

export const directions: XYDirection[] = [
const directions: XYDirection[] = [
{ y: -1, x: 0 },
{ y: -1, x: 1 },
{ y: 0, x: 1 },
Expand All @@ -27,8 +27,8 @@ export class Othello {
private readonly player1: IPlayer;
private readonly player2: IPlayer;
private readonly io: IIO;
private turnPlayer: IPlayer;
private pass = 0;
private currentPlayer: IPlayer;
private passedCount = 0;

constructor(board: IBoard, stoneCreator: IStoneCreator, playerCreator: IPlayerCreator, io: IIO) {
this.board = board;
Expand All @@ -37,96 +37,107 @@ export class Othello {
this.player2 = playerCreator.factory('white', '白');
this.io = io;

this.turnPlayer = this.player1;
this.currentPlayer = this.player1;
}

public start = async () => {
try {
const answer = await this.io.selectBoardSize();
this.board.init(answer);

const base = answer / 2 - 1;

for (let y = 0; y < 2; y++) {
for (let x = 0; x < 2; x++) {
if (x === y) {
this.board.putStone({ y: y + base, x: x + base }, this.stoneCreator.factory('black'));
} else {
this.board.putStone({ y: y + base, x: x + base }, this.stoneCreator.factory('white'));
}
}
}
// 初期盤面の生成
const size = await this.io.selectBoardSize();
this.setInitialBoard(size);

this.io.message(`先行は${this.turnPlayer.name}です`);
this.io.showMessage(`先行は${this.currentPlayer.name}です`);

// 2連続パスか盤面が一杯になるまで
while (this.pass < 2 && !this.board.isFull()) {
while (this.passedCount < 2 && !this.board.isFull()) {
await this.playTurn();
this.changeTurn();
}

this.end();
} catch (e) {
const _e = e as Error;
this.io.message(_e.message);
this.io.showMessage(_e.message);
}
};

private setInitialBoard = (size: number) => {
this.board.init(size);

const base = size / 2 - 1;

for (let y = 0; y < 2; y++) {
for (let x = 0; x < 2; x++) {
if (x === y) {
this.board.putStone({ y: y + base, x: x + base }, this.stoneCreator.factory('black'));
} else {
this.board.putStone({ y: y + base, x: x + base }, this.stoneCreator.factory('white'));
}
}
}
};

private putStone = (coodinate: Coodinate) => {
const flipableStones = this.getFlipableStoneCoodinates(coodinate);
const flippableStones = this.getFlipableStoneCoodinates(coodinate);

if (flipableStones.length === 0) {
if (flippableStones.length === 0) {
throw new Error('ひっくり返せる石がないよ');
}

this.board.putStone(coodinate, this.stoneCreator.factory(this.turnPlayer.color));
flipableStones.forEach(flipableStone => {
this.board.putStone(coodinate, this.stoneCreator.factory(this.currentPlayer.color));
flippableStones.forEach(flipableStone => {
const stone = this.board.getStone(flipableStone);
stone?.flip();
});
};

private changeTurn = () => {
this.turnPlayer = this.turnPlayer === this.player1 ? this.player2 : this.player1;
this.currentPlayer = this.currentPlayer === this.player1 ? this.player2 : this.player1;
};

private playTurn = async () => {
this.io.showBoard(this.board);
this.io.message(`${this.turnPlayer.name}の番`);
this.io.showMessage(`${this.currentPlayer.name}の番`);

if (!this.canPutStone()) {
// 置く場所がない場合
this.passedCount++;

this.io.showMessage(`${this.currentPlayer.name}は置けないのでパス`);
return;
}

this.passedCount = 0;

// 置けるまで聞く
while (true) {
try {
const coodinate = await this.io.selectXYCoodinate(this.board);
this.putStone(coodinate);
break;
} catch (e) {
const _e = e as Error;
console.log(`\n${_e.message}\n`);
}
}
};

// 置ける場所があるかどうか
private canPutStone = () => {
// 全部のマスを調べて置ける場所があるかどうか調べる
for (let i = 0; i < this.board.size; i++) {
for (let j = 0; j < this.board.size; j++) {
if (!this.board.canPutStone({ y: i, x: j })) {
if (!this.board.isEmpty({ y: i, x: j })) {
continue;
}

const flipableStones = this.getFlipableStoneCoodinates({ y: i, x: j });

// 置く場所があればターンを実行して終了
if (flipableStones.length > 0) {
this.pass = 0;

// 置けるまで聞く
while (true) {
const coodinate = await this.io.selectXYCoodinate(this.board);
try {
this.putStone(coodinate);
break;
} catch (e) {
const _e = e as Error;
console.log(`\n${_e.message}\n`);
}
}
return;
const flippableStones = this.getFlipableStoneCoodinates({ y: i, x: j });
if (flippableStones.length > 0) {
return true;
}
}
}

// 置く場所がない場合
this.pass++;

this.io.message(`${this.turnPlayer.name}は置けないのでパス`);
return false;
};

// 全方向を見て裏返せる石を探す
Expand Down Expand Up @@ -163,7 +174,7 @@ export class Othello {
}

//自分の石があったならcoodinatesを返す
if (boardMapCoordinate.state === this.turnPlayer.color) {
if (boardMapCoordinate.state === this.currentPlayer.color) {
return coodinates;
}

Expand All @@ -183,15 +194,15 @@ export class Othello {
const player1Count = this.board.countStone(this.player1.color);
const player2Count = this.board.countStone(this.player2.color);

this.io.message(`${this.player1.name}: ${player1Count}`);
this.io.message(`${this.player2.name}: ${player2Count}`);
this.io.showMessage(`${this.player1.name}: ${player1Count}`);
this.io.showMessage(`${this.player2.name}: ${player2Count}`);

let winner = player1Count > player2Count ? this.player1.name : this.player2.name;
if (player1Count === player2Count) {
winner = 'なし';
}

this.io.message(`勝者は: ${winner}`);
this.io.message('\nゲーム終了');
this.io.showMessage(`勝者は: ${winner}`);
this.io.showMessage('\nゲーム終了');
};
}

0 comments on commit 608a5b2

Please sign in to comment.