diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..5008ddfc Binary files /dev/null and b/.DS_Store differ diff --git a/.ruby b/.ruby new file mode 100644 index 00000000..fc7e6017 --- /dev/null +++ b/.ruby @@ -0,0 +1 @@ +2.3.0 -version diff --git a/.ruby-gemset b/.ruby-gemset new file mode 100644 index 00000000..f24df478 --- /dev/null +++ b/.ruby-gemset @@ -0,0 +1 @@ +scrabble diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..43932cd6 --- /dev/null +++ b/Rakefile @@ -0,0 +1,9 @@ +require 'rake/testtask' + + Rake::TestTask.new do |t| + t.libs = ["lib"] + t.warning = true + t.test_files = FileList['specs/*_spec.rb'] + end + + task default: :test diff --git a/lib/player.rb b/lib/player.rb new file mode 100644 index 00000000..c95e23c7 --- /dev/null +++ b/lib/player.rb @@ -0,0 +1,66 @@ +# require_relative "../scrabble" + +class Scrabble::Player + WINNING_SCORE = 100 + attr_accessor :played_words + attr_reader :name, :their_tiles + def initialize(name, tilebag) + @name = name + @played_words = [] + @tilebag = tilebag #starts up a tilebag when the player begins a game + @their_tiles = @tilebag.draw_tiles(7) #draws 7 tiles for them + end + + def plays + return @played_words #shows which words they have played + end + + def won? + return true if total_score > WINNING_SCORE + return false + end + + def play(word) + @played_words << word + return false if won? + return Scrabble::Scoring.score(word) + end + + def total_score + total_score = [] + @played_words.each do |word| + total_score << Scrabble::Scoring.score(word) + end + return total_score.reduce(0, :+) + end + + def highest_scoring_word + high_score_word = plays.max_by do |word| + Scrabble::Scoring.score(word) + end + return high_score_word + end + + def highest_word_score + highest_scored_word = plays.max_by do |word| + Scrabble::Scoring.score(word) + end + return Scrabble::Scoring.score(highest_scored_word) + end + + def tiles + return their_tiles + end + # checks to see how many tiles they need and fills them up if needed and if tiles are left in bag + def draw_tiles + num = 7 - @their_tiles.length + # fills tiles array until it has 7 letters from the given tile bag + if num > 0 + new_tiles = @tilebag.draw_tiles(num) + @their_tiles << new_tiles + return @their_tiles.flatten! + end + end + + +end diff --git a/lib/scoring.rb b/lib/scoring.rb new file mode 100644 index 00000000..f7e7cd05 --- /dev/null +++ b/lib/scoring.rb @@ -0,0 +1,69 @@ +# require_relative "../scrabble" + +class Scrabble::Scoring +SEVEN_LETTER_BONUS = 50 +#PLAYED_WORDS = [] +#WORD_SCORE_COLLECTION =[] + + LETTERS = { + %w(A E I O U L N R S T) => 1, + %w(D G) => 2, + %w(B C M P) => 3, + %w(F H V W Y) => 4, + %w(K) => 5, + %w(J X) => 8, + %w(Q Z) => 10 +} + + def self.letter_value(letter) + LETTERS.each do |key, value| + if key.include? letter + return value + end + end + end + + def self.score(word) + word_score = 0 + bonus = SEVEN_LETTER_BONUS + word_score += bonus if word.length == 7 + word_array = word.split("") + word_array.each do |letter| + temp_letter_val = letter_value(letter) + word_score += temp_letter_val + end + return word_score + end + +#return highest score from array_of_tiles +#in case of tie : +# -better to use fewer tiles +# -if top scores is between multiple words and one with 7, one using 7 win_words +# - multiple words with same score and same length, pick first + def self.highest_score_from(word_array) + by_scores = word_array.group_by { |word| self.score(word) } + win_words = by_scores.max[1] + if win_words.length == 1 + return win_words[0] + elsif win_words.any? { |word| word.length == 7 } + seven_letter_words = win_words.select { |word| word.length == 7} + return seven_letter_words.first + else + min_word = win_words.min_by { |word| word.length } + return min_word + end + end + +end + +#we were experimenting with several versions of this method. +#======================================================================= +# def self.score(word) +# value_array = [] +# x = (word).split("") +# x.each do |letter| +# value_array << letter_value(letter) +# end +# total = value_array.inject(:+) +# return word, total +# end diff --git a/lib/tilebag.rb b/lib/tilebag.rb new file mode 100644 index 00000000..54d040de --- /dev/null +++ b/lib/tilebag.rb @@ -0,0 +1,82 @@ +# require_relative '../scrabble' +class Scrabble::Tilebag + attr_accessor :default_tiles + + def initialize + @default_tiles = new_bag + end + + def new_bag + { + 'A' => 9, + "B" => 2, + "C" => 2, + "D" => 4, + "E" => 12, + "F" => 2, + "G" => 3, + "H" => 2, + "I" => 9, + "J" => 1, + "K" => 1, + "L" => 4, + "M" => 2, + "N" => 6, + "O" => 8, + "P" => 2, + "Q" => 1, + "R" => 6, + "S" => 4, + "T" => 6, + "U" => 4, + "V" => 2, + "W" => 2, + "X" => 1, + "Y" => 1, + "Z" => 1 + } + end + + +#returns an array of all actual tiles, to allow user to pick more than one of the same letter tile +#we incorporated this into our draw_tiles method because .sample was not letting that happen + def display_all_tiles + array = [] + @default_tiles.each do |key, value| + array << (key * value).split("") + end + return array.flatten + end + +#check to see if the numbers of tiles player is trying to draw are available, +# then removes them from tile bag and returns new tiles +# ex - if player tries to draw 6 and there are only 4, it gives them those 4 tiles + def draw_tiles(num) + if num <= tiles_remaining + our_tiles = display_all_tiles.sample(num) + tile_removal(our_tiles) + return our_tiles + else + print "Sorry, there are only #{tiles_remaining} left." + our_tiles = display_all_tiles.sample(tiles_remaining) + tile_removal(our_tiles) + return our_tiles + end + end + + #added up number of tiles using INJECT! + def tiles_remaining + @default_tiles.values.inject(0, :+) + end + +#deletes tiles from tile_bag, when there are no tiles left, it remove that key/value pair from bag + def tile_removal(array_of_tiles) + array_of_tiles.each do |letter| + if @default_tiles.keys.include?(letter) + @default_tiles[letter] -= 1 + end + @default_tiles.delete_if {|key, value| value == 0 } + end + end + +end diff --git a/scrabble.rb b/scrabble.rb new file mode 100644 index 00000000..e459a675 --- /dev/null +++ b/scrabble.rb @@ -0,0 +1,9 @@ +module Scrabble + + + +end + +require_relative "./lib/scoring" +require_relative './lib/player' +require_relative './lib/tilebag' diff --git a/specs/player_spec.rb b/specs/player_spec.rb new file mode 100644 index 00000000..3063d5d0 --- /dev/null +++ b/specs/player_spec.rb @@ -0,0 +1,109 @@ +require_relative './spec_helper' +require_relative '../scrabble' +require_relative '../lib/player' + + + +describe Scrabble::Player do + + before do + @our_tile_bag = Scrabble::Tilebag.new + end + + it "this does exist" do + Scrabble::Player.wont_be_nil + end + + + describe "InitializeInstanceVariable" do + it "should create instance of player name" do + Scrabble::Player.new("Tim", @our_tile_bag).must_be_instance_of(Scrabble::Player) + end + end + + describe "ReturnWordArray" do + it "should return an Array of the words played by player" do + Scrabble::Player.new("Tim", @our_tile_bag).plays.must_equal([]) + end + end + + describe "PlayWordsMethodExists" do + it "should input a new word to the plays array" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("RED") + risha.plays.must_equal(["RED"]) + end + end + + describe "PlayWordReturnValue" do + it "should return score of word, if player has not won" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("RED").must_equal(4) + end + end + + describe "PlayWordReturnValue" do + it "should return false if player has won" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("ZZZZZZZZZZZZ").must_equal(false) + end + end + + describe "TotalScore" do + it "should return the total score of the played words array" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("RED") + risha.play("HOTDOG") + risha.total_score.must_equal(15) + end + end + + describe "Won?Methodreturn_True" do + it "should return true if player has over 100 points" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("ZZZZZZZZZZZZ") + risha.won?.must_equal(true) + end + end + + describe "Won?Methodreturn_false" do + it "should return false if player has fewer than 100 points" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("RED") + risha.won?.must_equal(false) + end + end + + describe "HighestScoringWord" do + it "should return the highest scoring word" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("RED") + risha.play("HOTDOG") + risha.highest_scoring_word.must_equal("HOTDOG") + end + end + + describe "HighestWordScore" do + it "should return the highest score" do + risha = Scrabble::Player.new("risha", @our_tile_bag) + risha.play("RED") + risha.play("HOTDOG") + risha.highest_word_score.must_equal(11) + end + end + + describe "PlayerClass-tiles_method" do + it "should return a collection of tiles player can play(max7)" do + puppet = Scrabble::Player.new("puppet", @our_tile_bag) + puppet.tiles.length.must_equal(7) + end + end + + describe "DrawTiles" do + it "should not do anything if bag is full" do + betty = Scrabble::Player.new("betty", @our_tile_bag) + betty.draw_tiles.must_be_nil + end + end + +end diff --git a/specs/scoring_spec.rb b/specs/scoring_spec.rb new file mode 100644 index 00000000..f2d85c75 --- /dev/null +++ b/specs/scoring_spec.rb @@ -0,0 +1,106 @@ +require_relative './spec_helper' +require_relative '../scrabble' +require_relative '../lib/scoring' + +describe Scrabble::Scoring do + it "this does exist" do + Scrabble::Scoring.wont_be_nil + end +end + +# describe Scrabble::Scoring do + # it "is an object we have access to" do + # Scrabble::Scoring.wont_be_nil + # end + + describe "LetterValue#convert" do + TEST_CASES = { + "A" => 1, + "D" => 2, + "M" => 3, + "F" => 4, + "K" => 5, + "J" => 8, + "Q" => 10 + } + TEST_CASES.each do |letter, value| + it "should return #{letter} for #{value}" do + Scrabble::Scoring.letter_value(letter).must_equal(value) + end + end + end + + describe "WordScore" do + it "should return total score for word" do + Scrabble::Scoring.score("HOTDOG").must_equal(11) + end + end + + describe "WordScoreTest" do + TEST_CASE = { + "HOTDOG" => 11, + "JOKER" => 16, + "ZEBRA" => 16, + } + + TEST_CASES.each do |word, value| + it "should return #{word} for #{value}" do + Scrabble::Scoring.score(word).must_equal(value) + end + end + end + + describe "WordscoreBonus" do + it "when 7 letters used, add 50 points to the total score." do + Scrabble::Scoring.score("DEIRDRE").must_equal(59) + end + end + + describe "HighestScore" do + it "should return the highets score in the array." do + Scrabble::Scoring.highest_score_from(["CAT", "ZEBRA"]).must_equal("ZEBRA") + end + end + + describe "HighestScore" do + it "should return the highet score with the fewest tiles" do + Scrabble::Scoring.highest_score_from(["STONE", "PEE", "HI"]).must_equal("HI") + end + end + + describe "HighestScore" do + it "should return the first word if score and tiles are the same value." do + Scrabble::Scoring.highest_score_from(["I", "HOT", "HIT"]).must_equal("HOT") + end + end + + describe "HighestScore" do + it "when mutliple words that are equal in value, return the word with the length 7 tiles" do + Scrabble::Scoring.highest_score_from(["ZZZZZZ", "AEIOUTF", "AEIOUTH"]).must_equal("AEIOUTF") + end + end + + + # describe "WordscoreCollecter" do + # it "stores the scored words into an array." do + # Scrabble::Scoring.score("WHALE").must_equal(["WHALE", 11]) + # end + # end + + # describe "CollectWordArray" do + # it "Should create an array of words passed to it" do + # Scrabble::Scoring.collect_word_array("HOTDOG").must_equal(["HOTDOG"]) + # end + # end + + # describe "CollectScoreArray" do + # it "Should create an array of scores passed to it" do + # Scrabble::Scoring.collect_word_array("HOTDOG").must_equal([11]) + # end + # end + + # describe "CombinedCollection" do + # it "Should create a hash of arrays with words and their scores" do + # Scrabble::Scoring.combined_collection.must_equal(["HOTDOG" => 11]) + # end + # end diff --git a/specs/spec_helper.rb b/specs/spec_helper.rb new file mode 100644 index 00000000..eabef050 --- /dev/null +++ b/specs/spec_helper.rb @@ -0,0 +1,9 @@ +require 'simplecov' +SimpleCov.start +require 'minitest' +require 'minitest/spec' +require 'minitest/autorun' +require 'minitest/reporters' + +# give us some really nice output +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new diff --git a/specs/tilebag_spec.rb b/specs/tilebag_spec.rb new file mode 100644 index 00000000..abdcdebf --- /dev/null +++ b/specs/tilebag_spec.rb @@ -0,0 +1,46 @@ +require_relative './spec_helper' +require_relative '../scrabble' +require_relative '../lib/tilebag' + +describe Scrabble::Tilebag do + it "this does exist" do + Scrabble::Tilebag.wont_be_nil + end +end + +describe "TileBag-Draw_Tiles" do + it "should return (num) number of random tiles and remove from tilebag" do + @my_tiles = Scrabble::Tilebag.new + our_tiles = @my_tiles.draw_tiles(3) + our_tiles.length.must_equal(3) + @my_tiles.default_tiles.values.inject(:+).must_equal(94) + end + + it "should restrict player from removing more then amount of tiles remaining" do + tim = Scrabble::Tilebag.new + tim.draw_tiles(98).length.must_equal(97) + end +end + +describe "TilesRemaining" do + it "should return the number of tiles remaining in the bag" do + @display_tiles = Scrabble::Tilebag.new + @display_tiles.draw_tiles(6) + @display_tiles.tiles_remaining.must_equal(91) + end +end + +describe "Display_All_Tiles" do + tiles = Scrabble::Tilebag.new + it "should display an array of all tiles" do + tiles.display_all_tiles.must_be_instance_of(Array) + end +end + +# describe "DrawTiles" do +# it "should " do +# betty = Scrabble::Player.new +# betty.@their_tiles = 0git +# betty.draw_tiles(7).length.must_equal(7) +# end +# end