Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require_relative "model"
require_relative "view"

class Controller
def execute
loop do
run_menu
input = gets.chomp.upcase
print "\n"
sleep 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this one second pause before reacting to the input?

case input
when "S"
run_game
when "R"
display_move_list
when "Q"
quit_gracefully
else
puts "You aren't very good at this, are you?"
end
sleep 1
end
end

private
def run_menu
Menu.new.list_options
end

def quit_gracefully
puts "Quitting gracefully..."
print "\n"
sleep 2
%x( ^c )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wat. Are you sending a Ctrl-C into the process to make it quit? I'm not sure if that's awesome or crazy or crazy-awesome.

Perhaps a call to exit would do the job here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hahaha, I was proud of that line. Also, did not know about the exit command.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this work for you? I can't make it work.

No such file or directory - ^c (Errno::ENOENT)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it did. It spit out a 4-5 line error message, and quite. Hence the 'quitting gracefully'. In any case, now that I know about exit, that's clearly the way to go.

end

def display_move_list
if @game
puts "\tX\t|\tO\t"
puts "----------------+-----------------"
@game.move_list.each_slice(2) do |pair|
x1 = pair[0].loc[:x] + 1
y1 = pair[0].loc[:y] + 1
print "\t#{x1}, #{y1}\t|"
if pair[1]
x2 = pair[1].loc[:x] + 1
y2 = pair[1].loc[:y] + 1
print "\t#{x2}, #{y2}"
end
print "\n"
end
else
puts "No last game to review."
end
end

def run_game
@game = Game.new
@board = Board.new
@board.draw
while [email protected]? do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

until is available as the opposite of while

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The do on this line is not needed.

new_move
end
sleep 1
print "It's over. "
if @game.winner? == "X" || @game.winner? == "O"
puts "#{@game.winner?}'s win."
else
puts "It's a tie. How dull..."
end
end

def new_move
input = get_input
while !valid?(input) do
input = get_input
end
move = Move.new(input)
@game.register(move)
@board.add_to_pixel_array(move)
@board.draw
end

def get_input
print "row (1-3): "
x = gets.chomp.to_i - 1
print "column (1-3): "
y = gets.chomp.to_i - 1
{x: x, y: y}
end

def valid?(input)
x = input[:x]
y = input[:y]
if x < 0 || x > 2 || y < 0 || y > 2
puts "That move is out of bounds"
false
elsif [email protected][x][y].nil?
puts "That square is already full"
false
else
true
end
end

end

Controller.new.execute

45 changes: 45 additions & 0 deletions model.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
class Game
attr_reader :move_list, :grid

def initialize
@move_list = []
@grid = [[nil, nil, nil],[nil, nil, nil],[nil, nil, nil]]
end

def register(move)
x = move.loc[:x]
y = move.loc[:y]
@grid[x][y] = move.symbol

@move_list << move
end

def winner?
result = false
# check rows, columns for winner
for i in 0..2
result ||= (@grid[i][0] == @grid[i][1] && @grid[i][1] == @grid[i][2] && @grid[i][2])
result ||= (@grid[0][i] == @grid[1][i] && @grid[1][i] == @grid[2][i] && @grid[2][i])
end
# check diagonals for winner
result ||= (@grid[0][0] == @grid[1][1] && @grid[1][1] == @grid[2][2] && @grid[2][2])
result ||= (@grid[0][2] == @grid[1][1] && @grid[1][1] == @grid[2][0] && @grid[2][0])

# check for tie
# interesting project: better tie-detecting method
result ||= @move_list.count >= 9
end

end

class Move
attr_reader :symbol, :loc
@@count = 0

def initialize(location)
@@count += 1
@id = @@count
@loc = location
@symbol = @id.even? ? "O" : "X"
end
end
59 changes: 59 additions & 0 deletions view.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
class Menu
def list_options
puts ""
puts "(S)tart game"
puts "(R)eview last game"
puts "(Q)uit"
puts ""
print "Your choice: "
end
end

class Board

def initialize
# for good presentation, square width and height should both be even
@square_width = 6
@square_height = 4
@pixel_array = []
set_pixel_array
end

def draw
@pixel_array.each{ |row| puts row.join }
end

def add_to_pixel_array(move)
x_dim = pixelize(move.loc[:x], @square_height)
y_dim = pixelize(move.loc[:y], @square_width)
@pixel_array[x_dim][y_dim] = move.symbol
end

private
def total_length(square_length)
3 * square_length - 1
end

def set_pixel_array
for row in 1..total_length(@square_height)
row_output = []
for col in 1..total_length(@square_width)
if row % @square_height == 0 && col % @square_width == 0
row_output << "+"
elsif row % @square_height == 0
row_output << "-"
elsif col % @square_width == 0
row_output << "|"
else
row_output << " "
end
end
@pixel_array << row_output
end
end

def pixelize(value, square_length)
(value + 0.5) * square_length - 1
end

end