Here's how I would do it ( maybe also with larger buttons and letter slots). Also, modify to allow different target words. Regards, Michaela
// DataModel.swift
import Foundation
enum Letter : String {
case a = "A", b = "B", c = "C", d = "D", e = "E", f = "F", g = "G", h = "H", i = "I", j = "J", k = "K", l = "L", m = "M", n = "N", o = "O", p = "P", q = "Q", r = "R", s = "S", t = "T", u = "U", v = "V", w = "W", x = "X", y = "Y", z = "Z", sp = " "
}
struct WordLetter : Identifiable {
// has to be identifiable because some words (e.g. HELLO) have non-unique letters: so can't use .self as id
var id: Int = 0
var letter: Letter = .sp
}
class DataModel : ObservableObject {
let buttons: [[Letter]] = [
[.a, .b, .c, .d, .e, .f, .g],
[.h, .i, .j, .k, .l, .m, .n],
[.o, .p, .q, .r, .s, .t, .u],
[.v, .w, .x, .y, .z]]
var word = "HELLO"
@Published var finished = false {
didSet {
// now do something as a result of the user completing the word e.g. give a score, congratulate etc
}
}
@Published var wordSlots = [WordLetter]() {
didSet {
// see if there are still any spaces, if so not finished
for slot in wordSlots {
if slot.letter == .sp {
return
}
}
finished = true
}
}
var pressedButton : Letter? {
didSet {
// see if a button press letter is part of the word
findLetter()
}
}
init() {
// fill the Word Slots with blanks at the start - need to do this differently if you provide multiple target words
var tempSlots = [WordLetter]() // use a temporary array to save triggering an update to the main view for each blank added
for i in (0..<word.count) {
tempSlots.append(WordLetter(id: i, letter: .sp))
}
wordSlots = tempSlots
}
func findLetter() {
for i in (0..<word.count) {
let index = word.index(word.startIndex, offsetBy: i)
guard let pressed = pressedButton else { return }
// check if a pressed letter matches a letter (or more) in the word
if String(word[index]) == pressed.rawValue {
wordSlots[i].letter = pressed
}
}
}
}
import SwiftUI
struct ContentView: View {
@EnvironmentObject var dataModel: DataModel
var body: some View {
VStack{
Spacer()
HStack{
ForEach(dataModel.wordSlots) { wordLetter in
HStack{
Text(" ")
Text(wordLetter.letter.rawValue)
Text(" ")
} .border(.blue)
}
}
Spacer()
ForEach(dataModel.buttons, id: \.self) {row in
HStack{
ForEach(row, id: \.self) {item in
Button(action: {
dataModel.pressedButton = item }, label: {
Text(item.rawValue) })
}
}
}
Spacer()
}
}
}