Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
115
Task/Tic-tac-toe/D/tic-tac-toe.d
Normal file
115
Task/Tic-tac-toe/D/tic-tac-toe.d
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import std.stdio, std.string, std.algorithm, std.conv, std.random,
|
||||
std.ascii, std.array, std.range, std.math;
|
||||
|
||||
struct GameBoard {
|
||||
dchar[9] board = "123456789";
|
||||
enum : dchar { human = 'X', computer = 'O' }
|
||||
enum Game { going, humanWins, computerWins, draw }
|
||||
|
||||
const pure nothrow @safe @nogc invariant() {
|
||||
int nHuman = 0, nComputer = 0;
|
||||
foreach (immutable i, immutable c; board)
|
||||
if (c.isDigit)
|
||||
assert(i == c - '1'); // In correct position?
|
||||
else {
|
||||
assert(c == human || c == computer);
|
||||
(c == human ? nHuman : nComputer)++;
|
||||
}
|
||||
assert(abs(nHuman - nComputer) <= 1);
|
||||
}
|
||||
|
||||
string toString() const pure {
|
||||
return format("%(%-(%s|%)\n-+-+-\n%)", board[].chunks(3));
|
||||
}
|
||||
|
||||
bool isAvailable(in int i) const pure nothrow @safe @nogc {
|
||||
return i >= 0 && i < 9 && board[i].isDigit;
|
||||
}
|
||||
|
||||
auto availablePositions() const pure nothrow @safe /*@nogc*/ {
|
||||
return 9.iota.filter!(i => isAvailable(i));
|
||||
}
|
||||
|
||||
Game winner() const pure nothrow @safe /*@nogc*/ {
|
||||
static immutable wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
|
||||
[0, 3, 6], [1, 4, 7], [2, 5, 8],
|
||||
[0, 4, 8], [2, 4, 6]];
|
||||
|
||||
foreach (immutable win; wins) {
|
||||
immutable bw0 = board[win[0]];
|
||||
if (bw0.isDigit)
|
||||
continue; // Nobody wins on this one.
|
||||
|
||||
if (bw0 == board[win[1]] && bw0 == board[win[2]])
|
||||
return bw0 == GameBoard.human ?
|
||||
Game.humanWins :
|
||||
Game.computerWins;
|
||||
}
|
||||
|
||||
return availablePositions.empty ? Game.draw: Game.going;
|
||||
}
|
||||
|
||||
bool isFinished() const pure nothrow @safe /*@nogc*/ {
|
||||
return winner != Game.going;
|
||||
}
|
||||
|
||||
int computerMove() const // Random move.
|
||||
out(res) {
|
||||
assert(res >= 0 && res < 9 && isAvailable(res));
|
||||
} body {
|
||||
// return availablePositions.array.choice;
|
||||
return availablePositions.array[uniform(0, $)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GameBoard playGame() {
|
||||
GameBoard board;
|
||||
bool playsHuman = true;
|
||||
|
||||
while (!board.isFinished) {
|
||||
board.writeln;
|
||||
|
||||
int move;
|
||||
if (playsHuman) {
|
||||
do {
|
||||
writef("Your move (available moves: %s)? ",
|
||||
board.availablePositions.map!q{ a + 1 });
|
||||
readf("%d\n", &move);
|
||||
move--; // Zero based indexing.
|
||||
if (move < 0)
|
||||
return board;
|
||||
} while (!board.isAvailable(move));
|
||||
} else
|
||||
move = board.computerMove;
|
||||
|
||||
assert(board.isAvailable(move));
|
||||
writefln("\n%s chose %d", playsHuman ? "You" : "I", move + 1);
|
||||
board.board[move] = playsHuman ? GameBoard.human :
|
||||
GameBoard.computer;
|
||||
playsHuman = !playsHuman; // Switch player.
|
||||
}
|
||||
|
||||
return board;
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
"Tic-tac-toe game player.\n".writeln;
|
||||
immutable outcome = playGame.winner;
|
||||
|
||||
final switch (outcome) {
|
||||
case GameBoard.Game.going:
|
||||
"Game stopped.".writeln;
|
||||
break;
|
||||
case GameBoard.Game.humanWins:
|
||||
"\nYou win!".writeln;
|
||||
break;
|
||||
case GameBoard.Game.computerWins:
|
||||
"\nI win.".writeln;
|
||||
break;
|
||||
case GameBoard.Game.draw:
|
||||
"\nDraw".writeln;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue