-
Notifications
You must be signed in to change notification settings - Fork 26
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
Scrabble - Jackie & Leti (Ampers) #8
base: master
Are you sure you want to change the base?
Changes from 47 commits
27059d0
ad5a0be
24022ff
71bdb93
1b70781
f89b00a
e112d21
78c157b
68481b7
27b4827
5d1ddef
f7dab82
5d4ef25
f3b149f
0f2a8d1
fa5f61a
0a34fec
8263c3f
6a082a8
27db390
ecc16a8
bf0bc47
4abaeba
b143409
390cabe
e248d2c
25389fc
e745716
e320ff2
c4c3900
cc8d12e
0c54c22
4eb126f
7280a67
0fe3c6c
64fec21
495dbc0
4e25418
cd4c9f4
3965a05
c21f74d
be94de4
3ab27bf
eac411c
2678435
deeb039
897a2c8
0dfb93e
2405cff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#*********************************************************** | ||
#Class Player in Scrabble Module: | ||
|
||
require_relative 'scoring' | ||
|
||
module Scrabble | ||
class Player | ||
|
||
attr_reader :name, :plays | ||
|
||
def initialize(name) | ||
@name = name | ||
@plays = [] | ||
@tiles= [] | ||
end | ||
|
||
# _________________DRAW TILES METHOD____________________ | ||
# Randomly chooses as many possible words (max 7) that the player can still draw from the tiles bag by calling the draw_tiles method from the TileBag class. | ||
|
||
def draw_tiles(tile_bag) | ||
@tiles = tile_bag.draw_tiles(7 - @tiles.count) | ||
return @tiles | ||
end | ||
|
||
|
||
# _________________PLAY METHOD____________________ | ||
# Accepts a word as an argument and add it to the plays array. | ||
|
||
def play(word) | ||
@plays << word | ||
end | ||
|
||
# _________________TOTAL SCORE METHOD____________________ | ||
# Calculates and returns the toal score of the words in the plays array by calling the score method of the class Scoring. | ||
|
||
def total_score | ||
sum_of_scores = 0 | ||
@plays.each do |word| | ||
score = Scoring.score(word) | ||
|
||
sum_of_scores += score | ||
end | ||
return sum_of_scores | ||
end | ||
|
||
# _________________WON? METHOD____________________ | ||
# Returns true if the toal score is more than 100, otherwise returns false. | ||
|
||
def won? | ||
total_score > 100 ? true : false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good ternary |
||
end | ||
|
||
# ___________HIGHEST SCORING WORD METHOD________________ | ||
# Returns the highest scoring played word. | ||
|
||
def highest_scoring_word | ||
return Scoring.highest_score_from(@plays) | ||
end | ||
|
||
# ______________HIGHEST WORD SCORE METHOD__________________ | ||
# Returns the score of the highest scored word. | ||
|
||
def highest_word_score | ||
return Scoring.score(highest_scoring_word) | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,95 @@ | ||
########################################################### | ||
#Class Scoring in Scrabble Module: | ||
|
||
module Scrabble | ||
class Scoring | ||
|
||
# _________________SCORE METHOD____________________ | ||
# Calculates points scored with the given word: | ||
|
||
def self.score(word) | ||
|
||
# If word contains a character that is not a letter, returns nil: | ||
if word.match?(/\W/) | ||
return nil | ||
end | ||
|
||
# If word is has more than 7 characters, returns nil: | ||
if word.length > 7 | ||
return nil | ||
end | ||
|
||
# Creates a new array with each letter of the word as a diferent element: | ||
letters_array = word.upcase.split("") | ||
|
||
# If array with letters is empty, returns nil: | ||
if letters_array.empty? | ||
return nil | ||
end | ||
|
||
|
||
# Set the points for that word to initialize at zero and calculate the points of each word, adding them to the points variable: | ||
points = 0 | ||
|
||
letters_array.each do |letter| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This works, but is there a more compact way to do this, maybe with a hash? |
||
case letter | ||
when "Q", "Z" | ||
points += 10 | ||
when "D", "G" | ||
points += 2 | ||
when "B", "C", "M", "P" | ||
points += 3 | ||
when "F", "H", "V", "W", "Y" | ||
points += 4 | ||
when "K" | ||
points += 5 | ||
when "J", "X" | ||
points += 8 | ||
else #"A", "E", "I", "O", "U", "L", "N", "R", "S", "T" | ||
points += 1 | ||
end | ||
end | ||
|
||
# If word has 7 letters add 50 more points: | ||
letters_array.length == 7 ? points += 50 : points += 0 | ||
|
||
return points | ||
end | ||
|
||
def self.highest_score_from(array_of_words) | ||
|
||
# ________________HIGHEST SCORE METHOD___________________ | ||
# Returns the word with highest score, from a given array of words: | ||
|
||
def self.highest_score_from(array_of_words = []) | ||
# Evaluate given words to find the one with highest score, according to the game rules. If there is a tie, it will populate a new array with the words in the tie and compare them to find the winner. | ||
|
||
scoring_table = {} | ||
|
||
# Set the scores of each word: | ||
array_of_words.each {|word| scoring_table["#{word}"] = score(word)} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need the interpolation here: array_of_words.each {|word| scoring_table[word] = score(word)} will work |
||
|
||
# Find the words with the maximu score between them: | ||
max = scoring_table.values.max | ||
max_scored_words_hash = Hash[scoring_table.select { |k, v| v == max}] | ||
|
||
# Select only the keys from the has with the highest scored words: | ||
winning_words = max_scored_words_hash.keys | ||
|
||
# Choose and return the winning word according to the rules and solving a tie if any: | ||
if array_of_words == [] | ||
return nil | ||
elsif winning_words.length == 1 | ||
winner = winning_words[0] | ||
return winner | ||
elsif winning_words.max_by(&:length).length == 7 | ||
winner = winning_words.max_by(&:length) | ||
return winner | ||
else | ||
winner = winning_words.min_by {|word| word.length} | ||
return winner | ||
end | ||
end | ||
end | ||
end | ||
|
||
|
||
end #Scoring | ||
end #Scrabble |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#*********************************************************** | ||
# Class TileBag in Scrabble Module: | ||
|
||
module Scrabble | ||
class TileBag | ||
|
||
attr_reader :bag | ||
|
||
def initialize | ||
@bag = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a number of problems with this data structure. Most pressing is that it gives each letter an equal chance of being drawn. This is despite the fact that there are a lot more "E" tiles than "Z". |
||
"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 | ||
} | ||
end | ||
|
||
# _________________DRAW TILES METHOD____________________ | ||
# Accepts a number of tiles that needs to be drawn for the player and creates a loop that will: | ||
# - take a random letter from the bag | ||
# - add this letter to the array of tiles | ||
# - subtract the quantity of that letter available in the tile bag | ||
# - delete the key of this letter from the tile bag if there are none available anymore. | ||
|
||
def draw_tiles(num) | ||
tiles_drawn = [ ] | ||
|
||
num.times do | ||
new_letter = @bag.keys.sample | ||
tiles_drawn << new_letter | ||
@bag[new_letter] -= 1 | ||
@bag.delete_if { |letter, quantity| quantity == 0 } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good that you're keeping the number of tiles from going negative. |
||
end | ||
|
||
return tiles_drawn | ||
end | ||
|
||
# _______________TILES REMAINING METHOD_________________ | ||
# Returns the total quantity of tiles still available in the tile bag. | ||
|
||
def tiles_remaining | ||
return @bag.values.sum | ||
end | ||
|
||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
require 'minitest/autorun' | ||
require 'minitest/reporters' | ||
require 'minitest/skip_dsl' | ||
|
||
require_relative '../lib/player' | ||
require_relative '../lib/tile_bag' | ||
|
||
Minitest::Reporters.use! | ||
Minitest::Reporters::SpecReporter.new | ||
|
||
describe 'Player' do | ||
describe "#initialize" do | ||
it "Takes a Player name" do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.must_be_instance_of Scrabble::Player | ||
|
||
player_1.must_respond_to :name | ||
player_1.name.must_equal "Patrick" | ||
player_1.name.must_be_kind_of String | ||
|
||
end | ||
describe "#plays" do | ||
it "Returns an array of words played:" do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
|
||
player_1.plays.must_be_kind_of Array | ||
|
||
end | ||
end | ||
|
||
describe "#play(word)" do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about:
|
||
it "Adds input word to @plays array." do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.play("orange") | ||
|
||
player_1.plays.must_include "orange" | ||
|
||
end | ||
end | ||
end | ||
|
||
describe '#total_score' do | ||
it " Returns the sum of scores of played words" do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.play("apples") | ||
player_1.play("fuzzy") | ||
|
||
player_1.total_score.must_equal 39 | ||
end | ||
end | ||
|
||
describe '#won?' do | ||
it "Returns true if player has over 100 points" do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.play("xxxxxxx") | ||
player_1.won?.must_equal true | ||
|
||
end | ||
|
||
it "Returns false if player has over 100 points" do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.play("apples") | ||
player_1.play("fuzzy") | ||
player_1.won?.must_equal false | ||
|
||
end | ||
end | ||
|
||
describe '#highest_scoring_word' do | ||
it 'Returns the highest scoring played word' do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.play("cat") | ||
player_1.play("pig") | ||
|
||
player_1.highest_scoring_word.must_equal "pig" | ||
player_1.highest_scoring_word.must_be_kind_of String | ||
|
||
end | ||
|
||
|
||
it 'Returns the first word if there is a tie between hightest scoring words"' do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.play("ba") | ||
player_1.play("dd") | ||
|
||
player_1.highest_scoring_word.must_equal "ba" | ||
|
||
end | ||
|
||
end | ||
|
||
describe '#highest_word_score' do | ||
it 'Returns the score of the highest scoring word' do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
player_1.play("cat") | ||
player_1.play("pig") | ||
|
||
player_1.highest_word_score.must_equal 6 | ||
|
||
end | ||
end | ||
|
||
describe 'draw_tiles(tile_bag)' do | ||
it 'is a collection of letters that the player can play (max 7)' do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
tile_bag = Scrabble::TileBag.new | ||
|
||
players_tiles = player_1.draw_tiles(tile_bag) | ||
|
||
players_tiles.must_be_kind_of Array | ||
all_letters = players_tiles.all? { |word| word.class == String } | ||
all_letters.must_equal true | ||
end | ||
|
||
end | ||
|
||
it 'fills tiles array until it has 7 letters from the given tile bag' do | ||
player_1 = Scrabble::Player.new("Patrick") | ||
tile_bag = Scrabble::TileBag.new | ||
|
||
players_tiles = player_1.draw_tiles(tile_bag) | ||
players_tiles.length.must_equal 7 | ||
|
||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,21 +42,37 @@ | |
|
||
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 | ||
winning_word = Scrabble::Scoring.highest_score_from(["hotdog"]) | ||
winning_word.must_equal "hotdog" | ||
winning_word.must_be_kind_of String | ||
|
||
end | ||
|
||
it 'returns the highest word if there are two words' do | ||
winning_words = Scrabble::Scoring.highest_score_from(["dog", "academy"]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since order can potentially be important in the Something like: winning_words = Scrabble::Scoring.highest_score_from(["academy", "dog"])
winning_words.must_equal "academy" |
||
winning_words.must_equal "academy" | ||
end | ||
|
||
it 'if tied, prefer a word with 7 letters' do | ||
winning_words = Scrabble::Scoring.highest_score_from(["qqqqqj", "aaaaaad"]) | ||
winning_words.must_equal "aaaaaad" | ||
|
||
end | ||
|
||
it 'if tied and no word has 7 letters, prefers the word with fewer letters' do | ||
winning_words = Scrabble::Scoring.highest_score_from(["qq", "kkkk"]) | ||
winning_words.must_equal "qq" | ||
end | ||
|
||
it 'returns the first word of a tie with same letter count' do | ||
winning_words = Scrabble::Scoring.highest_score_from(["dd", "ba"]) | ||
winning_words.must_equal "dd" | ||
|
||
|
||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Read the description again. This method is required to return
false
if they have already won prior to playing the word.