Last active
August 29, 2015 14:04
-
-
Save rigibun/b5e70ad6649f44d69a7a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.stdio, | |
std.typecons; | |
import player; | |
enum boardDefault = (function char[8][] (){ | |
auto ret = new char[8][](8); | |
foreach(ref line; ret) | |
foreach(ref cell; line) | |
cell = '.'; | |
ret[3][3] = ret[4][4] = 'W'; | |
ret[3][4] = ret[4][3] = 'B'; | |
return ret; | |
})(); | |
class Othello | |
{ | |
enum Turn { black = 0, white = 1 } | |
enum Flags : uint { end = 1, skip = 2 } | |
alias Pos = Tuple!(int, "x", int, "y"); | |
char[8][] board; | |
Player playerWhite, playerBlack; | |
Turn turnPlayer; | |
public this(Player pBlack, Player pWhite) | |
{ | |
playerBlack = pBlack; | |
playerWhite = pWhite; | |
board = boardDefault; | |
turnPlayer = Turn.black; | |
} | |
public Tuple!(int, "black", int, "white") loop() | |
{ | |
drawBoard(); | |
while(gameHasContinued) | |
{ | |
if(placeToPutExists(turnPlayer)) | |
{ | |
Pos pos; | |
while(pos = (turnPlayer == Turn.black ? playerBlack : playerWhite).getMove(this), !canPut(turnPlayer, pos)) | |
writeln("Position", pos.x, " : ", pos.y, "is invalid."); | |
putStone(turnPlayer, pos); | |
drawBoard(); | |
} | |
else | |
{ | |
writeln("skip"); | |
} | |
turnPlayer = turnPlayer == Turn.black ? Turn.white : Turn.black; | |
} | |
return count(); | |
} | |
public Flags next() | |
{ | |
Flags flag; | |
if(gameHasContinued) | |
{ | |
if(placeToPutExists(turnPlayer)) | |
{ | |
Pos pos; | |
while(pos = (turnPlayer == Turn.black ? playerBlack : playerWhite).getMove(this), !canPut(turnPlayer, pos)) | |
writeln("Position", pos.x, " : ", pos.y, "is invalid."); | |
putStone(turnPlayer, pos); | |
} | |
else | |
{ | |
flag |= Flags.skip; | |
} | |
turnPlayer = turnPlayer == Turn.black ? Turn.white : Turn.black; | |
} | |
else | |
{ | |
flag |= Flags.end; | |
} | |
return flag; | |
} | |
public Tuple!(int, "black", int, "white") count() | |
{ | |
auto black = 0, white = 0; | |
foreach(line; board) | |
foreach(cell; line) | |
{ | |
if(cell == 'B') | |
black++; | |
else if(cell == 'W') | |
white++; | |
} | |
return Tuple!(int, "black", int, "white")(black, white); | |
} | |
public char[8][] getBoard() | |
{ | |
auto retBoard = new char[8][](8); | |
foreach(i; 0 .. 8) | |
foreach(j; 0 .. 8) | |
retBoard[i][j] = board[i][j]; | |
return retBoard; | |
} | |
public bool canPut(Turn turn, Pos pos) | |
{ | |
if(board[pos.y][pos.x] != '.') | |
return false; | |
static dx = [-1, 0, 1, -1, 1, -1, 0, 1]; | |
static dy = [-1, -1, -1, 0, 0, 1, 1, 1]; | |
auto stone = turn == Turn.black ? 'B' : 'W'; | |
auto opStone = stone == 'B' ? 'W' : 'B'; | |
auto flag = false; | |
foreach(i; 0 .. 8) | |
{ | |
auto x = pos.x, y = pos.y; | |
if(x + dx[i] < 8UL && y + dy[i] < 8UL && board[y + dy[i]][x + dx[i]] == opStone) | |
{ | |
while(x += dx[i], y += dy[i], !flag && x < 8UL && y < 8UL && board[y][x] != '.') | |
{ | |
flag = board[y][x] == stone; | |
} | |
} | |
if(flag) break; | |
} | |
return flag; | |
} | |
private bool gameHasContinued() | |
{ | |
return placeToPutExists(Turn.black) || placeToPutExists(Turn.white); | |
} | |
private bool placeToPutExists(Turn turn) | |
{ | |
auto flag = false; | |
foreach(y; 0 .. 8) | |
{ | |
foreach(x; 0 .. 8) | |
flag = flag || canPut(turn, Pos(x, y)); | |
if(flag) | |
break; | |
} | |
return flag; | |
} | |
private void putStone(Turn turn, Pos pos) | |
{ | |
static dx = [-1, 0, 1, -1, 1, -1, 0, 1]; | |
static dy = [-1, -1, -1, 0, 0, 1, 1, 1]; | |
auto stone = turn == Turn.black ? 'B' : 'W'; | |
auto opStone = stone == 'B' ? 'W' : 'B'; | |
board[pos.y][pos.x] = stone; | |
foreach(i; 0 .. 8) | |
{ | |
auto flag = false; | |
auto x = pos.x, y = pos.y; | |
if(x + dx[i] < 8UL && y + dy[i] < 8UL && board[y + dy[i]][x + dx[i]] == opStone) | |
while(x += dx[i], y += dy[i], !flag && x < 8UL && y < 8UL && board[y][x] != '.') | |
flag = board[y][x] == stone; | |
x = pos.x, y = pos.y; | |
if(flag) | |
while(x += dx[i], y += dy[i], x < 8UL && y < 8UL && board[y][x] != stone) | |
board[y][x] = stone; | |
} | |
} | |
private void drawBoard() | |
{ | |
writeln(" 01234567"); | |
foreach(y, line; board) | |
{ | |
y.write; | |
foreach(cell; line) | |
cell.write; | |
writeln; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.typecons; | |
import othello; | |
interface Player | |
{ | |
public alias Pos = Tuple!(int, "x", int, "y"); | |
Pos getMove(Othello); | |
} | |
class CliUser : Player | |
{ | |
import std.stdio, | |
std.string, | |
std.conv; | |
override Pos getMove(Othello o) | |
{ | |
writeln("Input you move:"); | |
string[] input; | |
Pos move; | |
while(input = readln.split, input.length < 2){} | |
move.x = input[0].to!ubyte; | |
move.y = input[1].to!ubyte; | |
return move; | |
} | |
} | |
class RandomPlayer : Player | |
{ | |
Othello.Turn mycolor; | |
this(Othello.Turn color) | |
{ | |
mycolor = color; | |
} | |
override Pos getMove(Othello o) | |
{ | |
import std.random; | |
Pos pos; | |
while(pos = Pos(uniform(0, 8), uniform(0, 8)), !o.canPut(mycolor, pos)){} | |
return pos; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment