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