Last active
July 25, 2019 01:06
-
-
Save slpsys/59cd287834e7dbe7656ba90a4c918c73 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
class Player | |
private_class_method :new | |
class << self | |
def one ; 1 ; end | |
def two ; 2 ; end | |
end | |
end | |
class TTTEngine | |
attr_accessor :board | |
BOTTOM_LEFT = 2 ** 0 | |
BOTTOM_CENTER = 2 ** 1 | |
BOTTOM_RIGHT = 2 ** 2 | |
CENTER_LEFT = 2 ** 3 | |
CENTER_CENTER = 2 ** 4 | |
CENTER_RIGHT = 2 ** 5 | |
TOP_LEFT = 2 ** 6 | |
TOP_CENTER = 2 ** 7 | |
TOP_RIGHT = 2 ** 8 | |
WIN_CONDITIONS = [ | |
[BOTTOM_LEFT, BOTTOM_RIGHT, BOTTOM_RIGHT], | |
[CENTER_LEFT, CENTER_RIGHT, CENTER_RIGHT], | |
[TOP_LEFT, TOP_RIGHT, TOP_RIGHT], | |
[BOTTOM_LEFT, CENTER_LEFT, TOP_LEFT], | |
[BOTTOM_CENTER, CENTER_CENTER, TOP_CENTER], | |
[BOTTOM_RIGHT, CENTER_RIGHT, TOP_RIGHT], | |
[BOTTOM_LEFT, CENTER_CENTER, TOP_Rclass Player | |
private_class_method :new | |
class << self | |
def one ; 1 ; end | |
def two ; 2 ; end | |
end | |
end | |
class TTTEngine | |
attr_accessor :board | |
BOTTOM_LEFT = 2 ** 0 | |
BOTTOM_CENTER = 2 ** 1 | |
BOTTOM_RIGHT = 2 ** 2 | |
CENTER_LEFT = 2 ** 3 | |
CENTER_CENTER = 2 ** 4 | |
CENTER_RIGHT = 2 ** 5 | |
TOP_LEFT = 2 ** 6 | |
TOP_CENTER = 2 ** 7 | |
TOP_RIGHT = 2 ** 8 | |
WIN_CONDITIONS = [ | |
[BOTTOM_LEFT, BOTTOM_RIGHT, BOTTOM_RIGHT], | |
[CENTER_LEFT, CENTER_RIGHT, CENTER_RIGHT], | |
[TOP_LEFT, TOP_RIGHT, TOP_RIGHT], | |
[BOTTOM_LEFT, CENTER_LEFT, TOP_LEFT], | |
[BOTTOM_CENTER, CENTER_CENTER, TOP_CENTER], | |
[BOTTOM_RIGHT, CENTER_RIGHT, TOP_RIGHT], | |
[BOTTOM_LEFT, CENTER_CENTER, TOP_RIGHT], | |
[TOP_LEFT, CENTER_CENTER, BOTTOM_RIGHT] | |
] | |
def initialize | |
@board = 0 | |
end | |
def move(player, x, y) | |
b = transpose_for_read(player, @board) | |
coord = translate_coords(x, y) | |
msg = "Great move!" | |
status = "Success" | |
if game_won? | |
msg = "Game has already been won!" | |
status = "Failure" | |
elsif !coord | |
msg = "Invalid position!" | |
status = "Failure" | |
elsif !valid_move?(player, @board, coord) | |
msg = "Invalid move!" | |
status = "Failure" | |
else | |
b += coord | |
@board |= transpose_for_write(player, b) | |
if game_won? | |
msg = "Player #{player} has won!" | |
status = "Completion" | |
end | |
end | |
{ board_state: @board, message: msg, status: status} | |
end | |
private | |
def count_moves(board) | |
count = 0 | |
while board > 0 | |
count += 1 if board & 1 == 1 | |
board >>= 1 | |
end | |
count | |
end | |
def valid_move?(player, board, coord) | |
## Check if it's their turn | |
if count_moves(board).even? && player == Player.two | |
return false | |
end | |
## Check if anyone's taken this space | |
(transpose_for_read(Player.one, board) & coord == 0) && | |
(transpose_for_read(Player.two, board) & coord == 0) | |
end | |
def game_won? | |
WIN_CONDITIONS.each do |cond| | |
mask = cond[0] | cond[1] | cond[2] | |
if (transpose_for_read(Player.one, @board) & mask) == mask | |
puts "Player One has won!" | |
return Player.one | |
elsif (transpose_for_read(Player.two, @board) & mask) == mask | |
puts "Player Two has won!" | |
return Player.two | |
end | |
end | |
false | |
end | |
def translate_coords(x, y) | |
bx = translate_x(x) | |
by = translate_y(y) | |
if bx && by | |
Object.const_get("TTTEngine::#{by}_#{bx}") | |
else | |
nil | |
end | |
end | |
def translate_x(coord) | |
case coord | |
when 0 | |
:LEFT | |
when 1 | |
:CENTER | |
when 2 | |
:RIGHT | |
end | |
end | |
def translate_y(coord) | |
case coord | |
when 0 | |
:BOTTOM | |
when 1 | |
:CENTER | |
when 2 | |
:TOP | |
end | |
end | |
def transpose_for_read(player, board) | |
if player == Player.one | |
board & (2 ** 9 - 1) | |
else | |
(board >> 9) & (2 ** 9 - 1) | |
end | |
end | |
def transpose_for_write(player, board) | |
if player == Player.two | |
board << 9 | |
else | |
board | |
end | |
end | |
end | |
t = TTTEngine.new | |
puts t.move(Player.one, 0, 0) | |
puts t.move(Player.two, 0, 3) | |
puts t.move(Player.two, 0, 2) | |
puts t.move(Player.two, 0, 1) | |
puts t.move(Player.one, 1, 0) | |
puts t.move(Player.two, 0, 1) | |
puts t.move(Player.one, 2, 0)IGHT], | |
[TOP_LEFT, CENTER_CENTER, BOTTOM_RIGHT] | |
] | |
def initialize | |
@board = 0 | |
end | |
def move(player, x, y) | |
b = transpose_in(player, @board) | |
coord = translate_coords(x, y) | |
msg = "Great move!" | |
status = "Success" | |
if game_won? | |
msg = "Game has already been won!" | |
status = "Failure" | |
elsif !coord | |
msg = "Invalid position!" | |
status = "Failure" | |
elsif !valid_move?(player, @board, coord) | |
msg = "Invalid move!" | |
status = "Failure" | |
else | |
b += coord | |
@board |= transpose_out(player, b) | |
if game_won? | |
msg = "Player #{player} has won!" | |
status = "Completion" | |
end | |
end | |
{ board_state: @board, message: msg, status: status} | |
end | |
private | |
def count_moves(board) | |
count = 0 | |
while board > 0 | |
count += 1 if board & 1 == 1 | |
board >>= 1 | |
end | |
count | |
end | |
def valid_move?(player, board, coord) | |
## Check if it's their turn | |
if count_moves(board).even? && player == Player.two | |
return false | |
end | |
## Check if anyone's taken this space | |
(transpose_in(Player.one, board) & coord == 0) && | |
(transpose_in(Player.two, board) & coord == 0) | |
end | |
def game_won? | |
WIN_CONDITIONS.each do |cond| | |
mask = cond[0] | cond[1] | cond[2] | |
if (transpose_in(Player.one, @board) & mask) == mask | |
puts "Player One has won!" | |
return Player.one | |
elsif (transpose_in(Player.two, @board) & mask) == mask | |
puts "Player Two has won!" | |
return Player.two | |
end | |
end | |
false | |
end | |
def translate_coords(x, y) | |
bx = translate_x(x) | |
by = translate_y(y) | |
if bx && by | |
Object.const_get("TTTEngine::#{by}_#{bx}") | |
else | |
nil | |
end | |
end | |
def translate_x(coord) | |
case coord | |
when 0 | |
:LEFT | |
when 1 | |
:CENTER | |
when 2 | |
:RIGHT | |
end | |
end | |
def translate_y(coord) | |
case coord | |
when 0 | |
:BOTTOM | |
when 1 | |
:CENTER | |
when 2 | |
:TOP | |
end | |
end | |
def transpose_in(player, board) | |
if player == Player.one | |
board & (2 ** 9 - 1) | |
else | |
(board >> 9) & (2 ** 9 - 1) | |
end | |
end | |
def transpose_out(player, board) | |
if player == Player.two | |
board << 9 | |
else | |
board | |
end | |
end | |
end | |
t = TTTEngine.new | |
puts t.move(Player.one, 0, 0) | |
puts t.move(Player.two, 0, 3) | |
puts t.move(Player.two, 0, 2) | |
puts t.move(Player.two, 0, 1) | |
puts t.move(Player.one, 1, 0) | |
puts t.move(Player.two, 0, 1) | |
puts t.move(Player.one, 2, 0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment