-
Notifications
You must be signed in to change notification settings - Fork 1
/
ViewController.swift
144 lines (115 loc) · 4.65 KB
/
ViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//
// ViewController.swift
// WordScrable
//
// Created by Julian Moorhouse on 29/07/2019.
// Copyright © 2019 Mindwarp Consultancy Ltd. All rights reserved.
//
import UIKit
class ViewController: UITableViewController {
var allWords = [String]()
var usedWords = [String]()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(promptForAnswer))
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(startGame))
if let startWordsUrl = Bundle.main.url(forResource: "start", withExtension: "txt") {
if let startWords = try? String(contentsOf: startWordsUrl) {
allWords = startWords.components(separatedBy: "\n")
}
}
if allWords.isEmpty {
allWords = ["silkworm"]
}
startGame()
}
@objc func startGame() {
title = allWords.randomElement()
usedWords.removeAll(keepingCapacity: true)
tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usedWords.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Word", for: indexPath)
cell.textLabel?.text = usedWords[indexPath.row]
return cell
}
@objc func promptForAnswer() {
let ac = UIAlertController(title: "Enter answer", message: nil, preferredStyle: .alert)
ac.addTextField()
let submitAction = UIAlertAction(title: "Submit", style: .default) {
[weak self, weak ac] action in // specifies input into closure, ac is a weak reference
// using ac? as its a weak reference
guard let answer = ac?.textFields?[0].text?.lowercased() else { return }
guard let title = self?.title else { return }
if answer == title {
return
}
// also self is weak, ? safely checks that the alert is still there
self?.submit(answer)
}
ac.addAction(submitAction)
present(ac, animated: true)
}
func submit(_ answer: String) {
let lowerAnswer = answer.lowercased()
if isPossible(word: lowerAnswer) {
if isOriginal(word: lowerAnswer) {
if isReal(word: lowerAnswer) {
usedWords.insert(answer, at: 0)
let indexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
return
}
else
{
showErrorMessage("Word not recognized", "You can't just make them up, you know!")
}
}
else
{
showErrorMessage("Word already used", "Be more original!")
}
}
else
{
guard let title = title else { return }
showErrorMessage("Word not possible", "You can't spell that word from \(title.lowercased())")
}
}
func isPossible(word: String) -> Bool {
guard var tempWord = title?.lowercased() else { return false }
for letter in word {
if let position = tempWord.firstIndex(of: letter) {
tempWord.remove(at: position)
}
else
{
return false
}
}
return true
}
func isOriginal(word: String) -> Bool {
return !usedWords.contains(word)
}
func isReal(word: String) -> Bool {
if word.count < 3 {
return false
}
let checker = UITextChecker()
// scan length of word
let range = NSRange(location: 0, length: word.utf16.count)
// scan text for mistakes
let misspelledRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")
// if any misspellings were found
return misspelledRange.location == NSNotFound
}
func showErrorMessage(_ title: String, _ message: String) {
let ac = UIAlertController(title: title, message: message, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}