diff --git a/lib/player.rb b/lib/player.rb new file mode 100644 index 00000000..b531d210 --- /dev/null +++ b/lib/player.rb @@ -0,0 +1,81 @@ +require 'awesome_print' +MAX_NUM_OF_TILES_ALLOWED = 7 + +module Scrabble + class Player + attr_reader :name, :players_plaque + attr_writer :players_plaque + + def initialize(name) + @name = name + @array_of_words = [] + @players_plaque = [] + end + + # Returns array of players tiles. + def tiles + return @players_plaque + end + + # Draws tiles from a TileBag to fill player's plaque. + def draw_tiles(tile_bag) + if @players_plaque.length < MAX_NUM_OF_TILES_ALLOWED + add_tiles = MAX_NUM_OF_TILES_ALLOWED - @players_plaque.length + @players_plaque.concat(tile_bag.draw_tiles(add_tiles)) + end + end + + # Returns an array of the words played by the user. + def plays + return @array_of_words + end + + # Adds the input word to the plays array + def play(word) + player_status = false + total_score = 0 + @array_of_words.each do |word_in_arr| + total_score += Scrabble::Scoring.score(word_in_arr) + end + + if total_score < 100 + word_score = Scrabble::Scoring.score(word) + player_status = word_score + @array_of_words << word + end + + return player_status + end + + # Returns the sum of scores of played words + def total_score + sum = 0 + @array_of_words.each do |a_word| + sum+= Scrabble::Scoring.score(a_word) + end + return sum + end + + # If the player has over 100 points, returns true, otherwise returns false + def won? + player_case = false + if total_score >= 100 + player_case = true + end + return player_case + end + + # Returns the highest scoring played word + def highest_scoring_word + highest_scoring_word = Scrabble::Scoring.highest_score_from(@array_of_words) + + return highest_scoring_word + end + + # Returns the highest_scoring_word score + def highest_word_score + return highest_scoring_value = Scrabble::Scoring.score(highest_scoring_word) + end + + end +end diff --git a/lib/scoring.rb b/lib/scoring.rb index fb3a3f2d..b14ea792 100644 --- a/lib/scoring.rb +++ b/lib/scoring.rb @@ -1,9 +1,63 @@ module Scrabble class Scoring + + # Returns total score of a given word. def self.score(word) + total = 0 + array_of_characters = word.split('') + if word.match(/^[a-zA-Z]{1,7}$/) == nil + total = nil + else + array_of_characters.each do |letter| + scrabble_value = letter.upcase + case scrabble_value + when "A", "E", "I", "O", "U", "L", "N", "R", "S", "T" + scrabble_value = 1 + when "D", "G" + scrabble_value = 2 + when "B", "C", "M", "P" + scrabble_value = 3 + when "F", "H", "V", "W", "Y" + scrabble_value = 4 + when "K" + scrabble_value = 5 + when "J","X" + scrabble_value = 8 + when "Q", "Z" + scrabble_value = 10 + end + total = scrabble_value + total + end + end + if array_of_characters.length == 7 + total = total + 50 + end + return total end + # Returns highest score from an array of words. def self.highest_score_from(array_of_words) + max = 0 + if array_of_words.size == 0 + highest_score = nil + elsif array_of_words.size == 1 + highest_score = array_of_words[0] + end + array_of_words.each do |word| + if Scrabble::Scoring.score(word) > max + max = Scrabble::Scoring.score(word) + highest_score = word + elsif Scrabble::Scoring.score(word) == max && word.length == 7 + max = Scrabble::Scoring.score(word) + highest_score = word + elsif Scrabble::Scoring.score(word) == max && highest_score.length !=7 + if highest_score.length > word.length + highest_score = word + end + end + end + + return highest_score end end end diff --git a/lib/tilebag.rb b/lib/tilebag.rb new file mode 100644 index 00000000..978e248b --- /dev/null +++ b/lib/tilebag.rb @@ -0,0 +1,65 @@ +require 'awesome_print' + +module Scrabble + class TileBag + attr_reader :tile_bag + + def initialize + @tile_bag = + { A: ['A']*9, + B: ['B']*2, + C: ['C']*2, + D: ['D']*4, + E: ['E']*12, + F: ['F']*2, + G: ['G']*3, + H: ['H']*2, + I: ['I']*9, + J: ['J']*1, + K: ['K']*1, + L: ['L']*4, + M: ['M']*2, + N: ['N']*6, + O: ['O']*8, + P: ['P']*2, + Q: ['Q']*1, + R: ['R']*6, + S: ['S']*4, + T: ['T']*6, + U: ['U']*4, + V: ['V']*2, + W: ['W']*2, + X: ['X']*1, + Y: ['Y']*2, + Z: ['Z']*1 } + end + + # Returns a collection of random tiles, removes the tiles from the default set or returns an empty array and displays a message to the user. + def draw_tiles(num) + random_tiles = [] + if num <= tiles_remaining && num > 1 + num.times do + count = 0 + random_number = rand(0...tiles_remaining) + @tile_bag.map{|letter_type,letter| + letter.each do |single_letter| + if count == random_number + random_tiles << single_letter + letter.pop + end + count+=1 + end} + end + else + puts "There are not enough tiles" + end + return random_tiles + end + + # Returns the number of tiles remaining in the bag + def tiles_remaining + tiles_remaining = @tile_bag.sum{|letter_type,character| character.length} + return tiles_remaining + end + end + end diff --git a/specs/player_spec.rb b/specs/player_spec.rb new file mode 100644 index 00000000..afc7a45f --- /dev/null +++ b/specs/player_spec.rb @@ -0,0 +1,128 @@ +require 'minitest/autorun' +require 'minitest/pride' +require 'minitest/reporters' +require 'minitest/skip_dsl' + +require_relative '../lib/player' +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + + +describe 'Player' do + + describe 'name' do + it 'returns the value of the @name instance variable' do + player_name = Scrabble::Player.new ("Ada") + player_name.name.must_equal "Ada" + end + end + + describe 'tiles' do + it 'is a collection of letters that the player can play (max 7) and starts at 0' do + player = Scrabble::Player.new ("Ada") + player.tiles.must_be_instance_of Array + player.tiles.length.must_equal 0 + end + + end + + describe 'draw_tiles' do + it 'Fills a partially populated plaque' do + player_name = Scrabble::Player.new("Ada") + tile_bag = Scrabble::TileBag.new + player_name.players_plaque = ['C','D','E'] + player_name.draw_tiles(tile_bag) + player_name.tiles.length.must_equal 7 + end + + it 'Will not fill in a fully populated plaque' do + player_name = Scrabble::Player.new("Ada") + tile_bag = Scrabble::TileBag.new + testing_arr = ['A','B','C','D','E','F','G'] + player_name.players_plaque = testing_arr + player_name.draw_tiles(tile_bag) + player_name.players_plaque.must_equal(testing_arr) + end + + end + + describe 'plays' do + it 'returns an Array' do + player_name = Scrabble::Player.new ("Ada") + player_name.plays.must_be_instance_of Array + end + + end + + describe 'play' do + it 'adds the word into the array of words' do + player_name = Scrabble::Player.new ("Ada") + player_name.play("pop") + player_name.plays.must_include "pop" + end + + it 'Returns false if player has already won' do + player_name = Scrabble::Player.new ("Ada") + player_name.play("ZZZZZZZ") + must_be_false = player_name.play("POP") + must_be_false.must_equal false + end + + it 'Returns score of word if < 100 ' do + player_name = Scrabble::Player.new ("Ada") + must_return_word = player_name.play("lawl") + must_return_word.must_equal 7 + end + + end + + describe 'total_score' do + it 'Returns a total score to the user' do + player_name = Scrabble::Player.new("Ada") + player_name.play('hi') + player_name.play('bye') + player_name.play('cry') + player_name.play('why') + player_name.total_score.must_equal 33 + end + end + + describe 'won?' do + it 'Returns true if player has won' do + player_name = Scrabble::Player.new ("Ada") + player_name.play("ZZZZZZZ") + player_name.won?.must_equal true + end + + it 'Returns false if player has not won' do + player_name = Scrabble::Player.new ("Ada") + player_name.play("pop") + player_name.play("lawl") + player_name.won?.must_equal false + end + + end + + describe 'highest_scoring_word' do + it 'Returns highest scoring word in an array of words for a single player' do + player_name = Scrabble::Player.new("Ada") + player_name.play('hi') + player_name.play('bye') + player_name.play('why') + player_name.play('cry') + + player_name.highest_scoring_word.must_equal 'why' + end + end + + describe 'highest_word_score' do + it "Returns the score of the highest scoring word" do + player_name = Scrabble::Player.new("Ada") + player_name.play('hi') + player_name.play('bye') + player_name.play('ZZZZZZZ') + player_name.play('cry') + + player_name.highest_word_score.must_equal 120 + end + end +end diff --git a/specs/scoring_spec.rb b/specs/scoring_spec.rb index ab498929..d3cc7012 100644 --- a/specs/scoring_spec.rb +++ b/specs/scoring_spec.rb @@ -1,10 +1,10 @@ require 'minitest/autorun' +require 'minitest/pride' require 'minitest/reporters' require 'minitest/skip_dsl' require_relative '../lib/scoring' -# Get that nice colorized output Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new describe 'Scoring' do @@ -42,21 +42,39 @@ describe 'highest_score_from' do it 'returns nil if no words were passed' do + empt_array = [] + empt_array_of_words = Scrabble::Scoring.highest_score_from(empt_array) + empt_array_of_words.must_be_nil end it 'returns the only word in a length-1 array' do + single_arr = ['word'] + solo_arr_of_words = Scrabble::Scoring.highest_score_from(single_arr) + solo_arr_of_words.must_equal 'word' end it 'returns the highest word if there are two words' do + random_arr = ['zzebra','medium'] + highest_of_words = Scrabble::Scoring.highest_score_from(random_arr) + highest_of_words.must_equal 'zzebra' end it 'if tied, prefer a word with 7 letters' do + equivalent_words = ['zzebra','zebrakk'] + tied_words = Scrabble::Scoring.highest_score_from(equivalent_words) + tied_words.must_equal 'zebrakk' end it 'if tied and no word has 7 letters, prefers the word with fewer letters' do + equivalent_words = ['zebra','kebrak'] + tied_values = Scrabble::Scoring.highest_score_from(equivalent_words) + tied_values.must_equal 'zebra' end it 'returns the first word of a tie with same letter count' do + tied_words = ['zebra','qebra'] + tied_values = Scrabble::Scoring.highest_score_from(tied_words) + tied_values.must_equal 'zebra' end end end diff --git a/specs/tilebag_spec.rb b/specs/tilebag_spec.rb new file mode 100644 index 00000000..45685377 --- /dev/null +++ b/specs/tilebag_spec.rb @@ -0,0 +1,56 @@ +require 'minitest/autorun' +require 'minitest/pride' +require 'minitest/reporters' +require 'minitest/skip_dsl' +require_relative '../lib/tilebag' + +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new + +describe 'TileBag' do + describe 'initialize' do + it 'can be instantiated' do + tile_bag_test = Scrabble::TileBag.new + tile_bag_test.tile_bag.must_be_instance_of Hash + end + end + + describe 'draw_tiles' do + it 'can return a random array of characters of a specified size' do + random_arr = Scrabble::TileBag.new + array_of_char = random_arr.draw_tiles(4) + array_of_char.must_be_instance_of Array + array_of_char.length.must_equal 4 + end + + + it 'returns an empty array of tiles when there is not enough tiles ' do + tile_bag_test = Scrabble::TileBag.new + random_tiles = tile_bag_test.draw_tiles(100) + random_tiles.must_be_instance_of Array + random_tiles.length.must_equal 0 + end + + it 'returns an empty array of tiles when given a number less than 1' do + tile_bag_test = Scrabble::TileBag.new + random_tiles = tile_bag_test.draw_tiles(0) + random_tiles.must_be_instance_of Array + random_tiles.length.must_equal 0 + end + + + it 'deletes the tiles from the tile bag' do + tile_bag_test = Scrabble::TileBag.new + random_tiles = tile_bag_test.draw_tiles(4) + tile_bag_test.tiles_remaining.must_equal 94 + end + + end + + describe 'tiles_remaining' do + it "returns the number of tiles remaining in a new tile bag " do + tile_bag_test = Scrabble::TileBag.new + tile_bag_test.tiles_remaining.must_equal 98 + end + + end +end