Created
January 9, 2024 23:14
-
-
Save thebugcatcher/ef94e3803021f7295e5cb58df604d45c to your computer and use it in GitHub Desktop.
Tic Tac Toe Terminal Game in Ruby (mentorship)
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 Board | |
# Grid is 2D array | |
attr_accessor :grid | |
X_VALUE = "x" | |
O_VALUE = "o" | |
EMPTY_VALUE = " " | |
def initialize(board_dimension) | |
grid = [] | |
bound = board_dimension - 1 | |
(0..bound).each do |row| | |
grid[row] = [] | |
(0..bound).each do |col| | |
grid[row][col] = EMPTY_VALUE | |
end | |
end | |
@grid = grid | |
end | |
def add_to_grid(row, col, value) | |
grid[row - 1][col - 1] = value | |
end | |
def display | |
str = "-------------\n" | |
grid.each do |row| | |
str += "| " | |
row.each do |value| | |
str += value | |
str += " | " | |
end | |
str += "\n" | |
str += "-------------\n" | |
end | |
str | |
end | |
end | |
class User | |
attr_accessor :name | |
def initialize(name) | |
@name = name | |
end | |
end | |
class Game | |
attr_accessor :user_1, :user_2, :board, :current_turn, :turns | |
def initialize(user_1, user_2, board_dimension) | |
@user_1 = user_1 | |
@user_2 = user_2 | |
@board = Board.new(board_dimension) | |
@current_turn = [user_1, user_2].sample() | |
@turns = [] | |
end | |
def add_turn(row, col) | |
if board.grid[row - 1][col - 1] == Board::EMPTY_VALUE | |
value = value_from_user(current_turn) | |
board.add_to_grid(row, col, value) | |
update_current_turn | |
else | |
raise "Bad user input" | |
end | |
end | |
def display | |
<<~HEREDOC | |
X: #{user_1.name} O: #{user_2.name} | |
Current Turn: #{current_turn.name} | |
#{board.display} | |
HEREDOC | |
end | |
private | |
def value_from_user(user) | |
if user.name == user_1.name | |
Board::X_VALUE | |
elsif user.name == user_2.name | |
Board::O_VALUE | |
else | |
raise "Bad user input" | |
end | |
end | |
def update_current_turn | |
if current_turn.name == user_1.name | |
@current_turn = user_2 | |
elsif current_turn.name == user_2.name | |
@current_turn = user_1 | |
else | |
raise "Bad user" | |
end | |
end | |
end | |
module GameRunner | |
def self.call(game) | |
puts game.display | |
puts "____\n\n" | |
puts "#{game.current_turn.name} input: " | |
row, col = gets.chomp.split(",").map(&:to_i) | |
game.add_turn(row, col) | |
check_state(game) | |
puts `clear` | |
call(game) | |
end | |
def self.check_state(game) | |
x_wins = winning_criteria(game.board.grid, Board::X_VALUE) | |
o_wins = winning_criteria(game.board.grid, Board::O_VALUE) | |
if x_wins && o_wins | |
raise "Error" | |
elsif x_wins | |
puts `clear` | |
puts game.display | |
puts "Winner #{game.user_1.name}!" | |
exit | |
elsif o_wins | |
puts `clear` | |
puts game.display | |
puts "Winner #{game.user_2.name}!" | |
exit | |
elsif check_draw(game.board.grid) | |
puts `clear` | |
puts game.display | |
puts "Draw!" | |
exit | |
end | |
end | |
def self.winning_criteria(grid, value) | |
winning_criteria_row(grid, value) || | |
winning_criteria_col(grid, value) || | |
winning_criteria_diag_1(grid, value) || | |
winning_criteria_diag_2(grid, value) | |
end | |
def self.winning_criteria_row(grid, value) | |
grid.any? do |row| | |
row.all? { |cell| cell == value } | |
end | |
end | |
def self.winning_criteria_col(grid, value) | |
dimension = grid.size - 1 | |
(0..dimension).any? do |index| | |
grid.all? do |row| | |
row[index] == value | |
end | |
end | |
end | |
def self.winning_criteria_diag_1(grid, value) | |
index = 0 | |
grid.all? do |row| | |
result = row[index] == value | |
index += 1 | |
result | |
end | |
end | |
def self.winning_criteria_diag_2(grid, value) | |
index = grid.size - 1 | |
grid.all? do |row| | |
result = row[index] == value | |
index -= 1 | |
result | |
end | |
end | |
def self.check_draw(grid) | |
grid.all? do |row| | |
row.all? do |cell| | |
cell != Board::EMPTY_VALUE | |
end | |
end | |
end | |
private_class_method :check_state, | |
:winning_criteria, | |
:winning_criteria_row, | |
:winning_criteria_col, | |
:winning_criteria_diag_1, | |
:winning_criteria_diag_2 | |
end | |
user_1 = User.new("User 1") | |
user_2 = User.new("User 2") | |
game = Game.new(user_1, user_2, 3) | |
puts `clear` | |
GameRunner.call(game) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment