From 4be5912f1ab7b882878ff464d0e48b67b3323a75 Mon Sep 17 00:00:00 2001 From: Mike Kenworthy Date: Fri, 16 Jan 2015 21:22:19 -0500 Subject: [PATCH 1/5] Partially there --- tictactoe/controller.rb | 55 ++++++++++++++ tictactoe/exceptions.rb | 6 ++ tictactoe/globals.rb | 4 ++ tictactoe/model.rb | 0 tictactoe/states.rb | 67 +++++++++++++++++ tictactoe/view.rb | 156 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 288 insertions(+) create mode 100644 tictactoe/controller.rb create mode 100644 tictactoe/exceptions.rb create mode 100644 tictactoe/globals.rb create mode 100644 tictactoe/model.rb create mode 100644 tictactoe/states.rb create mode 100644 tictactoe/view.rb diff --git a/tictactoe/controller.rb b/tictactoe/controller.rb new file mode 100644 index 0000000..8a094e8 --- /dev/null +++ b/tictactoe/controller.rb @@ -0,0 +1,55 @@ +require_relative 'globals' + + + +class GameController + include GameView + + def run! + # Print::display("Mikes page!" , ["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"], "~Kenworthy", 80) + @currState = InitState.new + + until @currState.is_a? EndState do + Print::initialize("Hello world!", "~Kenworthy inc", 80) + Print::display(@currState.getBody) + + @currState = @currState.send(Print::getInput(@currState.getQuestion)) + + end + + end + +=begin + def run! + todoList = List.new + + Print::run_spinner + Print::title_screen + + #Make todoList methods like RESTful endpoints (new/edit/update/delete) + #Think Backbone Model & View + + loop do + Print::menu + case Print::fetch_user_input + when "V" + Print::print_list(todoList.todos) + when "A" + todoList.add_todo(Print::serialize_todo) + when "C" + todoList.complete_todo(Print::completed_id.to_i) + when "D" + todoList.delete_todo(Print::deleted_id.to_i) + when "Q" + puts "We're done" + exit + else + Print::error_message + end + end + end +=end + +end + +GameController.new.run! diff --git a/tictactoe/exceptions.rb b/tictactoe/exceptions.rb new file mode 100644 index 0000000..248f53a --- /dev/null +++ b/tictactoe/exceptions.rb @@ -0,0 +1,6 @@ +class TooMuchContent < Exception +end +class NotInitialized < Exception +end +class NotImplemented < Exception +end \ No newline at end of file diff --git a/tictactoe/globals.rb b/tictactoe/globals.rb new file mode 100644 index 0000000..182278d --- /dev/null +++ b/tictactoe/globals.rb @@ -0,0 +1,4 @@ +require_relative 'view' +require_relative 'model' +require_relative 'states' +require_relative 'exceptions' \ No newline at end of file diff --git a/tictactoe/model.rb b/tictactoe/model.rb new file mode 100644 index 0000000..e69de29 diff --git a/tictactoe/states.rb b/tictactoe/states.rb new file mode 100644 index 0000000..11dafcd --- /dev/null +++ b/tictactoe/states.rb @@ -0,0 +1,67 @@ +require_relative "globals" + +class GameState + attr_writer :oldQuestion + [:getBody, :send, :getQuestion].each do |i| + define_method(i) do |*args| + raise NotImplemented, "Please implement this function" + end + end + def invalidInput + state = self.class.new + state.oldQuestion = state.getQuestion + def state.getQuestion + ["Invalid input!"] + @oldQuestion + end + state + end + def initialize + @oldQuestion = [] + end +end + +class InitState < GameState + def getBody + #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] + ["Welcome to Tic-Tac-Toe!", + 'Type "newgame" to start a new two player game!', + 'Type "quit" to return to bash'] + end + def send(input) + case input.downcase + when "newgame" + SetP1State.new + when "quit" + EndState.new + else + invalidInput + end + end + def getQuestion + ["Please press enter to begin!"] + end +end + +class SetP1State < GameState + def getBody + ["Player 1 is currently: #{}"] + end + def send(input) + case input.downcase + when "newgame" + setP1State.new + when "quit" + EndState.new + else + invalidInput + end + end + def getQuestion + ["Please enter a name for player 1"] + end +end + + +class EndState < GameState + +end \ No newline at end of file diff --git a/tictactoe/view.rb b/tictactoe/view.rb new file mode 100644 index 0000000..83b3791 --- /dev/null +++ b/tictactoe/view.rb @@ -0,0 +1,156 @@ +require_relative 'globals' + +module GameView + + module Print + + class << self + + @@initilized = false + + def initialize(header, footer, screen_size, + header_alignment=:LEFT, body_alignment=:CENTER, footer_alignment=:RIGHT) + @@initilized = true + @header = header + @footer = footer + @header_alignment = header_alignment + @body_alignment = body_alignment + @footer_alignment = footer_alignment + @screen_size = screen_size + @screen_size -= 1 if (@screen_size % 2 != 0) + end + + def getInput(question) + question.each{ |line| print_line(line, :LEFT) } + print ">> " + gets.chomp + end + + def display(body) + system "clear" or system "cls" + raise NotInitialized, "Please run the initialization before attempting display" unless @@initilized + checkContent(@header, body, @footer) + print_bar() + print_line(@header, @header_alignment) + print_bar() + print_blank() + body.each{ |line| print_line(line, @body_alignment) } + print_blank() + print_bar() + end + + def print_line(line, align) + padding = (@screen_size - 6 - line.length) + if align == :LEFT + puts "** " + line + (" " * padding) + " **" + elsif align == :RIGHT + puts "** " + (" " * (@screen_size - 6 - line.length)) + line + " **" + elsif align == :CENTER + right_pad = padding + 1 if padding / 2 != 0 + puts "** " + (" " * (padding / 2)) + line + (" " * (right_pad / 2)) + " **" + end + end + + def print_blank() + puts "** " + (" " * (@screen_size - 6)) + " **" + end + + def print_bar() + line = "" + nStars = ((@screen_size - 4) / 2) + nStars.times{ line += "*" } + line = line + " || " + nStars.times{ line += "*" } + puts line + end + + def checkContent(header, body, footer) + content = [header] + body + [footer] + content.max do |a, b| + b.length <=> a.length + end + raise TooMuchContent "Reduce line size..." unless content.first.length < (@screen_size - 6) + # max(content.first.length,10) + end +=begin + + def run_spinner + print "Loading (please wait) " + 5.times { print "."; sleep 1; } + print "\n" + end + + def error_message + puts "That's not a command key. Try again!" + end + + def title_screen +title = < " + gets.chomp + end +=end + + end + end +end From 3d54001837922f7e762a080eca069485a0a27dba Mon Sep 17 00:00:00 2001 From: Mike Kenworthy <MKenworthy@covermymeds.com> Date: Mon, 19 Jan 2015 11:54:03 -0500 Subject: [PATCH 2/5] More progress --- tictactoe/controller.rb | 32 +------ tictactoe/model.rb | 89 +++++++++++++++++ tictactoe/states.rb | 207 ++++++++++++++++++++++++++++++---------- tictactoe/view.rb | 83 +--------------- 4 files changed, 252 insertions(+), 159 deletions(-) diff --git a/tictactoe/controller.rb b/tictactoe/controller.rb index 8a094e8..92da83a 100644 --- a/tictactoe/controller.rb +++ b/tictactoe/controller.rb @@ -4,6 +4,7 @@ class GameController include GameView + include GameState def run! # Print::display("Mikes page!" , ["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"], "~Kenworthy", 80) @@ -19,37 +20,6 @@ def run! end -=begin - def run! - todoList = List.new - - Print::run_spinner - Print::title_screen - - #Make todoList methods like RESTful endpoints (new/edit/update/delete) - #Think Backbone Model & View - - loop do - Print::menu - case Print::fetch_user_input - when "V" - Print::print_list(todoList.todos) - when "A" - todoList.add_todo(Print::serialize_todo) - when "C" - todoList.complete_todo(Print::completed_id.to_i) - when "D" - todoList.delete_todo(Print::deleted_id.to_i) - when "Q" - puts "We're done" - exit - else - Print::error_message - end - end - end -=end - end GameController.new.run! diff --git a/tictactoe/model.rb b/tictactoe/model.rb index e69de29..2185380 100644 --- a/tictactoe/model.rb +++ b/tictactoe/model.rb @@ -0,0 +1,89 @@ +require_relative 'globals' + +module GameModel + + module Model + + class << self + + @initilized = false + + def initialize() + @p1 = nil + @p2 = nil + @board = Board.new() + @initilized = true + end + + def setp1(name) + + end + + def setp2(name) + + end + + def getp1() + + end + + def getp2() + + end + + def getBoardAsArray + string = [" \e[4m [0] [1] [2] \e[0m "] + @board.size.times do |r| + row = "[#{r}] |" + @board.size.times do |c| + row += "\e[4m " + (@board.data[r][c] ? @board.data[r][c].to_s : " ") + " \e[0m|" + end + row += " " + string.push(row) + end + string + end + + end + end + + class Player + + end + + class P1 < Player + + end + + class P2 < Player + + end + + class Piece + attr_reader :owner + def initialize(owner) + @owner = owner + end + end + + class X < Piece + def to_str + "X" + end + end + + class O < Piece + def to_str + "O" + end + end + + class Board + attr_accessor :data, :size + def initialize(size=3) + @size = size + @data = Array.new(size) { Array.new(size) { |i| i*2 } } + end + + end +end diff --git a/tictactoe/states.rb b/tictactoe/states.rb index 11dafcd..14f0b05 100644 --- a/tictactoe/states.rb +++ b/tictactoe/states.rb @@ -1,67 +1,178 @@ require_relative "globals" -class GameState - attr_writer :oldQuestion - [:getBody, :send, :getQuestion].each do |i| - define_method(i) do |*args| - raise NotImplemented, "Please implement this function" +module GameState + + class State + include GameModel + attr_writer :oldQuestion, :errorMessage + [:getBody, :send, :getQuestion].each do |i| + define_method(i) do |*args| + raise NotImplemented, "Please implement this function" + end end - end - def invalidInput - state = self.class.new - state.oldQuestion = state.getQuestion - def state.getQuestion - ["Invalid input!"] + @oldQuestion + def invalidInput(error=nil) + state = self.class.new + error ? state.errorMessage = [error] : state.errorMessage = ["Invalid input!"] + state.oldQuestion = state.getQuestion + def state.getQuestion + @errorMessage + @oldQuestion + end + state + end + def initialize + @oldQuestion = [] end - state end - def initialize - @oldQuestion = [] + + class InitState < State + def getBody + #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] + ["Welcome to Tic-Tac-Toe!", + 'Type "newgame" to start a new two player game!', + 'Type "quit" to return to bash'] + end + def send(input) + case input.downcase + when "newgame" + Model::initialize + SetP1State.new + when "quit" + EndState.new + else + invalidInput + end + end + def getQuestion + ["Please press enter to begin!"] + end end -end - -class InitState < GameState - def getBody - #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] - ["Welcome to Tic-Tac-Toe!", - 'Type "newgame" to start a new two player game!', - 'Type "quit" to return to bash'] + + class SetP1State < State + def getBody + ["Player 1 is currently: #{}", + "Commands:", ":quit => Quit the application", ":back => Go to the previous menu"] + end + def send(input) + case input.downcase + when ":back" + setP1State.new + when ":quit" + EndState.new + else + #set the name of the player and move to P2 selection state + + #If game is playing, return to game + + SetP2State.new + end + end + def getQuestion + ["Please enter a name for player 1"] + end end - def send(input) - case input.downcase - when "newgame" - SetP1State.new - when "quit" - EndState.new - else - invalidInput + + class SetP2State < State + def getBody + ["Player 2 is currently: #{}", + "Commands:", ":quit => Quit the application", ":back => Go to the previous menu"] + end + def send(input) + case input.downcase + when ":back" + setP1State.new + when ":quit" + EndState.new + else + #set the name of the player and move to the next state + + + #If game is playing, return to game + + P1Turn.new + end + end + def getQuestion + ["Please enter a name for player 2"] end end - def getQuestion - ["Please press enter to begin!"] + + class Turn < State + end -end -class SetP1State < GameState - def getBody - ["Player 1 is currently: #{}"] + class P1Turn < Turn + def getBody + #Get board as text + Model::getBoardAsArray + end + def send(input) + case input.downcase + when ":back" + setP1State.new + when ":quit" + EndState.new + else + #Check to ensure space is empty + + #Check for endgame conditions + + #Move to proper state + + P2Turn.new + end + end + def getQuestion + [""] + end end - def send(input) - case input.downcase - when "newgame" - setP1State.new - when "quit" - EndState.new - else - invalidInput + + class P2Turn < Turn + def getBody + [""] + end + def send(input) + case input.downcase + when ":back" + setP1State.new + when ":quit" + EndState.new + else + #Check to ensure space is empty + + #Check for endgame conditions + + #Move to proper state + + Complete.new + end + end + def getQuestion + [""] end end - def getQuestion - ["Please enter a name for player 1"] + + class Complete < State + def getBody + #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] + ["Congratulations player #{}"] + end + def send(input) + case input.downcase + when "newgame" + SetP1State.new + when "quit" + EndState.new + else + invalidInput + end + end + def getQuestion + [""] + end end -end + class EndState < State -class EndState < GameState + end end \ No newline at end of file diff --git a/tictactoe/view.rb b/tictactoe/view.rb index 83b3791..7d33104 100644 --- a/tictactoe/view.rb +++ b/tictactoe/view.rb @@ -33,14 +33,15 @@ def display(body) print_bar() print_line(@header, @header_alignment) print_bar() - print_blank() + # print_blank() body.each{ |line| print_line(line, @body_alignment) } print_blank() print_bar() end def print_line(line, align) - padding = (@screen_size - 6 - line.length) + # p line.scan(/\e/).count + padding = (@screen_size - 6 + (line.scan(/\e/).count * 4) - line.length) if align == :LEFT puts "** " + line + (" " * padding) + " **" elsif align == :RIGHT @@ -72,84 +73,6 @@ def checkContent(header, body, footer) raise TooMuchContent "Reduce line size..." unless content.first.length < (@screen_size - 6) # max(content.first.length,10) end -=begin - - def run_spinner - print "Loading (please wait) " - 5.times { print "."; sleep 1; } - print "\n" - end - - def error_message - puts "That's not a command key. Try again!" - end - - def title_screen -title = <<TITLE - - ********** || ********** - * TODO MAGIC * - ********** || ********** - -TITLE - puts title - end - - def menu -menu = <<EOS - - ***** Welcome ***** - - (V)iew your todos - - (A)dd a todo - - (C)omplete a todo - - (D)elete a todo - - (Q)uit program - ***** ***** - -EOS - puts menu - end - - #does print_list know too much about the underlying object??? - - def print_list(todos) - todos.each do |todo| - if todo.completed? - puts "[X] #{todo.id} || #{todo.title} - #{todo.description}" - else - puts "[_] #{todo.id} || #{todo.title} - #{todo.description}" - end - end - end - - def serialize_todo - {}.tap do |obj| - ["\nEnter the title:", "\nEnter the description:"].each do |t| - if obj.empty? - obj[:title] = fetch_user_input(t) - else - obj[:description] = fetch_user_input(t) - end - end - end - end - - def deleted_id - gimme_id = "\nEnter the id of todo item you want to DELETE:" - fetch_user_input(gimme_id) - end - - def completed_id - gimme_id = "\nEnter the id of todo item you want to mark as COMPLETED:" - fetch_user_input(gimme_id) - end - - def fetch_user_input(question=nil) - puts question if question - print "> " - gets.chomp - end -=end end end From beff87800ed91c24c08ada8385d153cc4b87de52 Mon Sep 17 00:00:00 2001 From: Mike Kenworthy <MKenworthy@covermymeds.com> Date: Tue, 20 Jan 2015 12:12:48 -0500 Subject: [PATCH 3/5] Working version of TicTacToe --- tictactoe/controller.rb | 64 +++++++++++++- tictactoe/model.rb | 60 +++++++------ tictactoe/states.rb | 184 ++++++++++++++++++++++++---------------- 3 files changed, 205 insertions(+), 103 deletions(-) diff --git a/tictactoe/controller.rb b/tictactoe/controller.rb index 92da83a..1e98600 100644 --- a/tictactoe/controller.rb +++ b/tictactoe/controller.rb @@ -5,21 +5,81 @@ class GameController include GameView include GameState + include GameModel def run! # Print::display("Mikes page!" , ["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"], "~Kenworthy", 80) @currState = InitState.new + Print::initialize("Hello world!", "~Kenworthy inc", 80) until @currState.is_a? EndState do - Print::initialize("Hello world!", "~Kenworthy inc", 80) + Print::display(@currState.getBody) - @currState = @currState.send(Print::getInput(@currState.getQuestion)) + nextState = @currState.send(Print::getInput(@currState.getQuestion)) + (nextState = Complete.new if (checkFTW(Model::board) || Model::board.full?)) if @currState.is_a? Turn + + @currState = nextState end end + def checkFTW(board) + puts "Heres the board!" + p board.data + + winBoard = Array.new(3) { Array.new(board.size) { nil } } + (board.size-1).times do |i| + winBoard[0][i] = board.data[i][0] + winBoard[1][i] = board.data[0][i] + end + winBoard[2][0] = board.data[0][0] + winBoard[2][1] = board.data[0][board.size-1] + + # puts "Heres the unchecked winners board!" + # p winBoard + + + board.size.times do |r| + board.size.times do |c| + # puts "Row #{r} Col #{c}" + # puts "Winboard value #{winBoard[1][c]} Board value #{board.data[r][c]}" + winBoard[1][c] = false unless(board.data[r][c] && winBoard[1][c] && board.data[r][c].class == winBoard[1][c].class) + winBoard[0][r] = false unless(board.data[r][c] && winBoard[0][r] && board.data[r][c].class == winBoard[0][r].class) + + if c == r + winBoard[2][0] = false unless(board.data[r][c] && winBoard[2][0] && board.data[r][c].class == winBoard[2][0].class) + end + if (c + r) == (board.size-1) + winBoard[2][1] = false unless(board.data[r][c] && winBoard[2][1] && board.data[r][c].class == winBoard[2][1].class) + end + end + end + + # puts "here are the winners!" + puts "There was a winner?" + p winBoard.flatten.any? + p winBoard + rcd = -1 + num = -1 + if winBoard.flatten.any? + winBoard.size.times do |c| + winBoard[c].size.times do |r| + if winBoard[r][c] + Model::winning_position = [r,c] + Model::winner = winBoard[r][c].owner + return true + end + end + end + end + false + + end + end + + GameController.new.run! diff --git a/tictactoe/model.rb b/tictactoe/model.rb index 2185380..d2a1257 100644 --- a/tictactoe/model.rb +++ b/tictactoe/model.rb @@ -5,30 +5,23 @@ module GameModel module Model class << self - + attr_reader :board + attr_accessor :winner, :winning_position @initilized = false def initialize() - @p1 = nil - @p2 = nil + @players = [nil, nil] @board = Board.new() @initilized = true + @winner = nil end - def setp1(name) - - end - - def setp2(name) - - end - - def getp1() - + def set_player(name, p) + @players[p] = Player.new(name, p == 0 ? X.new(self) : O.new(self)) end - - def getp2() - + + def get_player(i) + @players[i] ? @players[i] : "not set" end def getBoardAsArray @@ -41,22 +34,31 @@ def getBoardAsArray row += " " string.push(row) end + puts string string end - end - end - - class Player - - end + def place_piece(piece, r, c) + @board.data[r][c] = piece + end - class P1 < Player + def get_space(r,c) + @board.data[r][c] + end + end end - class P2 < Player + class Player + attr_reader :piece + def initialize(name, piece) + @name = name + @piece = piece + end + def to_s + @name + "(" + @piece.to_s + ")" + end end class Piece @@ -67,13 +69,13 @@ def initialize(owner) end class X < Piece - def to_str + def to_s "X" end end class O < Piece - def to_str + def to_s "O" end end @@ -82,8 +84,12 @@ class Board attr_accessor :data, :size def initialize(size=3) @size = size - @data = Array.new(size) { Array.new(size) { |i| i*2 } } + # @data = [[X.new(P1.new("Mike")),nil,nil],[X.new(P1.new("Mike")),X.new(P1.new("Mike")),nil],[X.new(P1.new("Mike")),nil,X.new(P1.new("Mike"))]]#Array.new(size) { Array.new(size) { nil }}#X.new(P2.new("Mike")) } } + @data = Array.new(size) { Array.new(size) { nil } } end + def full? + @data.flatten.reduce(true) { |m, i| m && i } + end end end diff --git a/tictactoe/states.rb b/tictactoe/states.rb index 14f0b05..0fb3c2f 100644 --- a/tictactoe/states.rb +++ b/tictactoe/states.rb @@ -1,4 +1,11 @@ require_relative "globals" +require "pry" + +class String + def is_integer? + self.to_i.to_s == self + end +end module GameState @@ -22,25 +29,34 @@ def state.getQuestion def initialize @oldQuestion = [] end + + def commands(input) + case input.downcase + when ":newgame" || ":n" + Model::initialize + SetP1State.new + when ":quit" || ":q" + EndState.new + when ":back" || ":b" + Back.new + else + false + end + end end class InitState < State def getBody #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] ["Welcome to Tic-Tac-Toe!", - 'Type "newgame" to start a new two player game!', - 'Type "quit" to return to bash'] + 'Available commands', + ':newgame => Start a new game', + ':quit => Quit game'] end def send(input) - case input.downcase - when "newgame" - Model::initialize - SetP1State.new - when "quit" - EndState.new - else - invalidInput - end + returned_value = commands(input) + return returned_value if returned_value + invalidInput end def getQuestion ["Please press enter to begin!"] @@ -49,122 +65,138 @@ def getQuestion class SetP1State < State def getBody - ["Player 1 is currently: #{}", + ["Player 1 is currently: #{Model::get_player(0)}", "Commands:", ":quit => Quit the application", ":back => Go to the previous menu"] end def send(input) - case input.downcase - when ":back" - setP1State.new - when ":quit" - EndState.new - else - #set the name of the player and move to P2 selection state - - #If game is playing, return to game - - SetP2State.new - end + returned_value = commands(input) + return returned_value if returned_value + #set the name of the player and move to P2 selection state + Model::set_player(input, 0) + SetP2State.new + #If game is playing, return to game end def getQuestion - ["Please enter a name for player 1"] + ["Please enter a name for player 1 and press enter!"] end end class SetP2State < State def getBody - ["Player 2 is currently: #{}", + ["Player 2 is currently: #{Model::get_player(1)}", "Commands:", ":quit => Quit the application", ":back => Go to the previous menu"] end def send(input) - case input.downcase - when ":back" - setP1State.new - when ":quit" - EndState.new - else - #set the name of the player and move to the next state - + returned_value = commands(input) + return returned_value if returned_value + #set the name of the player and move to the next state + Model::set_player(input, 1) - #If game is playing, return to game + #If game is playing, return to game - P1Turn.new - end + P1Turn.new end def getQuestion ["Please enter a name for player 2"] end end + class Turn < State + def send(input, player) + returned_value = commands(input) + return returned_value if returned_value + + coords = input.split("") + + return invalidInput("Please enter two numbers only") if coords.size != 2 + + if coords[0].is_integer? && coords[1].is_integer? + coords.map!(&:to_i) + else + return invalidInput("Please only use numbers") + end + p coords + p Model::get_space(coords[0],coords[1]) + # binding.pry + if Model::get_space(coords[0],coords[1]) + # binding.pry + return invalidInput("There's already a piece on #{Model::get_space(coords[0],coords[1])}") + else + Model::place_piece(player.piece.class.new(player), coords[0].to_i, coords[1].to_i) + false + end + + end end class P1Turn < Turn def getBody #Get board as text - Model::getBoardAsArray + ["Player 1 turn!"] + Model::getBoardAsArray end - def send(input) - case input.downcase - when ":back" - setP1State.new - when ":quit" - EndState.new - else - #Check to ensure space is empty - - #Check for endgame conditions - #Move to proper state + def send(input) + player = Model::get_player(0) - P2Turn.new - end + returned_value = super(input, player) + return returned_value if returned_value + + P2Turn.new end + def getQuestion - [""] + ["Place your #{Model::get_player(0).piece}! Ex: 00 => upper left"] end end class P2Turn < Turn def getBody - [""] + ["Player 2 turn!"] + Model::getBoardAsArray end - def send(input) - case input.downcase - when ":back" - setP1State.new - when ":quit" - EndState.new - else - #Check to ensure space is empty - #Check for endgame conditions + def send(input) + player = Model::get_player(1) - #Move to proper state + returned_value = super(input, player) + return returned_value if returned_value - Complete.new - end + P1Turn.new end + def getQuestion - [""] + ["Place your #{Model::get_player(1).piece}! Ex: 00 => upper left"] end end class Complete < State def getBody #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] - ["Congratulations player #{}"] + winning_position = Model::winning_position + p winning_position + rcd = "" + + if Model::winner + case winning_position[0] + when 0 + rcd = "Row" + when 1 + rcd = "Col" + when 2 + rcd = "diag" + end + ret = ["Congratulations player #{Model::winner}", "You won on #{rcd}#{winning_position[1]}",""] + else + ret = ["No winner!",""] + end + + ret += Model::getBoardAsArray end def send(input) - case input.downcase - when "newgame" - SetP1State.new - when "quit" - EndState.new - else + returned_value = commands(input) + return returned_value if returned_value invalidInput - end end def getQuestion [""] @@ -175,4 +207,8 @@ class EndState < State end + class Back < State + + end + end \ No newline at end of file From 8ab159eacae5119e0d41f60f589ab146b9433e6c Mon Sep 17 00:00:00 2001 From: Mike Kenworthy <MKenworthy@covermymeds.com> Date: Tue, 20 Jan 2015 12:18:12 -0500 Subject: [PATCH 4/5] Enabled any key for movement past the init screen --- tictactoe/states.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tictactoe/states.rb b/tictactoe/states.rb index 0fb3c2f..09c92eb 100644 --- a/tictactoe/states.rb +++ b/tictactoe/states.rb @@ -56,6 +56,12 @@ def getBody def send(input) returned_value = commands(input) return returned_value if returned_value + + if input == "" + Model::initialize + return SetP1State.new + end + invalidInput end def getQuestion From faae4d13f7e43f562e18c23bae45af19677a7f6b Mon Sep 17 00:00:00 2001 From: Mike Kenworthy <MKenworthy@covermymeds.com> Date: Tue, 20 Jan 2015 12:56:42 -0500 Subject: [PATCH 5/5] Fixed some style stuff --- tictactoe/controller.rb | 42 +++++------ tictactoe/exceptions.rb | 2 +- tictactoe/globals.rb | 2 +- tictactoe/model.rb | 25 +++---- tictactoe/states.rb | 151 ++++++++++++++++++++-------------------- tictactoe/view.rb | 48 ++++++------- 6 files changed, 128 insertions(+), 142 deletions(-) diff --git a/tictactoe/controller.rb b/tictactoe/controller.rb index 1e98600..95d0ee3 100644 --- a/tictactoe/controller.rb +++ b/tictactoe/controller.rb @@ -1,7 +1,5 @@ require_relative 'globals' - - class GameController include GameView include GameState @@ -10,55 +8,53 @@ class GameController def run! # Print::display("Mikes page!" , ["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"], "~Kenworthy", 80) @currState = InitState.new - Print::initialize("Hello world!", "~Kenworthy inc", 80) + Print.initialize('Hello world!', '~Kenworthy inc', 80) + + until @currState.is_a? EndState - until @currState.is_a? EndState do - - Print::display(@currState.getBody) + Print.display(@currState.getBody) - nextState = @currState.send(Print::getInput(@currState.getQuestion)) + nextState = @currState.send(Print.getInput(@currState.getQuestion)) - (nextState = Complete.new if (checkFTW(Model::board) || Model::board.full?)) if @currState.is_a? Turn + (nextState = Complete.new if checkFTW(Model.board) || Model.board.full?) if @currState.is_a? Turn @currState = nextState end - end def checkFTW(board) - puts "Heres the board!" + puts 'Heres the board!' p board.data winBoard = Array.new(3) { Array.new(board.size) { nil } } - (board.size-1).times do |i| + (board.size - 1).times do |i| winBoard[0][i] = board.data[i][0] winBoard[1][i] = board.data[0][i] end winBoard[2][0] = board.data[0][0] - winBoard[2][1] = board.data[0][board.size-1] + winBoard[2][1] = board.data[0][board.size - 1] # puts "Heres the unchecked winners board!" # p winBoard - board.size.times do |r| board.size.times do |c| # puts "Row #{r} Col #{c}" # puts "Winboard value #{winBoard[1][c]} Board value #{board.data[r][c]}" - winBoard[1][c] = false unless(board.data[r][c] && winBoard[1][c] && board.data[r][c].class == winBoard[1][c].class) - winBoard[0][r] = false unless(board.data[r][c] && winBoard[0][r] && board.data[r][c].class == winBoard[0][r].class) + winBoard[1][c] = false unless board.data[r][c] && winBoard[1][c] && board.data[r][c].class == winBoard[1][c].class + winBoard[0][r] = false unless board.data[r][c] && winBoard[0][r] && board.data[r][c].class == winBoard[0][r].class if c == r - winBoard[2][0] = false unless(board.data[r][c] && winBoard[2][0] && board.data[r][c].class == winBoard[2][0].class) + winBoard[2][0] = false unless board.data[r][c] && winBoard[2][0] && board.data[r][c].class == winBoard[2][0].class end - if (c + r) == (board.size-1) - winBoard[2][1] = false unless(board.data[r][c] && winBoard[2][1] && board.data[r][c].class == winBoard[2][1].class) + if (c + r) == (board.size - 1) + winBoard[2][1] = false unless board.data[r][c] && winBoard[2][1] && board.data[r][c].class == winBoard[2][1].class end end end # puts "here are the winners!" - puts "There was a winner?" + puts 'There was a winner?' p winBoard.flatten.any? p winBoard rcd = -1 @@ -67,19 +63,15 @@ def checkFTW(board) winBoard.size.times do |c| winBoard[c].size.times do |r| if winBoard[r][c] - Model::winning_position = [r,c] - Model::winner = winBoard[r][c].owner + Model.winning_position = [r, c] + Model.winner = winBoard[r][c].owner return true end end end end false - end - end - - GameController.new.run! diff --git a/tictactoe/exceptions.rb b/tictactoe/exceptions.rb index 248f53a..f5d64b7 100644 --- a/tictactoe/exceptions.rb +++ b/tictactoe/exceptions.rb @@ -3,4 +3,4 @@ class TooMuchContent < Exception class NotInitialized < Exception end class NotImplemented < Exception -end \ No newline at end of file +end diff --git a/tictactoe/globals.rb b/tictactoe/globals.rb index 182278d..af21489 100644 --- a/tictactoe/globals.rb +++ b/tictactoe/globals.rb @@ -1,4 +1,4 @@ require_relative 'view' require_relative 'model' require_relative 'states' -require_relative 'exceptions' \ No newline at end of file +require_relative 'exceptions' diff --git a/tictactoe/model.rb b/tictactoe/model.rb index d2a1257..665ed1a 100644 --- a/tictactoe/model.rb +++ b/tictactoe/model.rb @@ -1,17 +1,15 @@ require_relative 'globals' module GameModel - module Model - class << self attr_reader :board attr_accessor :winner, :winning_position @initilized = false - def initialize() + def initialize @players = [nil, nil] - @board = Board.new() + @board = Board.new @initilized = true @winner = nil end @@ -19,9 +17,9 @@ def initialize() def set_player(name, p) @players[p] = Player.new(name, p == 0 ? X.new(self) : O.new(self)) end - + def get_player(i) - @players[i] ? @players[i] : "not set" + @players[i] ? @players[i] : 'not set' end def getBoardAsArray @@ -29,9 +27,9 @@ def getBoardAsArray @board.size.times do |r| row = "[#{r}] |" @board.size.times do |c| - row += "\e[4m " + (@board.data[r][c] ? @board.data[r][c].to_s : " ") + " \e[0m|" + row += "\e[4m " + (@board.data[r][c] ? @board.data[r][c].to_s : ' ') + " \e[0m|" end - row += " " + row += ' ' string.push(row) end puts string @@ -42,10 +40,9 @@ def place_piece(piece, r, c) @board.data[r][c] = piece end - def get_space(r,c) + def get_space(r, c) @board.data[r][c] end - end end @@ -57,7 +54,7 @@ def initialize(name, piece) end def to_s - @name + "(" + @piece.to_s + ")" + @name + '(' + @piece.to_s + ')' end end @@ -70,19 +67,19 @@ def initialize(owner) class X < Piece def to_s - "X" + 'X' end end class O < Piece def to_s - "O" + 'O' end end class Board attr_accessor :data, :size - def initialize(size=3) + def initialize(size = 3) @size = size # @data = [[X.new(P1.new("Mike")),nil,nil],[X.new(P1.new("Mike")),X.new(P1.new("Mike")),nil],[X.new(P1.new("Mike")),nil,X.new(P1.new("Mike"))]]#Array.new(size) { Array.new(size) { nil }}#X.new(P2.new("Mike")) } } @data = Array.new(size) { Array.new(size) { nil } } diff --git a/tictactoe/states.rb b/tictactoe/states.rb index 09c92eb..e67f506 100644 --- a/tictactoe/states.rb +++ b/tictactoe/states.rb @@ -1,43 +1,42 @@ -require_relative "globals" -require "pry" +require_relative 'globals' class String def is_integer? - self.to_i.to_s == self + to_i.to_s == self end end module GameState - class State include GameModel attr_writer :oldQuestion, :errorMessage [:getBody, :send, :getQuestion].each do |i| - define_method(i) do |*args| - raise NotImplemented, "Please implement this function" + define_method(i) do |*_args| + fail NotImplemented, 'Please implement this function' end end - def invalidInput(error=nil) + def invalidInput(error = nil) state = self.class.new - error ? state.errorMessage = [error] : state.errorMessage = ["Invalid input!"] + error ? state.errorMessage = [error] : state.errorMessage = ['Invalid input!'] state.oldQuestion = state.getQuestion def state.getQuestion - @errorMessage + @oldQuestion + @errorMessage + @oldQuestion end state end + def initialize @oldQuestion = [] end def commands(input) case input.downcase - when ":newgame" || ":n" - Model::initialize + when ':newgame' || ':n' + Model.initialize SetP1State.new - when ":quit" || ":q" + when ':quit' || ':q' EndState.new - when ":back" || ":b" + when ':back' || ':b' Back.new else false @@ -47,123 +46,126 @@ def commands(input) class InitState < State def getBody - #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] - ["Welcome to Tic-Tac-Toe!", - 'Available commands', - ':newgame => Start a new game', - ':quit => Quit game'] + # ["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] + ['Welcome to Tic-Tac-Toe!', + 'Available commands', + ':newgame => Start a new game', + ':quit => Quit game'] end + def send(input) - returned_value = commands(input) + returned_value = commands(input) return returned_value if returned_value - if input == "" - Model::initialize + if input == '' + Model.initialize return SetP1State.new end invalidInput end + def getQuestion - ["Please press enter to begin!"] + ['Please press enter to begin!'] end end class SetP1State < State def getBody - ["Player 1 is currently: #{Model::get_player(0)}", - "Commands:", ":quit => Quit the application", ":back => Go to the previous menu"] + ["Player 1 is currently: #{Model.get_player(0)}", + 'Commands:', ':quit => Quit the application', ':back => Go to the previous menu'] end + def send(input) - returned_value = commands(input) + returned_value = commands(input) return returned_value if returned_value - #set the name of the player and move to P2 selection state - Model::set_player(input, 0) + # set the name of the player and move to P2 selection state + Model.set_player(input, 0) SetP2State.new - #If game is playing, return to game + # If game is playing, return to game end + def getQuestion - ["Please enter a name for player 1 and press enter!"] + ['Please enter a name for player 1 and press enter!'] end end class SetP2State < State def getBody - ["Player 2 is currently: #{Model::get_player(1)}", - "Commands:", ":quit => Quit the application", ":back => Go to the previous menu"] + ["Player 2 is currently: #{Model.get_player(1)}", + 'Commands:', ':quit => Quit the application', ':back => Go to the previous menu'] end + def send(input) - returned_value = commands(input) + returned_value = commands(input) return returned_value if returned_value - #set the name of the player and move to the next state - Model::set_player(input, 1) + # set the name of the player and move to the next state + Model.set_player(input, 1) - #If game is playing, return to game + # If game is playing, return to game P1Turn.new end + def getQuestion - ["Please enter a name for player 2"] + ['Please enter a name for player 2'] end end - class Turn < State - def send(input, player) - returned_value = commands(input) + returned_value = commands(input) return returned_value if returned_value - coords = input.split("") + coords = input.split('') - return invalidInput("Please enter two numbers only") if coords.size != 2 + return invalidInput('Please enter two numbers only') if coords.size != 2 if coords[0].is_integer? && coords[1].is_integer? coords.map!(&:to_i) else - return invalidInput("Please only use numbers") + return invalidInput('Please only use numbers') end - p coords - p Model::get_space(coords[0],coords[1]) + p coords + p Model.get_space(coords[0], coords[1]) # binding.pry - if Model::get_space(coords[0],coords[1]) + if Model.get_space(coords[0], coords[1]) # binding.pry - return invalidInput("There's already a piece on #{Model::get_space(coords[0],coords[1])}") + return invalidInput("There's already a piece on #{Model.get_space(coords[0], coords[1])}") else - Model::place_piece(player.piece.class.new(player), coords[0].to_i, coords[1].to_i) + Model.place_piece(player.piece.class.new(player), coords[0].to_i, coords[1].to_i) false end - end end class P1Turn < Turn def getBody - #Get board as text - ["Player 1 turn!"] + Model::getBoardAsArray + # Get board as text + ['Player 1 turn!'] + Model.getBoardAsArray end def send(input) - player = Model::get_player(0) + player = Model.get_player(0) returned_value = super(input, player) return returned_value if returned_value - + P2Turn.new end def getQuestion - ["Place your #{Model::get_player(0).piece}! Ex: 00 => upper left"] + ["Place your #{Model.get_player(0).piece}! Ex: 00 => upper left"] end end class P2Turn < Turn def getBody - ["Player 2 turn!"] + Model::getBoardAsArray + ['Player 2 turn!'] + Model.getBoardAsArray end def send(input) - player = Model::get_player(1) + player = Model.get_player(1) returned_value = super(input, player) return returned_value if returned_value @@ -172,49 +174,48 @@ def send(input) end def getQuestion - ["Place your #{Model::get_player(1).piece}! Ex: 00 => upper left"] + ["Place your #{Model.get_player(1).piece}! Ex: 00 => upper left"] end end class Complete < State def getBody - #["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] - winning_position = Model::winning_position + # ["Some stuff is crazy", "and that is why I love it", "be peaceful my friend"] + winning_position = Model.winning_position p winning_position - rcd = "" + rcd = '' - if Model::winner + if Model.winner case winning_position[0] when 0 - rcd = "Row" + rcd = 'Row' when 1 - rcd = "Col" + rcd = 'Col' when 2 - rcd = "diag" + rcd = 'diag' end - ret = ["Congratulations player #{Model::winner}", "You won on #{rcd}#{winning_position[1]}",""] - else - ret = ["No winner!",""] + ret = ["Congratulations player #{Model.winner}", "You won on #{rcd}#{winning_position[1]}", ''] + else + ret = ['No winner!', ''] end - - ret += Model::getBoardAsArray + + ret += Model.getBoardAsArray end + def send(input) - returned_value = commands(input) + returned_value = commands(input) return returned_value if returned_value - invalidInput + invalidInput end + def getQuestion - [""] + [''] end end class EndState < State - end class Back < State - end - -end \ No newline at end of file +end diff --git a/tictactoe/view.rb b/tictactoe/view.rb index 7d33104..7c4956c 100644 --- a/tictactoe/view.rb +++ b/tictactoe/view.rb @@ -1,15 +1,12 @@ require_relative 'globals' module GameView - module Print - class << self - @@initilized = false - def initialize(header, footer, screen_size, - header_alignment=:LEFT, body_alignment=:CENTER, footer_alignment=:RIGHT) + def initialize(header, footer, screen_size, + header_alignment = :LEFT, body_alignment = :CENTER, footer_alignment = :RIGHT) @@initilized = true @header = header @footer = footer @@ -21,47 +18,47 @@ def initialize(header, footer, screen_size, end def getInput(question) - question.each{ |line| print_line(line, :LEFT) } - print ">> " + question.each { |line| print_line(line, :LEFT) } + print '>> ' gets.chomp end def display(body) - system "clear" or system "cls" - raise NotInitialized, "Please run the initialization before attempting display" unless @@initilized + system('clear') || system('cls') + fail NotInitialized, 'Please run the initialization before attempting display' unless @@initilized checkContent(@header, body, @footer) - print_bar() + print_bar print_line(@header, @header_alignment) - print_bar() + print_bar # print_blank() - body.each{ |line| print_line(line, @body_alignment) } - print_blank() - print_bar() + body.each { |line| print_line(line, @body_alignment) } + print_blank + print_bar end def print_line(line, align) # p line.scan(/\e/).count padding = (@screen_size - 6 + (line.scan(/\e/).count * 4) - line.length) if align == :LEFT - puts "** " + line + (" " * padding) + " **" + puts '** ' + line + (' ' * padding) + ' **' elsif align == :RIGHT - puts "** " + (" " * (@screen_size - 6 - line.length)) + line + " **" + puts '** ' + (' ' * (@screen_size - 6 - line.length)) + line + ' **' elsif align == :CENTER right_pad = padding + 1 if padding / 2 != 0 - puts "** " + (" " * (padding / 2)) + line + (" " * (right_pad / 2)) + " **" + puts '** ' + (' ' * (padding / 2)) + line + (' ' * (right_pad / 2)) + ' **' end end - def print_blank() - puts "** " + (" " * (@screen_size - 6)) + " **" + def print_blank + puts '** ' + (' ' * (@screen_size - 6)) + ' **' end - def print_bar() - line = "" + def print_bar + line = '' nStars = ((@screen_size - 4) / 2) - nStars.times{ line += "*" } - line = line + " || " - nStars.times{ line += "*" } + nStars.times { line += '*' } + line = line + ' || ' + nStars.times { line += '*' } puts line end @@ -70,10 +67,9 @@ def checkContent(header, body, footer) content.max do |a, b| b.length <=> a.length end - raise TooMuchContent "Reduce line size..." unless content.first.length < (@screen_size - 6) + fail TooMuchContent 'Reduce line size...' unless content.first.length < (@screen_size - 6) # max(content.first.length,10) end - end end end