diff --git a/bin/bordle b/bin/bordle deleted file mode 100755 index 3aed7c5..0000000 Binary files a/bin/bordle and /dev/null differ diff --git a/src/dictionary.cr b/src/dictionary.cr index 75ffb26..1c7d293 100644 --- a/src/dictionary.cr +++ b/src/dictionary.cr @@ -1,32 +1,33 @@ - -class Bordle +class Bordle class Dictionary - DICTIONARY_FILE = "/usr/share/dict/french" + DICTIONARY_PATH = Path.new("/usr/share/dict/") property length : UInt8 property data : Array(String) + property language : String = "french" def initialize(length : UInt8) @length = length @data = [] of String load_data - end def load_data + dictionary_file = DICTIONARY_PATH / @language # use french dictionary from wfrench package - if ! File.exists? DICTIONARY_FILE - STDERR.puts "ERROR: dictionary file missing! (#{DICTIONARY_FILE})" - STDERR.puts " Please install then wfrench package on your system" + if !File.exists? dictionary_file + STDERR.puts "ERROR: dictionary file missing! (#{dictionary_file})" + STDERR.puts " Please install then w#{@language} package on your system" exit 1 end - lines = File.read_lines(DICTIONARY_FILE) - @data = + lines = File.read_lines(dictionary_file) + @data = lines - .select {|word| word.size == @length } - .map { |word| word.tr( TR_DIACRITICS, TR_ASCII ) } - end + .select { |word| word.size == @length } + .map { |word| word.tr(TR_DIACRITICS, TR_ASCII) } + end + def includes?(word) @data.includes? word end diff --git a/src/game.cr b/src/game.cr index fc6f56c..1581b72 100644 --- a/src/game.cr +++ b/src/game.cr @@ -1,11 +1,10 @@ - require "colorize" require "./types" require "./dictionary" require "./target_word" -class Bordle +class Bordle class Game def initialize @length = 5_u8 @@ -17,10 +16,10 @@ class Bordle printf("#{try}. ") diff.each do |ls| colors = case ls[1] - when Score::NotOk then {:white, :black} + when Score::NotOk then {:white, :black} when Score::WrongPlace then {:white, :yellow} when Score::RightPlace then {:white, :green} - else {:white, :black} + else {:white, :black} end str = ("%s" % ls[0]).colorize.fore(colors[0]).back(colors[1]) printf("%s", str) @@ -37,16 +36,30 @@ class Bordle word = "" if word.nil? word.tr(TR_DIACRITICS, TR_ASCII).downcase + error = [] of String + error << "language" if !@dict.includes? word + error << "length" if word.size != @length break if word.size == @length && @dict.includes? word printf("\x1B[A\x1B[2K") + puts "-- #{word} : invalid #{error.join(" and ")} --" end word end def run - printf " .....\n" + puts "-- BORDLE (#{@target.inspect}) --".colorize.fore(:blue) + puts <<-MARK + 1. You win when you find the secret word. + 2. You have 5 attempts; you lose if you use them all. + 3. The secret word is in #{@dict.language} and 5 characters long. + 4. Language and length mistakes are not counted as attemps. + 5. Diacritics (accents, etc.) are removed. + 6. Use CTRL-C to exit. + MARK + puts "" + puts " ....." try = 0 - while true + while true try += 1 word = input_word(try) printf("\x1B[A\x1B[2K") @@ -57,7 +70,7 @@ class Bordle puts "-- GAGNÉ ! --".colorize.fore(:green) return end - if try >= 5 + if try >= 5 puts "-- PERDU ! --".colorize.fore(:red) return end @@ -65,4 +78,3 @@ class Bordle end end end - diff --git a/src/main.cr b/src/main.cr index 9406659..6cde94e 100644 --- a/src/main.cr +++ b/src/main.cr @@ -1,14 +1,12 @@ - require "option_parser" require "./game" class Bordle class BordleCli - property options : String? - def initialize() + def initialize @options = nil end @@ -17,20 +15,18 @@ class Bordle end # FIXME: add --length LEN option (length of words) - # FIXME: add --lang LANG option (choose dictionnary) + # FIXME: add --language LANG option (choose dictionnary) # FIXME: add --tries TRIES option (how many tries are allowed) - # FIXME: add --with-letters (show used/unused letters) + # FIXME: add --with-letters (show used/unused letters) def self.run(args) app = BordleCli.new options = BordleCli.parse_options(args) app.options = options game = Game.new - game.run() - + game.run end end end Bordle::BordleCli.run(ARGV) - diff --git a/src/target_word.cr b/src/target_word.cr index 0c121aa..4d5d348 100644 --- a/src/target_word.cr +++ b/src/target_word.cr @@ -1,5 +1,4 @@ - -class Bordle +class Bordle class TargetWord def initialize(@target_word : String) end @@ -8,7 +7,7 @@ class Bordle @target_word == word end - def to_h() + def to_h hash = Hash(Char, Array(Int32)).new @target_word.each_char_with_index do |char, index| hash[char] = [] of Int32 unless hash.has_key? char @@ -22,30 +21,30 @@ class Bordle result = [] of LetterScore # REF = r a t e s - # TEST= c e r e t + # TEST= c e r e t word.each_char_with_index do |char, index| - if ! hash.has_key? char + if !hash.has_key? char result << {char, Score::NotOk} next end char_values = hash[char] - char_misplaced = char_values.select {|pos| @target_word[pos] != word[pos] } - char_wellplaced = char_values.select {|pos| @target_word[pos] == word[pos] } + char_misplaced = char_values.select { |pos| @target_word[pos] != word[pos] } + char_wellplaced = char_values.select { |pos| @target_word[pos] == word[pos] } # puts "values(#{char}) = #{char_values}" # puts "misplaced(#{char}) = #{char_misplaced}" # puts "wellplaced(#{char}) = #{char_wellplaced}" if char_wellplaced.includes? index result << {char, Score::RightPlace} - char_wellplaced.reject! {|pos| pos == index } + char_wellplaced.reject! { |pos| pos == index } hash[char] = char_misplaced + char_wellplaced hash.delete(char) if hash[char].empty? next end - if ! char_misplaced.empty? + if !char_misplaced.empty? result << {char, Score::WrongPlace} char_misplaced = char_misplaced.skip(1) hash[char] = char_misplaced + char_wellplaced diff --git a/src/types.cr b/src/types.cr index 3795c47..27b29f9 100644 --- a/src/types.cr +++ b/src/types.cr @@ -1,8 +1,6 @@ - -class Bordle +class Bordle TR_DIACRITICS = "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšȘșſŢţŤťŦŧȚțÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž" - TR_ASCII = "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSsSssTtTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz" - + TR_ASCII = "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSsSssTtTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz" enum Score RightPlace = 0