My code appends ints to an array. There is no sorting. I would like to index every entry to the array. Sort the array from smallest to largest.
import UIKit
class ViewController: UIViewController {
#IBOutlet var enterText: UITextField!
var arrayOfInt = [Int]()
#IBAction func submitText(_ sender: Any) {
if let text = enterText.text {
if let number = Int(text) {
arrayOfInt.append(number)
print(arrayOfInt)
} else {
print("Please enter number")
}
}
}
}
You can use like this :
#IBAction func submitText(_ sender: Any) {
if let text = enterText.text {
if let number = Int(text) {
var index = 0
for num in arrayOfInt {
if num > number {
arrayOfInt.insert(number, at: index)
break
}
index += 1
}
print(arrayOfInt)
} else {
print("Please enter number")
}
}
}
Related
I am adding in some functionalities for this iOS swift matching card game and I need to check if the first 2 buttons flipped over match. They have four types of emojis for eight cards, which means there are 4 pairs of matches. I am having trouble finding out how to check if the cards match and when they match, I need the background color of the buttons to opaque (invisible). Everything else works except the empty if statement in the concentration class within the chooseCard function. That is where I need help.
Here's all the code so you can see whats related to what:
class ViewController: UIViewController {
lazy var game = Concentration(numberOfPairsOfCards: (cardButtons.count + 1) / 2)
var flipCount = 0 {
// Property Observer
didSet { flipLabel.text = "Flips: \(flipCount)" }
}
#IBOutlet weak var flipLabel: UILabel!
#IBOutlet var cardButtons: [UIButton]!
#IBAction func touchCard(_ sender: UIButton) {
flipCount+=1
if let cardNumber = cardButtons.firstIndex(of: sender) {
game.chooseCard(at: cardNumber)
updateViewFromModel()
} else {
print ("chosen card was not in cardButtons")
}
}
var emojiChoices = ["๐ป", "๐", "๐๐พ", "๐ฆ"]
var emoji = [Int:String]()
func emoji(for card: Card) -> String {
if emoji[card.identifier] == nil, emojiChoices.count > 0 {
let randomIndex = Int(arc4random_uniform(UInt32(emojiChoices.count)))
emoji[card.identifier] = emojiChoices.remove(at: randomIndex)
}
return emoji[card.identifier] ?? "?"
}
func updateViewFromModel() {
for index in cardButtons.indices {
let button = cardButtons[index]
let card = game.cards[index]
if card.isFaceUp {
button.setTitle(emoji(for: card), for: UIControl.State.normal)
button.backgroundColor = UIColor.white
}
else {
button.setTitle("", for: UIControl.State.normal)
button.backgroundColor = UIColor.orange
}
}
}
}
import Foundation
class Concentration {
var cards = [Card]()
func chooseCard(at index: Int) {
if cards[index].isFaceUp {
cards[index].isFaceUp = false
}
else {
cards[index].isFaceUp = true
}
if cards[index].isFaceUp && cards[index].isMatched {
}
}
init(numberOfPairsOfCards: Int) {
for _ in 0..<numberOfPairsOfCards {
let card = Card()
cards += [card,card]
}
//TODO: Shuffle cards
cards.shuffle()
}
}
import Foundation
struct Card {
var isMatched = false
var isFaceUp = false
var identifier: Int
static var identifierFactory = 0
static func getUniqueIdentifier() -> Int {
Card.identifierFactory += 1
return Card.identifierFactory
}
init() {
self.identifier = Card.getUniqueIdentifier()
}
}
In your concentration class you will check for faceUp card indexes
Change your Concentration from class to Struct
struct Concentration { // instead of class Concentration
private var indexOfFaceUpCard: Int? {
get {
let faceUpCardIndices = cards.indices.filter { cards[$0].isFaceUp }
return faceUpCardIndices.count == 1 ? faceUpCardIndices.first : nil
} set {
for index in cards.indices {
cards[index].isFaceUp = (index == newValue)
}
}
}
Then you have mutating chooseCard method
mutating func chooseCard(at index: Int)
In your chooseCard method you check for matching
if !cards[index].isMatched {
if let matchIndex = indexOfFaceUpCard, matchIndex != index {
if cards[matchIndex] == cards[index] {
cards[matchIndex].isMatched = true
cards[index].isMatched = true
}
cards[index].isFaceUp = true
} else {
indexOfFaceUpCard = index
}
}
So your method look like this
mutating func chooseCard(at index: Int) {
if !cards[index].isMatched {
if let matchIndex = indexOfFaceUpCard, matchIndex != index {
if cards[matchIndex] == cards[index] {
cards[matchIndex].isMatched = true
cards[index].isMatched = true
}
cards[index].isFaceUp = true
} else {
indexOfFaceUpCard = index
}
}
}
Update your card struct
struct Card: Hashable {
var isMatched = false
var isFaceUp = false
var identifier: Int
static var identifierFactory = 0
static func getUniqueIdentifier() -> Int {
Card.identifierFactory += 1
return Card.identifierFactory
}
static func ==(lhs: Card, rhs: Card) -> Bool {
return lhs.identifier == rhs.identifier
}
init() {
self.identifier = Card.getUniqueIdentifier()
}
}
I'm a beginner to Swift and generally Xcode. Thank you in advance for your time and help :)
I am doing a Quiz App, and I try to have random questions... I have a function to generate random numbers that I tried to apply in viewDidLoad()... unfortunately I can not guess how to use that information in his variable "var currentQuestion = 0"
This is the code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
generateRandomNumber(0, 9, 10)
}
override func viewDidAppear(_ animated: Bool) {
newQuestion()
}
// Quiz//
let questions = ["Q1","Q2","Q3","Q4","Q5"]
let answers = [["A","2","3"],["B","2","3"],["C","2","3"],["D","2","3"],["E","2","3"]]
//Variables
var currentQuestion = 0
var rightAnswerPlacement:UInt32 = 0
//Generate Random Numbers
func generateRandomNumber(_ from:Int, _ to:Int, _ qut:Int?) -> [Int] {
var myRandomNumbers = [Int]() //All our generated numbers
var numberOfNumbers = qut //How many numbers to generate
let lower = UInt32(from) //Generate from this number..
let higher = UInt32(to+1) //To this one
if numberOfNumbers == nil || numberOfNumbers! > (to-from) + 1 {
numberOfNumbers = (to-from) + 1
}
while myRandomNumbers.count != numberOfNumbers {
let myNumber = arc4random_uniform(higher - lower) + lower
if !myRandomNumbers.contains(Int(myNumber)) {
myRandomNumbers.append(Int(myNumber))
}
}
return myRandomNumbers
}
//Label
#IBOutlet weak var lbl: UILabel!
//Button
#IBAction func action(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerPlacement)) {
print ("RIGHT!")
} else {
print ("WRONG!!!!!!")
}
if (currentQuestion != questions.count) {
newQuestion()
} else {
}
}
//Function that displays new question
func newQuestion() {
lbl.text = questions[currentQuestion]
rightAnswerPlacement = arc4random_uniform(3)+1
//Create a button
var button:UIButton = UIButton()
var x = 1
for i in 1...3 {
//Create a button
button = view.viewWithTag(i) as! UIButton
if (i == Int(rightAnswerPlacement)) {
button.setTitle(answers[currentQuestion][0], for: .normal)
} else {
button.setTitle(answers[currentQuestion][x], for: .normal)
x = 2
}
}
currentQuestion += 1
}
Any idea that how will be possible to resolve?
First you need to store the array of random questions that you generate (side note you appear to try to generate 10 random numbers but have only 5 questions).
Then instead of using the currentQuestion directly you use that to access the question in the array.
So change it to this:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
questionArray = generateRandomNumber(0, 9, 10)
}
override func viewDidAppear(_ animated: Bool) {
newQuestion()
}
// Quiz//
let questions = ["Q1","Q2","Q3","Q4","Q5"]
let answers = [["A","2","3"],["B","2","3"],["C","2","3"],["D","2","3"],["E","2","3"]]
//Variables
var currentQuestion = 0
var rightAnswerPlacement:UInt32 = 0
var questionArray: [Int] = [] // Just an initial value
//Generate Random Numbers
func generateRandomNumber(_ from:Int, _ to:Int, _ qut:Int?) -> [Int] {
var myRandomNumbers = [Int]() //All our generated numbers
var numberOfNumbers = qut //How many numbers to generate
let lower = UInt32(from) //Generate from this number..
let higher = UInt32(to+1) //To this one
if numberOfNumbers == nil || numberOfNumbers! > (to-from) + 1 {
numberOfNumbers = (to-from) + 1
}
while myRandomNumbers.count != numberOfNumbers {
let myNumber = arc4random_uniform(higher - lower) + lower
if !myRandomNumbers.contains(Int(myNumber)) {
myRandomNumbers.append(Int(myNumber))
}
}
return myRandomNumbers
}
//Label
#IBOutlet weak var lbl: UILabel!
//Button
#IBAction func action(_ sender: AnyObject) {
if (sender.tag == Int(rightAnswerPlacement)) {
print ("RIGHT!")
} else {
print ("WRONG!!!!!!")
}
if (currentQuestion != questions.count) {
newQuestion()
} else {
}
}
//Function that displays new question
func newQuestion() {
lbl.text = questions[questionArray[currentQuestion]]
rightAnswerPlacement = arc4random_uniform(3)+1
//Create a button
var button:UIButton = UIButton()
var x = 1
for i in 1...3 {
//Create a button
button = view.viewWithTag(i) as! UIButton
if (i == Int(rightAnswerPlacement)) {
button.setTitle(answers[questionArray[currentQuestion]][0], for: .normal)
} else {
button.setTitle(answers[questionArray[currentQuestion]][x], for: .normal)
x = 2
}
}
currentQuestion += 1
}
(I think the code is correct but I'm currently running some tests in Xcode so can't check. If there is a problem leave a comment.)
In my calculator app I ran into a problem where I want ... to show in my array but only when the if statement for resultIsPending is true. Then after that I want the ... to be deleted. How can I do this in Swift? Here is the code of my ViewController.swift:
#IBOutlet weak var sequence: UILabel!
#IBOutlet weak var display: UILabel!
var userInTheMiddleOfTyping = false
var resultIsPending:Bool = false
var elements = [String]()
//var sequenceArray:Array = []
#IBAction func clear(_ sender: Any) {
display.text = " "
elements.removeAll()
elements = elements.filter{$0 != "\(String(describing: display.text))"}
sequence.text = elements.joined()
}
override func viewDidLoad() {
}
#IBAction func touchDigit(_ sender: UIButton) {
let digit = sender.currentTitle!
elements.append(digit)
combineToMakeOperationHistory()
if userInTheMiddleOfTyping{
let textCurrentlyInDisplay = display!.text!
display!.text = textCurrentlyInDisplay + digit
} else {
display!.text = digit
userInTheMiddleOfTyping = true
}
}
var displayValue: Double{
get{
return Double(display.text!)!
}
set{
display.text = String(newValue)
}
}
private var brain = CalculatorBrain()
#IBAction func performOperation(_ sender: UIButton) {
let perSender = sender.currentTitle!
elements.append(perSender)
combineToMakeOperationHistory()
if perSender == "+" || perSender == "รท" || perSender == "ร" || perSender == "-" || perSender == "^"{
resultIsPending = true
}
if userInTheMiddleOfTyping{
brain.setOperand(displayValue)
userInTheMiddleOfTyping = false
}
userInTheMiddleOfTyping = false
if let mathematicalSymbol = sender.currentTitle{
brain.performOperation(mathematicalSymbol)
}
if brain.result != nil{
displayValue = brain.result!
}
}
func combineToMakeOperationHistory() {
if resultIsPending{ // this is the if statement
elements.append("...")
}else if resultIsPending == false{
}
sequence.text = elements.joined()
}
You can filter your elements array and remove the "...".
elements = elements.filter({ $0 != "..." })
Whenever you want to remove the occurrence of a String value.
you can uses something like hat
var resultIsPending:Bool = false{
didSet(isPending) {
if isPending {
elements.append("...")
} else {
elements.dropLast()
}
}
}
Don't combine data that are not of the same type. There is no reason to put ... into the array of elements:
func combineToMakeOperationHistory() {
var sequenceText: String = elements.joined()
if (resultIsPending) {
sequenceText += "..."
}
sequence.text = sequenceText
}
Since we are not appending ... to the array, we don't have to remove it.
I am trying to store randomly generated data into a second array so that I am able to press a button to go back to it. At the moment I press back and there is nothing there. I think it is due to the items not being correctly stored in the second array. I will provide the code for reference. Any help would be greatly appreciated!
var randomGeneratedQuotes = Array <String>()
var currentlyShown : String?
var randomQuote: String {
let randomNumber = Int(arc4random_uniform(UInt32(myQuotes.count)))
return myQuotes[randomNumber]
}
var previousRandom: String? {
if currentlyShown == randomQuote {
let previous = randomGeneratedQuotes.index(of: currentlyShown!)! - 1
return randomGeneratedQuotes[previous]
}
return randomGeneratedQuotes.last
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var randomQuote: String {
let randomNumber = Int(arc4random_uniform(UInt32(myQuotes.count)))
return myQuotes[randomNumber]
}
func storePrevious() {
if randomGeneratedQuotes.contains(randomQuote) {return}
randomGeneratedQuotes.append(randomQuote)
}
quotesLabel.text = randomQuote
}
//right hand button tapped
#IBAction func RHSButton(_ sender: Any) {
var randomQuote: String {
let randomNumber = Int(arc4random_uniform(UInt32(myQuotes.count)))
return myQuotes[randomNumber]
}
func storePrevious() {
if randomGeneratedQuotes.contains(randomQuote) {return}
randomGeneratedQuotes.append(randomQuote)
}
quotesLabel.text = randomQuote
}
//left hand button tapped
#IBAction func LHSButton(_ sender: Any) {
func pressedBack() {
currentlyShown = previousRandom
}
quotesLabel.text = previousRandom
}
I have created a calculator and have created a Model.swift to handle all of my calculations. Then everything else is handled in my ViewController.swift. I'm trying to add another functionality, I am looking to create a history of all the operations performed in my calculator i have made and store them in an array.
Here is my code so far:
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var displayLabel: UILabel!
#IBOutlet weak var HistoryLabel: UILabel!
var historyArray: [String] = []
var userIsTypingNumbers = false
var firstNumber = 0
var secondNumber = 0
#IBAction private func NumbersEntered(_ sender: UIButton) {
//know what number is being pressed
/*let digit = sender.currentTitle!
//if user is typing a number, do this.
if userIsTypingNumbers{
//specify what number is being pressed
let textCurrentDisplay = displayLabel.text!
//append the another number onto the previous number.
displayLabel.text = textCurrentDisplay + digit
} else {
displayLabel.text = digit
}
userIsTypingNumbers = true*/
/*addToHistory(recordToAddToHistory: digit)*/
let number = sender.currentTitle
if userIsTypingNumbers {
displayLabel.text = displayLabel.text! + number!
} else {
displayLabel.text = number
userIsTypingNumbers = true
}
}
var displayValue: Double {
get {
return Double(displayLabel.text!)!
}
set {
displayLabel.text = String(newValue)
}
}
private var calculations = PerformCalculations()
#IBAction func Enter(_ sender: UIButton) {
//perform the calculations
if userIsTypingNumbers{
calculations.setOperand(operand: displayValue)
userIsTypingNumbers = false
}
if let mathematicalSymbol = sender.currentTitle {
calculations.performOperation(symbol: mathematicalSymbol)
/*addToHistory(recordToAddToHistory: String(mathematicalSymbol))*/
}
/*HistoryLabel.text = HistoryLabel.text! + String(sender.currentTitle!)*/
displayValue = calculations.result
/*HistoryLabel.text = HistoryLabel.text! + String(displayValue)*/
/*historyArray.append("\(String(describing: HistoryLabel.text))")*/
}
#IBAction func Clear(_ sender: UIButton) {
//clear display to 0.
displayLabel.text = "0"
HistoryLabel.text = ""
}
#IBAction func Delete(_ sender: UIButton) {
//deleting last typed number, if user messed up.
let name: String = self.displayLabel.text!
//count number of characters.
let stringLength = name.characters.count
let substringIndex = stringLength - 1
displayLabel.text = (name as NSString).substring(to: substringIndex)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "History"){
if let destinationVC = segue.destination as? HistoryClassViewController{
destinationVC.someData = HistoryLabel.text
}
}
}*/
}
Model.swift
import Foundation
enum Optional<T>{
case None
case Some(T)
}
class PerformCalculations {
private var accumulator = 0.0
func setOperand(operand: Double){
accumulator = operand
}
//performing the operations for various operands
private var operations: Dictionary<String, Operation> = [
"โ" : Operation.UnaryOperation(sqrt), //sqrt,
"ร": Operation.BinaryOperation({$0 * $1}),
"+": Operation.BinaryOperation({$0 + $1}),
"-": Operation.BinaryOperation({$0 - $1}),
"รท": Operation.BinaryOperation({$0 / $1}),
"=": Operation.Equals
]
//case for various operands
private enum Operation{
case Constant(Double)
case UnaryOperation((Double) -> Double)
case BinaryOperation((Double, Double) -> Double)
case Equals
}
//switch case to actually perform the operations
func performOperation(symbol: String){
if let operation = operations[symbol]{
switch operation{
case .Constant(let value): accumulator = value
case .BinaryOperation(let function):
executePendingBinaryOperation()
pendingVar = PendingBianryOperationInfo(binaryFunction: function, firstOperand: accumulator)
case .UnaryOperation(let foo): accumulator = foo(accumulator)
case .Equals:
executePendingBinaryOperation()
}
}
}
private func executePendingBinaryOperation(){
if pendingVar != nil{
accumulator = pendingVar!.binaryFunction(pendingVar!.firstOperand,accumulator)
pendingVar = nil
}
}
private var pendingVar: PendingBianryOperationInfo?
private struct PendingBianryOperationInfo{
var binaryFunction: (Double, Double) -> Double
var firstOperand: Double
}
var result: Double{
get{
return accumulator
}
}
}
Any help would be appreciated, thank you very much!
I have solved my problem. Here is the updated code, incase it ever comes in handy for someone.
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var displayLabel: UILabel!
#IBOutlet weak var HistoryLabel: UILabel!
var historyArray: [String] = []
var userIsTypingNumbers = false
var firstNumber = 0
var secondNumber = 0
var operation = ""
var result = 0.0
#IBAction private func NumbersEntered(_ sender: UIButton) {
//know what number is being pressed
let number = sender.currentTitle
//if user is typing number, do this.
if userIsTypingNumbers {
//specify what number is being pressed.
//append the number onto the previous number.
displayLabel.text = displayLabel.text! + number!
} else {
displayLabel.text = number
userIsTypingNumbers = true
}
}
var displayValue: Double {
get {
return Double(displayLabel.text!)!
}
set {
displayLabel.text = String(newValue)
}
}
private var calculations = PerformCalculations()
#IBAction func OperationsPressed(_ sender: UIButton) {
userIsTypingNumbers = false
firstNumber = Int(Double(displayLabel.text!)!)
operation = sender.currentTitle!
if operation == "โ" {
result = (PerformCalculations().squareroot(a: Double(firstNumber)))
displayLabel.text = String(result)
}
}
#IBAction func Enter(_ sender: UIButton) {
userIsTypingNumbers = false
secondNumber = Int(Double(displayLabel.text!)!)
if operation == "+" {
result = (PerformCalculations().add(a: Double(firstNumber), b: Double(secondNumber)))
} else if operation == "รท" {
result = (PerformCalculations().division(a: Double(firstNumber), b: Double(secondNumber)))
} else if operation == "ร" {
result = (PerformCalculations().multiplication(a: Double(firstNumber), b: Double(secondNumber)))
} else if operation == "-" {
result = (PerformCalculations().subtract(a: Double(firstNumber), b: Double(secondNumber)))
}
displayLabel.text = String(result)
historyArray.append("\(firstNumber) \(operation) \(secondNumber) = \(result)")
userIsTypingNumbers = false
//self.performSegue(withIdentifier: "History", sender: self)
}
#IBAction func Clear(_ sender: UIButton) {
//clear display to 0.
displayLabel.text = "0"
}
#IBAction func Delete(_ sender: UIButton) {
//deleting last typed number, if user messed up.
let name: String = self.displayLabel.text!
//count number of characters.
let stringLength = name.characters.count
let substringIndex = stringLength - 1
displayLabel.text = (name as NSString).substring(to: substringIndex)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "History" {
if let destinationVC = segue.destination as? TableTableViewController {
destinationVC.dataString = historyArray.description
}
}
}*/
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destViewController : TableTableViewController = segue.destination as! TableTableViewController
destViewController.dataString = historyArray.description
}
}
Model.swift
import Foundation
class PerformCalculations {
func add(a: Double, b: Double) -> Double {
let result = a + b
return result
}
func division(a: Double, b: Double) -> Double {
let result = a / b
return result
}
func subtract(a: Double, b: Double) -> Double {
let result = a - b
return result
}
func multiplication(a: Double, b: Double) -> Double {
let result = a * b
return result
}
func squareroot(a: Double) -> Double {
let result = sqrt(a)
return result
}
}