How to make a loop in a switch with a readline - ios

I have to make a game for my online course, it displays on the console it's a game for 2 players with 3 characters for each team and I'm struggling how can i make a loop in my switch to "force" the player to choose between 1, 2 or 3 (it symbolize the characters of his team) to attack the enemy team, here's my code :
func chooseChar(charac: inout[Character]){
let choice = readLine()
var attacker: Character
switch choice {
case "1":
attacker = self.playerTeam[0]
charac.append(attacker)
case "2":
attacker = self.playerTeam[1]
charac.append(attacker)
case "3":
attacker = self.playerTeam[2]
charac.append(attacker)
default: print("choose between 1 2 3")
}
}
Actually, when the player choose for example 4 it goes on the default and my code stop...
Anybody have an idea ? sorry for my bad english !
Thanks !

Use a classic C way and add while(true) make things easier like this.
func chooseChar(charac: inout[Character]){
while (true){
let choice = readLine()
var attacker: Character
switch choice {
case "1":
attacker = self.playerTeam[0]
charac.append(attacker)
return
case "2":
attacker = self.playerTeam[1]
charac.append(attacker)
return
case "3":
attacker = self.playerTeam[2]
charac.append(attacker)
return
default: print("choose between 1 2 3")
}
}
}

As per your requirement you can call the same function in default case (use recursion)(this will make your code running until any case1,case2,or case3 occurs), or you can set a parameter in default case and check outside the switch and make action according to that.

Related

swift switch statement cases have different and shared things to do

i have code like this
switch thing {
case thisThing:
do thing #1
do thing #2
case thatThing:
do thing #2
do thing #3
case anotherThing:
do thing #4
default:
default
}
So, EVERY case has something that ONLY IT does. Some cases also do the same things as one or more other cases.
Is there a way to accomplish this if I don't want any repetitive code?
OR, is there a much more efficient way of doing this without switch statements at all?? I mean, I could, for example, use if statements, but like switch statements, I can't think of a way to accomplish what I want without using repetitive code.
also, this example might be more clear than the above
myFavoriteNumbers = []
myLeastFavoriteNumbers = []
switch myNumber {
case 1:
print("my number is number 1") // do this only for case 1
myFavoriteNumbers += [1] // do this for case 1 and case 2
case 2:
print("this is number 2") // do this only for case 2
myFavoriteNumbers += [2] // do this for case 1 and case 2
case 3:
print("I don't like number 3") // do this only for case 3
myLeastFavoriteNumbers += [3] // do this for case 3 and case 4
case 4:
print("Number Four") // do this only for case 4
myLeastFavoriteNumbers += [4] // do this for case 3 and case 4
default:
print("Default")
}
You can use an initial separate pattern matching statement (comparable to a single case independent from the switch statement) that covers the actions that are unique for any (valid) number, and let the switch statement follow with cases that handle actions that are common for several numbers. With this you separate the unique and common logic action, where the latter is simply implemented as usual cases for any pattern matching switch implementation.
E.g., for your example
var myFavoriteNumbers: [Int] = []
var myLeastFavoriteNumbers: [Int] = []
let myNumberDescriptions = ["my number is number 1",
"this is number 2", "I don't like number 3", "Number Four"]
let myNumber = 1
/* unique action:
perform a unique action (given a valid number)
and thereafter proceed to common cases */
if 1...myNumberDescriptions.count ~= myNumber {
print(myNumberDescriptions[myNumber-1])
}
/* common cases */
switch myNumber {
/* common case: is a favourite number */
case 1...2: myFavoriteNumbers += [myNumber]
/* common case: is a least favourite number */
case 3...4: myLeastFavoriteNumbers += [myNumber]
default:
print("Default")
}
In case the action that is unique to any number is more complex, use the same approach as above, but use more advanced logic (e.g. an event handler) for the unique action "case".
You could nest switch statements that switch on the same value, like this:
switch myNumber {
case 1...2:
myFavoriteNumbers += [myNumber] // do this for case 1 and case 2
switch myNumber {
case 1:
print("my number is number 1") // do this only for case 1
default:
print("this is number 2") // do this only for case 2
}
case 3...4:
myLeastFavoriteNumbers += [myNumber] // do this for case 3 and case 4
switch myNumber {
case 3:
print("I don't like number 3") // do this only for case 3
default:
print("Number Four") // do this only for case 4
}
default:
print("Default")
}
Not the most elegant bit of code you'll ever see, but it achieves what you want to achieve without the repetition.
Fallthrough comes to mind as an obvious solution, but as somebody here already said it does not work in a way that would be helpful.
I don't have any silver bullet for you but I think I would go about this in such a way:
create one switch statement which only covers separate logic
create a second switch statement which combines common logic
switch thing {
case thisThing:
do thing #1
case thatThing:
do thing #4
case anotherThing:
do thing #5
default: ()
}
switch thing {
case thisThing, thatThing:
do thing #2
default: ()
}
It would work when your logic does not depend on the order of function calls (which it should not, if it does it may be a sign to improve your code design). To me it looks clean, however it's still not ideal..

Swift : Recursively calling a function with an enum type as a parameter

I found this code at apple swift documentation
indirect enum ArithmeticExpression {
case Number(Int)
case Addition(ArithmeticExpression, ArithmeticExpression)
case Multiplication(ArithmeticExpression, ArithmeticExpression)
}
func evaluate(expression: ArithmeticExpression) -> Int {
switch expression {
case .Number(let value):
return value
case .Addition(let left, let right):
return evaluate(left) + evaluate(right)
case .Multiplication(let left, let right):
return evaluate(left) * evaluate(right)
}
}
// evaluate (5 + 4) * 2
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let sum = ArithmeticExpression.Addition(five, four)
let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2))
print(evaluate(product))
// prints "18"
i don't quit understand how the recursion is happening in here and why a constant declaration is being declared as a parameter in the return statement in the returning line ?
Think of it as a tree. Nodes=Expressions. Constants=Leaves.
(image source ruslanspivak.com)
While traversing it - you examine each of the two operands. If it's an expression, you need to compute it, so you call on 'evaluate' with this operand. If it's a constant, think of it like a result - it's just a number, so no more calculations are needed.
In the end, we ALWAYS get to a constants (=leaves) it is then when the the stack starts to fold and the values results return "up" in the tree to add up to the total result.
For more diving into the subject I recommend googling "binary expression tree".
(By the way, the code example does not tend for priorities. The multiplication is computed before the addition only because the order of calls.
If we really wanted to take care of priorities : e.g. "(", ")" over "*" , "/", a stack for operations would have been needed here.)

Is there a way of checking more than one condition in Swift switch?

In Swift, I need to make a switch like this:
switch char {
case "+": statement 1; statement 3
case "-": statement 2; statement 3
default: statement 3
}
However, I don't want to copy the statement 3, because it is actually quite long, so I'm looking for an alternative way (if it exists) to somehow make the switch check every case condition, and execute the default too.
Repeated code? Good candidate for a local function:
func statement3() {
// ... lots of stuff here ...
}
switch char {
case "+": statement 1; statement3()
case "-": statement 2; statement3()
default: statement3()
}
But if you really want to do statement3 in every case, then just take it out of the switch statement altogether:
switch char {
case "+": statement 1
case "-": statement 2
default: break
}
statement 3
The only way you can fallthrough a case and skip over the next one to get you to default is to retest the condition:
switch char {
case "+": statement 1; fallthrough
case "-": if char == "-" { statement 2 }; fallthrough
default: statement 3
}
which at the end of the day, let's be honest, looks awesomely frugly. I suggest you replace your long statements by function calls and keep the control flow you gave above.

What is the difference between a return and a break in an infinite loop?

In doing the Guessing Game from the Rust Book (I won't put the link because it will probably not exist in a few weeks), there is a point where you use return to break out of the loop. I used break instead:
loop {
guess = guesser();
guess_cast = guess.trim().parse();
let guess_num = match guess_cast {
Ok(num) => num,
Err(_) => {
println!("Guess was not a number, try again");
continue;
},
};
if guess_num < answer {
println!("Too low");
} else if guess_num > answer {
println!("Too high");
} else {
println!("You guessed it!");
break;
}
}
Is there a real difference in using return over break in this case? What about other cases when you want to break out of an infinite loop?
If the loop is the final statement in the function, then there is patently no functional distinction between break; and return;. If this condition does not hold, there is evidently a difference, for return terminates execution of the function, while break only terminates execution of the loop.
In the case where they are functionally the same, which you use may vary based on context (which one feels better in this particular location), personal preference and what, if anything, you ate for breakfast.

Switch statement in Swift

I'm learning syntax of Swift and wonder, why the following code isn't working as I expect it to:
for i in 1...100{
switch (i){
case 1:
Int(i%3) == 0
println("Fizz")
case 2:
Int(i%5) == 0
println("Buzz")
default:
println("\(i)")
}
}
I want to print Fizz every time number is divisible by 3 (3, 6, 9, 12, etc) and print Buzz every time it's divisible by 5. What piece of the puzzle is missing?
Note: I did solve it using the following:
for ( var i = 0; i < 101; i++){
if (Int(i%3) == 0){
println("Fizz")
} else if (Int(i%5) == 0){
println("Buzz")
} else {
println("\(i)")
}
}
I want to know how to solve this using Switch. Thank you.
The usual rules for the FizzBuzz game
are to replace every multiple of 3 by "Fizz", every multiple of 5 by "Buzz", and
every multiple of both 3 and 5 by "FizzBuzz".
This can be done with a switch statement on the tuple (i % 3, i % 5).
Note that _ means "any value":
for i in 1 ... 100 {
switch (i % 3, i % 5) {
case (0, 0):
print("FizzBuzz")
case (0, _):
print("Fizz")
case (_, 0):
print("Buzz")
default:
print(i)
}
}
Switch statements in Swift support value bindings.
This allows you to assign a value that matches a certain condition (evaluated via the where clause) to a temporary variable (x & y here):
for i in 1...100 {
switch (i){
case let x where x%3 == 0:
println("Fizz")
case let y where y%5 == 0:
println("Buzz")
default:
println("\(i)")
}
}
You could also use the assigned temp value in the case body.
Update:
Matt Gibson points out in the comments, that you can omit the assignment to a temp var if you are not going to use it in the case body.
So a more concise version of the above code would be:
for i in 1...100 {
switch (i){
case _ where i%3 == 0:
println("Fizz")
case _ where i%5 == 0:
println("Buzz")
default:
println("\(i)")
}
}
Side note: Your 2 code samples are slightly different (the first one uses the range 0-100 as input, while the second one operates on 1-100). My sample is based on your first code snippet.
This is a more general answer for people who come here just wanting to know how to use the switch statement in Swift.
General usage
switch someValue {
case valueOne:
// executable code
case valueTwo:
// executable code
default:
// executable code
}
Example
let someValue = "horse"
switch someValue {
case "horse":
print("eats grass")
case "wolf":
print("eats meat")
default:
print("no match")
}
Notes:
No break statement is necessary. It is the default behavior. Swift switch cases do not "fall through". If you want them to fall through to the code in the next case, you must explicitly use the fallthrough keyword.
Every case must include executable code. If you want to ignore a case, you can add a single break statement.
The cases must be exhaustive. That is, they must cover every possibly value. If it is not feasible to include enough case statements, a default statement can be included last to catch any other values.
The Swift switch statement is very flexible. The following sections include some other ways of using it.
Matching multiple values
You can match multiple values in a single case if you use separate the values with commas. This is called a compound case.
let someValue = "e"
switch someValue {
case "a", "b", "c":
// executable code
case "d", "e":
// executable code
default:
// executable code
}
You can also match whole intervals.
let someValue = 4
switch someValue {
case 0..<10:
// executable code
case 10...100:
// executable code
default:
// executable code
}
You can even use tuples. This example is adapted from the documentation.
let aPoint = (1, 1)
switch aPoint {
case (0, 0):
// only catches an exact match for first and second
case (_, 0):
// any first, exact second
case (-2...2, -2...2):
// range for first and second
default:
// catches anything else
}
Value Bindings
Sometimes you might want to create a temporary constant or variable from the switch value. You can do this right after the case statement. Anywhere that a value binding is used, it will match any value. This is similar to using _ in the tuple example above. The following two examples are modified from the documentation.
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
// can use x here
case (0, let y):
// can use y here
case let (x, y):
// can use x or y here, matches anything so no "default" case is necessary
}
You can further refine the matching by using the where keyword.
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
// executable code
case let (x, y) where x == -y:
// executable code
case let (x, y):
// executable code
}
Further study
This answer was meant to be a quick reference. Please read the full documentation for more. It isn't difficult to understand.
This is how it can be done
var i = 0
switch i {
case i where i % 5 == 0 && i % 3 == 0: print(" Fizz Buzz")
case i where i % 3 == 0 : print("Fizz")
case i where i % 5 == 0 : print("Buzz")
default: print(i)
}
The industry standard behaviour of switch can lead to bugs similar to "Go to Fail".
Basically the code doesn't always do exactly what it looks like the code will do when reading over it, which leads to code auditors skipping over critical bugs.
To counter that, Apple has decided switch statements should not work the same in Swift as the industry standard. In particular:
There is an automatic break at the end of every case. It's impossible for more than one case statement to execute.
If it's theoretically possible for one of the case statements to be missed, then the code will not compile at all. In swift one of the case statements will always execute, no matter what value is provided. If you provide an enum, every enum value must be handled. If a new value is added to an existing enum the code won't compile until new case statements are added. If you provide a 32 bit integer, you must handle every possible value of a 32 bit int.
Here are the two ways I use switch statement for this kind of problems .
1>> Using where keyword
func printNumberType(number : Int){
switch number {
case number where number % 3 == 0 && number % 5 == 0 :
print("foo bar")
case number where number % 3 == 0 :
print("foo")
case number where number % 5 == 0 :
print("bar")
default :
print("Number is not divisible by 3 and 5")
}
}
2>> Using values combination
func printNumberByMultipleValues(number : Int){
let combination = (number % 3,number % 5)
switch combination {
case (0,0):
print("foo bar")
case (0,_) :
print("foo")
case (_,0) :
print("bar")
default :
print("Number is not divisible by 3 and 5")
}
}
Here is closer example for multiple value type .
var printNumberByMultipleValues : (Int)->() = { number in
let combination = (number % 3,number % 5)
switch combination {
case (0,0):
print("foo bar")
case (0,_) :
print("foo")
case (_,0) :
print("bar")
default :
print("Number is not divisible by 3 and 5")
}
}
Use this code. Your logic is wrong. Your Switch Statement does not find the case accept 1 and 2
class TEST1{
func print() -> Void{
var i = 0
for i in 1...100{
if Int(i%3) == 0 {
println("Fizz")
}
else if Int(i%5) == 0{
println("Buzz")
}
else {
println("\(i)")
}
}
}
}
var x = TEST1()
x.print()

Resources