Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dikla Rikovitch Scrabble Octo #18

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions lib/player.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
require_relative './scoring'
require 'pry'

module Scrabble
class Player
<<<<<<< HEAD

attr_reader :name, :total_score,
=======
attr_reader :name, :total_score, :tiles
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388

def initialize(name)
@name = name
@player_array = []
@total_score = 0
<<<<<<< HEAD
=======
@tiles = []
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
end

def plays
return @player_array
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you named the array @plays, you could make this method an attr_reader.


def play(word)
if @total_score > 100
return false
end
@player_array << word
score = Scrabble::Scoring.score(word)
@total_score += score.to_i
return score
end

def won?
if @total_score > 100
return true
else

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since > will always return true or false, this could be shortened to:

def won?
  return total_score > 100
end

return false
end
end

def highest_scoring_word
return Scrabble::Scoring.highest_score_from(@player_array)
end

def highest_word_score
Scrabble::Scoring.score(highest_scoring_word)
end

def draw_tiles(tile_bag)
until @tiles.length == 7
@tiles << tile_bag.draw_tiles(1)
end
end


end
end
#binding.pry
82 changes: 82 additions & 0 deletions lib/scoring.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,91 @@

module Scrabble
class Scoring
def self.score(word)
total_score = 0

# if statement to check if the word has bad characters and space
if /[[\W][\s]+?]/.match(word)
return nil
end

# if word only has good character then the below will execute
scrabble_word = word.split(//)
if scrabble_word.length > 7 || scrabble_word.length == 0
return nil
elsif scrabble_word.length == 7
total_score += 50
end

scrabble_word.each do |letter|
case letter.downcase
when "a", "e", "i", "o", "u", "l", "n", "r", "s", "t"
total_score += 1
when "d", "g"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing these as options in a case statement certainly works, but it is a single-use solution. If you ever needed to use letter values somewhere else, you'd have to copy paste. An alternative would be to build a data structure stored in a variable that maps letters to scores, something like this:

LETTERS = {
  "A" => 1
  "B" => 3,
  "C" => 3,
  "D" => 2,
  # ...
}

Then to get the score for a letter, you can say LETTERS[letter].

total_score += 2
when "b", "c", "m", "p"
total_score += 3
when "f", "h", "v", "w", "y"
total_score += 4
when "k"
total_score += 5
when "j", "x"
total_score += 8
when "q", "z"
total_score += 10
end
end
return total_score
end

def self.highest_score_from(array_of_words)
max_score = 0
str = " "
max_length = 8
if array_of_words.length == 0
return nil
end
<<<<<<< HEAD

=======
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
array_of_words.each do |word|
if word.length == 7
if self.score(word) > max_score
max_score = self.score(word)
str = word
end
<<<<<<< HEAD

=======
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
elsif word.length < 7
if self.score(word) > max_score
max_score = self.score(word)
max_length = word.length
str = word
<<<<<<< HEAD

elsif Scrabble::Scoring.score(word) == max_score && word.length < max_length
max_score = Scrabble::Scoring.score(word)

=======
elsif self.score(word) == max_score && word.length < max_length
max_score = self.score(word)
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
max_length = word.length
str = word
end
end
end
return str
end
<<<<<<< HEAD
=======

# array = ["aeiou", "uoiea"]
# puts self.highest_score_from(array)

>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
end
end
41 changes: 41 additions & 0 deletions lib/tilebag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require_relative './scoring'
require 'pry'

module Scrabble
class TileBag

attr_reader :tiles

DEFAULT_TILES = {
"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" => 2, "z" => 1
}


def initialize
@tiles = []
DEFAULT_TILES.each do |letter, count|
count.times {@tiles << letter}
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love this strategy for getting the initial tiles into the tile bag! Keeping them in an array is much simpler than trying to manage them in a hash, for example.

end

def draw_tiles(num)
if num > @tiles.length
raise ArgumentError.new("Only #{num} tiles left.")
end
tiles_collection = []
@tiles = @tiles.shuffle
num.times do
tiles_collection << @tiles.pop
end
return tiles_collection
end

def tiles_remaining
return @tiles.length
end
end
end
138 changes: 138 additions & 0 deletions specs/player_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
require 'minitest/autorun'
require 'minitest/reporters'
require 'minitest/skip_dsl'

require_relative '../lib/player'

# Get that nice colorized output
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new

describe 'Player' do
describe "#initialize" do
it "Takes a name" do
player = Scrabble::Player.new("Erika")

player.must_respond_to :name
player.name.must_equal "Erika"
player.name.must_be_kind_of String
end
end

describe 'plays' do
it 'Returns an array of played words' do
word = "dikla"
user = Scrabble::Player.new(word)
scrabble_word = user.plays
scrabble_word.must_be_kind_of Array
end
end

describe 'play' do
it 'Adds the input word to the plays Array' do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the player has already won? Is the word recorded? What does it return?

word = "nut"
user = Scrabble::Player.new("bob")
user.play(word)
user.plays.must_include "nut"
# Scrabble::Player.play(words).must_include "nut"
end
it 'Returns false if player has already won' do
# Arrange
user = Scrabble::Player.new("Fiona")
5.times do
user.play('zzzzzzz')
end
user.won?.must_equal true

# Act
result = user.play('test')

# Assert
result.must_equal false
end
it 'Returns the score of the word' do
# Arrange
user = Scrabble::Player.new("Fiona")
# Act
result = user.play("cat")
# Assert
result.must_equal 5
end
<<<<<<< HEAD

it 'Returns the sum of scores of played words' do
=======
it "Returns the sum of scores of played words" do
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
# Arrange
user = Scrabble::Player.new("Sam")
result = 0
words_arr = ["dog", "cat"]
words_arr.each do |word|
result += user.play(word)
end
# Act
result += user.play("dog")
# Assert
result.must_equal 15
end
end

describe 'won?' do
it 'Returns true if the player has over 100 points' do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be interested in investigating a little closer around 100 points, to more clearly define the "edge" of the behavior. In particular, what happens when the player has:

  • 99 points
  • 100 points
  • 101 points

user = Scrabble::Player.new("Delta")
5.times do
user.play('zzzzzzz')
end

user.won?.must_equal true
end
it 'Returns false if the player less over 100 points' do
user = Scrabble::Player.new("Tide")
3.times do
user.play("dog")
end
user.won?.must_equal false
end
end

describe 'highest_scoring_word' do
it 'Returns the highest scoring played word' do
user = Scrabble::Player.new("Amy")
# words_arr = ["dog", "cat", "zebra"]
user.play("dog")
user.play("zebra")
result = user.highest_scoring_word
result.must_equal "zebra"

end
end

describe 'highest_word_score' do
it 'Returns the highest scoring word score' do
<<<<<<< HEAD

user = Scrabble::Player.new("Kate")
=======
user = Scrabble::Player.new("Amy")
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
user.play("dog")
user.play("zebra")
result = user.highest_word_score
result.must_equal 16
end
end
<<<<<<< HEAD
end
=======

describe 'draw_tiles(tile_bag)' do
it 'fills tiles array until it has 7 letters from the given tile bag' do
user = Scrabble::Player.new("Amy")
tile_bag = Scrabble::TileBag.new
user.draw_tiles(tile_bag)
user.tiles.length.must_equal 7
end
end
end
>>>>>>> 63e10b980789cec14cd9c17435143fee723b3388
6 changes: 6 additions & 0 deletions specs/scoring_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,27 @@

describe 'highest_score_from' do
it 'returns nil if no words were passed' do
Scrabble::Scoring.highest_score_from([]).must_be_nil
end

it 'returns the only word in a length-1 array' do
Scrabble::Scoring.highest_score_from(["apple"]).must_equal "apple"
end

it 'returns the highest word if there are two words' do
Scrabble::Scoring.highest_score_from(["apple", "pear"]).must_equal "apple"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like we discussed in class, it would probably be wise to check multiple orderings of these words, that is, both ['apple', 'pear'] and ['pear', 'apple']. You'd be surprised how often this sort of thing turns up a bug.

end

it 'if tied, prefer a word with 7 letters' do
Scrabble::Scoring.highest_score_from(["daeiou", "aeiouae"]).must_equal "aeiouae"
end

it 'if tied and no word has 7 letters, prefers the word with fewer letters' do
Scrabble::Scoring.highest_score_from(["abcd", "qa"]).must_equal "qa"
end

it 'returns the first word of a tie with same letter count' do
Scrabble::Scoring.highest_score_from(["abcd", "dcba"]).must_equal "abcd"
end
end
end
Loading