From 701bdc68371ddb140aabfbf0fdaa89fb81185d3f Mon Sep 17 00:00:00 2001 From: Joe Reich Date: Fri, 18 Dec 2015 16:32:00 -0500 Subject: [PATCH 1/7] basic outline, plus view --- controller.rb | 29 ++++++++++++++++++++++++++ model.rb | 40 ++++++++++++++++++++++++++++++++++++ view.rb | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 controller.rb create mode 100644 model.rb create mode 100644 view.rb diff --git a/controller.rb b/controller.rb new file mode 100644 index 0000000..fecd4ef --- /dev/null +++ b/controller.rb @@ -0,0 +1,29 @@ +class Controller + def execute + # show menu + # run game until it is over + # display game information + # show menu + end + + def run_game + # player whose move it is goes + # check for win + # change whose move it is + # repeat + end + + def show_menu + # display some stuff + # get input to start game + # should this be in the view? + end + + def new_move + # get user input, parse + # create Move.new + # add the move the game.moves + # tell the view to add the move to the pixel array + # and draw + end +end \ No newline at end of file diff --git a/model.rb b/model.rb new file mode 100644 index 0000000..f08ce84 --- /dev/null +++ b/model.rb @@ -0,0 +1,40 @@ +class Game + attr_accessor :moves + + + def initialize + @moves = [] + end + + + + def winner? + + end +end + +class Move + attr_reader :symbol, :loc, :game + @@count = 0 + + def initialize(x_loc, y_loc, game) + @@count += 1 + @id = @@count + @loc = {x: x_loc, y: y_loc} + @game = game + + add_move_to_register + end + + # move this method to the controller? + def add_move_to_register + @game.moves << @loc + end +end + +# g = Game.new +# m1 = Move.new(2,2,g) +# m2 = Move.new(1,1,g) + +# p g.moves + diff --git a/view.rb b/view.rb new file mode 100644 index 0000000..f5d8824 --- /dev/null +++ b/view.rb @@ -0,0 +1,56 @@ +class Menu +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 + + # private + def total_length(square_length) + 3 * square_length - 1 + end + + # move this to the model? + 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 add_move_to_pixel_array(symbol, location) + x_dim = pixelize(location[:x], @square_width) + y_dim = pixelize(location[:y], @square_height) + @pixel_array[y_dim][x_dim] = symbol + end + + def pixelize(value, square_length) + (value - 0.5) * square_length - 1 + end + +end + +# b = Board.new +# b.add_move_to_pixel_array("X", {x: 1, y: 1}) +# b.draw From ed0184fec3be49c52d968d1da104754a38d3752d Mon Sep 17 00:00:00 2001 From: Joe Reich Date: Fri, 18 Dec 2015 17:22:44 -0500 Subject: [PATCH 2/7] can now make a single move --- controller.rb | 43 +++++++++++++++++++++++++++++-------------- model.rb | 15 +++++++-------- view.rb | 15 +++++++-------- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/controller.rb b/controller.rb index fecd4ef..17d538f 100644 --- a/controller.rb +++ b/controller.rb @@ -1,18 +1,17 @@ +require_relative "model" +require_relative "view" + class Controller def execute # show menu - # run game until it is over + @game = Game.new + @board = Board.new + new_move + # new moves until game is over # display game information # show menu end - def run_game - # player whose move it is goes - # check for win - # change whose move it is - # repeat - end - def show_menu # display some stuff # get input to start game @@ -20,10 +19,26 @@ def show_menu end def new_move - # get user input, parse - # create Move.new - # add the move the game.moves - # tell the view to add the move to the pixel array - # and draw + # request, parse, and validate input + move = Move.new(input, @game) + @board.add_to_pixel_array(move) + @board.draw + # model.add_to_register(move) + # view.add_to_pixel_array(move) + # view.draw + end + + def input + print "row (1-3): " + x = gets.chomp.to_i + print "column (1-3): " + y = gets.chomp.to_i + {x: x, y: y} end -end \ No newline at end of file + + +end + +c = Controller.new +c.execute + diff --git a/model.rb b/model.rb index f08ce84..2e405d9 100644 --- a/model.rb +++ b/model.rb @@ -11,25 +11,24 @@ def initialize def winner? end + + def add_to_register(move) + @game.moves << move + end end class Move attr_reader :symbol, :loc, :game @@count = 0 - def initialize(x_loc, y_loc, game) + def initialize(location, game) @@count += 1 @id = @@count - @loc = {x: x_loc, y: y_loc} + @loc = location @game = game - - add_move_to_register + @symbol = @id.even? ? "X" : "O" end - # move this method to the controller? - def add_move_to_register - @game.moves << @loc - end end # g = Game.new diff --git a/view.rb b/view.rb index f5d8824..f2f7929 100644 --- a/view.rb +++ b/view.rb @@ -15,12 +15,17 @@ def draw @pixel_array.each{ |row| puts row.join } end - # private + 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 - # move this to the model? def set_pixel_array for row in 1..total_length(@square_height) row_output = [] @@ -39,12 +44,6 @@ def set_pixel_array end end - def add_move_to_pixel_array(symbol, location) - x_dim = pixelize(location[:x], @square_width) - y_dim = pixelize(location[:y], @square_height) - @pixel_array[y_dim][x_dim] = symbol - end - def pixelize(value, square_length) (value - 0.5) * square_length - 1 end From 14554394093d9a9fb86fb5cd3c453ce1aa9776a5 Mon Sep 17 00:00:00 2001 From: Joe Reich Date: Fri, 18 Dec 2015 20:37:58 -0500 Subject: [PATCH 3/7] minimally viable --- controller.rb | 38 +++++++++++++++++++++++++++++--------- model.rb | 36 ++++++++++++++++++++++++------------ view.rb | 6 +----- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/controller.rb b/controller.rb index 17d538f..81729b8 100644 --- a/controller.rb +++ b/controller.rb @@ -6,8 +6,11 @@ def execute # show menu @game = Game.new @board = Board.new - new_move - # new moves until game is over + # 5.times {new_move} + while !@game.winner? do + new_move + end + puts "It's over! #{@game.winner?}'s win" # display game information # show menu end @@ -19,23 +22,40 @@ def show_menu end def new_move - # request, parse, and validate input + input = get_input + while !valid?(input) do + input = get_input + end move = Move.new(input, @game) + @game.register(move) @board.add_to_pixel_array(move) @board.draw - # model.add_to_register(move) - # view.add_to_pixel_array(move) - # view.draw end - def input + # move this to model too? + def get_input print "row (1-3): " - x = gets.chomp.to_i + x = gets.chomp.to_i - 1 print "column (1-3): " - y = gets.chomp.to_i + y = gets.chomp.to_i - 1 {x: x, y: y} end + # move this to the model? + 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 diff --git a/model.rb b/model.rb index 2e405d9..fb2bb0e 100644 --- a/model.rb +++ b/model.rb @@ -1,19 +1,38 @@ class Game - attr_accessor :moves + attr_accessor :move_list, :grid def initialize - @moves = [] + @move_list = [] + @grid = [[nil, nil, nil],[nil, nil, nil],[nil, nil, nil]] end + def winner? + row_winner? || col_winner? || diag_winner? + end + def register(move) + @move_list << move + x = move.loc[:x] + y = move.loc[:y] + @grid[x][y] = move.symbol + end - def winner? + def row_winner? + (@grid[0][0] == @grid[0][1] && @grid[0][1] == @grid[0][2] && @grid[0][2]) || + (@grid[1][0] == @grid[1][1] && @grid[1][1] == @grid[1][2] && @grid[1][2]) || + (@grid[2][0] == @grid[2][1] && @grid[2][1] == @grid[2][2] && @grid[2][2]) + end + def col_winner? + (@grid[0][0] == @grid[1][0] && @grid[1][0] == @grid[2][0] && @grid[2][0]) || + (@grid[0][1] == @grid[1][1] && @grid[1][1] == @grid[2][1] && @grid[2][1]) || + (@grid[0][2] == @grid[1][2] && @grid[1][2] == @grid[2][2] && @grid[2][2]) end - def add_to_register(move) - @game.moves << move + def diag_winner? + (@grid[0][0] == @grid[1][1] && @grid[1][1] == @grid[2][2] && @grid[2][2]) || + (@grid[2][0] == @grid[1][1] && @grid[1][1] == @grid[0][2] && @grid[0][2]) end end @@ -30,10 +49,3 @@ def initialize(location, game) end end - -# g = Game.new -# m1 = Move.new(2,2,g) -# m2 = Move.new(1,1,g) - -# p g.moves - diff --git a/view.rb b/view.rb index f2f7929..ad60188 100644 --- a/view.rb +++ b/view.rb @@ -45,11 +45,7 @@ def set_pixel_array end def pixelize(value, square_length) - (value - 0.5) * square_length - 1 + (value + 0.5) * square_length - 1 end end - -# b = Board.new -# b.add_move_to_pixel_array("X", {x: 1, y: 1}) -# b.draw From ce72cb481a3d34f66b6c0c89c91fddda9dc197ae Mon Sep 17 00:00:00 2001 From: Joe Reich Date: Fri, 18 Dec 2015 20:59:08 -0500 Subject: [PATCH 4/7] Actually minimally viable (ties) --- controller.rb | 7 +++++-- model.rb | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/controller.rb b/controller.rb index 81729b8..a95c94c 100644 --- a/controller.rb +++ b/controller.rb @@ -6,11 +6,14 @@ def execute # show menu @game = Game.new @board = Board.new - # 5.times {new_move} while !@game.winner? do new_move end - puts "It's over! #{@game.winner?}'s win" + if @game.winner? == "X" || @game.winner? == "O" + puts "It's over! #{@game.winner?}'s win" + else + puts "It's over! It's a tie!" + end # display game information # show menu end diff --git a/model.rb b/model.rb index fb2bb0e..8c31b98 100644 --- a/model.rb +++ b/model.rb @@ -8,7 +8,7 @@ def initialize end def winner? - row_winner? || col_winner? || diag_winner? + row_winner? || col_winner? || diag_winner? || @move_list.count >= 9 end def register(move) From 9a9f2c85142d4ed1d1629cafbca62f2770e04bc0 Mon Sep 17 00:00:00 2001 From: Joe Reich Date: Sat, 19 Dec 2015 00:48:31 -0500 Subject: [PATCH 5/7] menu, bells, whistles --- controller.rb | 58 +++++++++++++++++++++++++++++++++++++++++++-------- model.rb | 33 +++++++++++++---------------- view.rb | 8 +++++++ 3 files changed, 71 insertions(+), 28 deletions(-) diff --git a/controller.rb b/controller.rb index a95c94c..0ebbddb 100644 --- a/controller.rb +++ b/controller.rb @@ -3,25 +3,65 @@ class Controller def execute - # show menu + loop do + run_menu + input = gets.chomp.upcase + puts "" + sleep 1 + case input + when "Q" + puts "Quitting gracefully..." + puts "" + sleep 2 + %x( ^c ) + when "S" + run_game + when "R" + display_move_list + else + puts "You aren't very good at this, are you?" + end + sleep 1 + end + end + + def run_menu + Menu.new.list_options + 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 if @game.winner? == "X" || @game.winner? == "O" puts "It's over! #{@game.winner?}'s win" else puts "It's over! It's a tie!" end - # display game information - # show menu - end - - def show_menu - # display some stuff - # get input to start game - # should this be in the view? end def new_move diff --git a/model.rb b/model.rb index 8c31b98..679f502 100644 --- a/model.rb +++ b/model.rb @@ -7,10 +7,6 @@ def initialize @grid = [[nil, nil, nil],[nil, nil, nil],[nil, nil, nil]] end - def winner? - row_winner? || col_winner? || diag_winner? || @move_list.count >= 9 - end - def register(move) @move_list << move x = move.loc[:x] @@ -18,22 +14,21 @@ def register(move) @grid[x][y] = move.symbol end - def row_winner? - (@grid[0][0] == @grid[0][1] && @grid[0][1] == @grid[0][2] && @grid[0][2]) || - (@grid[1][0] == @grid[1][1] && @grid[1][1] == @grid[1][2] && @grid[1][2]) || - (@grid[2][0] == @grid[2][1] && @grid[2][1] == @grid[2][2] && @grid[2][2]) - end - - def col_winner? - (@grid[0][0] == @grid[1][0] && @grid[1][0] == @grid[2][0] && @grid[2][0]) || - (@grid[0][1] == @grid[1][1] && @grid[1][1] == @grid[2][1] && @grid[2][1]) || - (@grid[0][2] == @grid[1][2] && @grid[1][2] == @grid[2][2] && @grid[2][2]) + def winner? + results = false + + for i in 0..2 + # check row + results ||= (@grid[i][0] == @grid[i][1] && @grid[i][1] == @grid[i][2] && @grid[i][2]) + # check column + results ||= (@grid[0][i] == @grid[1][i] && @grid[1][i] == @grid[2][i] && @grid[2][i]) + end + + # check diagonals + results ||= (@grid[0][0] == @grid[1][1] && @grid[1][1] == @grid[2][2] && @grid[2][2]) + results ||= (@grid[0][2] == @grid[1][1] && @grid[1][1] == @grid[2][0] && @grid[2][0]) end - def diag_winner? - (@grid[0][0] == @grid[1][1] && @grid[1][1] == @grid[2][2] && @grid[2][2]) || - (@grid[2][0] == @grid[1][1] && @grid[1][1] == @grid[0][2] && @grid[0][2]) - end end class Move @@ -45,7 +40,7 @@ def initialize(location, game) @id = @@count @loc = location @game = game - @symbol = @id.even? ? "X" : "O" + @symbol = @id.even? ? "O" : "X" end end diff --git a/view.rb b/view.rb index ad60188..82b7fdb 100644 --- a/view.rb +++ b/view.rb @@ -1,4 +1,12 @@ 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 From 9409342f78d4191741b91bf8cbdc96c916429490 Mon Sep 17 00:00:00 2001 From: Joe Reich Date: Sat, 19 Dec 2015 01:04:33 -0500 Subject: [PATCH 6/7] additional touches --- controller.rb | 23 +++++++++++++---------- model.rb | 22 +++++++++------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/controller.rb b/controller.rb index 0ebbddb..704a3c1 100644 --- a/controller.rb +++ b/controller.rb @@ -9,15 +9,12 @@ def execute puts "" sleep 1 case input - when "Q" - puts "Quitting gracefully..." - puts "" - sleep 2 - %x( ^c ) 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 @@ -29,6 +26,13 @@ def run_menu Menu.new.list_options end + def quit_gracefully + puts "Quitting gracefully..." + puts "" + sleep 2 + %x( ^c ) + end + def display_move_list if @game puts "\tX\t|\tO\t" @@ -57,10 +61,11 @@ def run_game new_move end sleep 1 + print "It's over. " if @game.winner? == "X" || @game.winner? == "O" - puts "It's over! #{@game.winner?}'s win" + puts "#{@game.winner?}'s win." else - puts "It's over! It's a tie!" + puts "It's a tie. How dull..." end end @@ -99,9 +104,7 @@ def valid?(input) end end - end -c = Controller.new -c.execute +Controller.new.execute diff --git a/model.rb b/model.rb index 679f502..446271c 100644 --- a/model.rb +++ b/model.rb @@ -1,32 +1,29 @@ class Game attr_accessor :move_list, :grid - def initialize @move_list = [] @grid = [[nil, nil, nil],[nil, nil, nil],[nil, nil, nil]] end def register(move) - @move_list << move x = move.loc[:x] y = move.loc[:y] @grid[x][y] = move.symbol + + @move_list << move end def winner? - results = false - + result = false + # check rows, columns for winner for i in 0..2 - # check row - results ||= (@grid[i][0] == @grid[i][1] && @grid[i][1] == @grid[i][2] && @grid[i][2]) - # check column - results ||= (@grid[0][i] == @grid[1][i] && @grid[1][i] == @grid[2][i] && @grid[2][i]) + 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 - results ||= (@grid[0][0] == @grid[1][1] && @grid[1][1] == @grid[2][2] && @grid[2][2]) - results ||= (@grid[0][2] == @grid[1][1] && @grid[1][1] == @grid[2][0] && @grid[2][0]) + # 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]) end end @@ -42,5 +39,4 @@ def initialize(location, game) @game = game @symbol = @id.even? ? "O" : "X" end - end From a0a4fc116a2a5d28c9e1600e391ef380364b0474 Mon Sep 17 00:00:00 2001 From: Joe Reich Date: Sat, 19 Dec 2015 01:30:57 -0500 Subject: [PATCH 7/7] more minor tweaks --- controller.rb | 137 +++++++++++++++++++++++++------------------------- model.rb | 11 ++-- 2 files changed, 75 insertions(+), 73 deletions(-) diff --git a/controller.rb b/controller.rb index 704a3c1..4eb138b 100644 --- a/controller.rb +++ b/controller.rb @@ -6,7 +6,7 @@ def execute loop do run_menu input = gets.chomp.upcase - puts "" + print "\n" sleep 1 case input when "S" @@ -22,87 +22,86 @@ def execute end end - def run_menu - Menu.new.list_options - end + private + def run_menu + Menu.new.list_options + end - def quit_gracefully - puts "Quitting gracefully..." - puts "" - sleep 2 - %x( ^c ) - 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}" + 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 - print "\n" + else + puts "No last game to review." 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..." + 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 - end - def new_move - input = get_input - while !valid?(input) do + 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 - move = Move.new(input, @game) - @game.register(move) - @board.add_to_pixel_array(move) - @board.draw - end - # move this to model too? - 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 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 - # move this to the model? - 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 + 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 end diff --git a/model.rb b/model.rb index 446271c..ba1ce73 100644 --- a/model.rb +++ b/model.rb @@ -1,5 +1,5 @@ class Game - attr_accessor :move_list, :grid + attr_reader :move_list, :grid def initialize @move_list = [] @@ -24,19 +24,22 @@ def winner? # 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, :game + attr_reader :symbol, :loc @@count = 0 - def initialize(location, game) + def initialize(location) @@count += 1 @id = @@count @loc = location - @game = game @symbol = @id.even? ? "O" : "X" end end