我有一个字。起初,而不是字母,只有?。例如,单词“town”将显示为“????”。然后用户猜猜字母,如果他钉了它,它会改变吗?到实际的信。例如,如果他猜对了,那就像是't ???'。
问题是,我不知道如何通过字符串并将其划分为字符。如果我以某种方式这样做,我无法在新字符串中更改它。
应该看起来像这样。
word do: [ :c |
c = guessedChar
ifTrue[mask := mask, guessedChar]
ifFalse[mask := mask, '?']
].
mask
初始化为零,因为word
长度可以改变而word
是String
。 guessedChar
连接到inputField,但它一次只包含一个字符。
它会更好,为每个猜对手做一次或者保持所有猜对象的集合并且每次都运行它吗?
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
,它不会修改现有的实例。
你可以用
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
的东西)
"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