diff --git a/controller.rb b/controller.rb new file mode 100644 index 0000000..4eb138b --- /dev/null +++ b/controller.rb @@ -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 + 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 ) + 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 !@game.winner? do + 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 !@game.grid[x][y].nil? + puts "That square is already full" + false + else + true + end + end + +end + +Controller.new.execute + diff --git a/model.rb b/model.rb new file mode 100644 index 0000000..ba1ce73 --- /dev/null +++ b/model.rb @@ -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 diff --git a/view.rb b/view.rb new file mode 100644 index 0000000..82b7fdb --- /dev/null +++ b/view.rb @@ -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