-
Notifications
You must be signed in to change notification settings - Fork 1
/
ViewController.swift
135 lines (110 loc) · 4.36 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
//
// 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))
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()
}
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 else { 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()
let errorTitle: String
let errorMessage: String
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
{
errorTitle = "Word not recognized"
errorMessage = "You can't just make them up, you know!"
}
}
else
{
errorTitle = "Word already used"
errorMessage = "Be more original!"
}
}
else
{
guard let title = title else { return }
errorTitle = "Word not possible"
errorMessage = "You can't spell that word from \(title.lowercased())"
}
let ac = UIAlertController(title: errorTitle, message: errorMessage, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
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 {
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
}
}