VisualWorks - найти символы в строке и заменить их - PullRequest
2 голосов
/ 29 апреля 2019

У меня есть одно слово. Сначала вместо букв есть только? Так, например, слово «город» будет показано как «????». Тогда пользователь угадывает письмо, и если он его прибивает, оно изменится с? на фактическое письмо. Например, если он угадает t, это будет выглядеть так: «t ???».

Проблема в том, что я понятия не имею, как пройти строку и разделить ее на символы. И если я как-то это сделаю, я не смогу изменить это в новой строке.

Должно выглядеть как-то так.

word do: [ :c | 
          c = guessedChar
                ifTrue[mask := mask, guessedChar]
                ifFalse[mask := mask, '?']
            ].

mask инициализируется в ноль, потому что длина word может измениться, а word равно String. guessedChar подключен к inputField, однако он содержит только один символ за раз.

И было бы лучше, сделать это один раз для каждого угаданного символа или сохранить коллекцию всех угаданных символов и запускать его каждый раз?

Ответы [ 3 ]

2 голосов
/ 30 апреля 2019

A String - это Collection из Character объектов. Таким образом, вы можете использовать те же методы, которые применяются и к другим коллекциям (например, #select:, #collect: или #reject:)

guessedCharacters := 'ts'.
mask := word collect:[:each | (guessedCharacters includes: each)
                                 ifTrue:[each]
                                 ifFalse:[$?]].

Обратите внимание, что 't' - это String с Character t. Character может быть записан с префиксом $ как буквенный символ $t.

Поскольку String является подклассом SequenceableCollection, вы можете объединить две строки с помощью ,. Однако вы не можете объединить String и Character.

Вместо этого вы можете использовать #copyWith: для добавления Character к String. В результате получается новый String, он не будет изменять существующий экземпляр.

1 голос
/ 29 апреля 2019

Вы можете использовать

word doWithIndex: [:c :i | c = guess ifTrue: [mask at: i put: c]]

, что эквивалентно:

i := 1.
word do: [:c |
  c = guess ifTrue: [mask at: i put: c].
  i := i + 1]

, за исключением того, что вам не нужно инициализировать и увеличивать i (что немного большеподвержен ошибкам и более многословен)


Приложение

Учитывая, что экземпляры String не могут расти или изменять свой размер, что является неизменным, я предполагаю, чточто может измениться - это переменная word.В этом случае вы должны инициализировать mask соответственно, чтобы обе строки всегда имели одинаковую длину.Например:

 word: aString
   word := aString.
   mask := word copy atAllPut: $?

Если вы также хотите сохранить уже угаданные символы:

 word: aString
   | guessed |
   word := aString.
   guessed := mask reject: [:c | c = $?].
   mask := word copy atAllPut: $?.
   guessed do: [:c | self try: c].

Где #try: - это метод, который мы использовали до

try: aCharacter
  word doWithIndex: [:c :i | c = aCharacter ifTrue: [mask at: i put: c]]

(при желании вы можете uppercase вещей)

0 голосов
/ 13 мая 2019
"initially"
actualWord := 'phlebotomy'.
actualMask := actualWord collect: [:ch| $?].

"after each guess"
word := actualWord readStream.
mask := actualMask readStream.
newMask := WriteStream on: String new.
[ word atEnd
] whileFalse:
    [ nextCh := word next = guessedCharcter
                  ifTrue: [mask skip. guessedCharacter]
                  ifFalse: [mask next].
      newMask nextPut: nextCh
    ].
actualMask := newMask contents
...