I am new to programming with swift and am confused as to why the program does not recognise what I have labeled as "test", claiming it is unresolved.
import UIKit
var rainfall = [38,94,142,149,236,305,202,82,139,222,178,103]
var raindays = [3,6,8,7,12,16,10,8,12,14,11,7]
let crit_raindays = 11
let et_raindays_lessthan_11 = 150
let et_raindays_morethan_11 = 120
let max_h2Ostore = 150
var evap_transpiration: [Int] = []
for i in raindays {
if i <= 11 {
var test = et_raindays_lessthan_11
}
else if i > 11 {
var test = et_raindays_morethan_11
}
evap_transpiration.append(test)
}
The variable test does not seem to be assigned properly, I have no idea why.
Error message: Use of unresolved identifier "test"
When you declare a local variable in Swift, it will be accessible only after its declaration and in the the same scope. In your sample code: the first declaration will be accessible only inside the first if statement, and the second declaration will be accessible only inside the second one.
The correct way is:
for i in raindays {
var test = 0
if i <= 11 {
test = et_raindays_lessthan_11
}
else if i > 11 {
test = et_raindays_morethan_11
}
evap_transpiration.append(test)
}
Even more, you don't need the second if, since if the first one is false, the second one will be always true. So, the code is:
for i in raindays {
var test = 0
if i <= 11 {
test = et_raindays_lessthan_11
}
else {
test = et_raindays_morethan_11
}
evap_transpiration.append(test)
}
Try this:
var test: Int
for i in raindays {
if i <= 11 {
test = et_raindays_lessthan_11
}
else if i > 11 {
test = et_raindays_morethan_11
}
evap_transpiration.append(test)
}
The reason is that you define test inside a block, so the scope is only internal to that block.
You need to declare test outside the for loop. Here is what I have that works.
import UIKit
var rainfall = [38,94,142,149,236,305,202,82,139,222,178,103]
var raindays = [3,6,8,7,12,16,10,8,12,14,11,7]
let crit_raindays = 11
let et_raindays_lessthan_11 = 150
let et_raindays_morethan_11 = 120
let max_h2Ostore = 150
var evap_transpiration: [Int] = []
var test = 0
for i in raindays {
if i <= 11 {
test = et_raindays_lessthan_11
}
else if i > 11 {
test = et_raindays_morethan_11
}
evap_transpiration.append(test)
}
Related
I'm trying to learn how to use Dome and Wren. To do this I've started working on a simple Flappy Bird clone.
The problem I'm having is that I get the error message
Bird does not implement bird_idle
It then points to line 63 in my main class which is shown below:
class Main {
resources=(value){ _resources = value }
bird=(value){ _bird = value }
construct new() {
_resources = Resources.new()
_bird = Bird.new(_resources.birdIdle, _resources.birdFlap, _resources.obstacleTile.width * 2, _resources.obstacleTile.height * 4, 10, 4)
}
init() {}
update() {}
draw(alpha) {
Canvas.cls()
Canvas.draw(_bird.bird_idle, _bird.center.x, _bird.center.y) <-- this is line 63
}
}
var Game = Main.new()
Since I'm new to Wren I don't quite understand what this means seeing as if you look at my bird class below, I should be implementing bird_idle. So what am I doing wrong?
class Bird {
bird_idle=(value){ _bird_idle = value } <-- Right?
bird_flap=(value){ _bird_flap = value }
center=(value){ _center = value }
gravity=(value){ _gravity = value }
force=(value){ _force = value }
velocity=(value){ _velocity = value }
velocityLimit=(value){ _velocityLimit = value }
isGameRunning=(value){ _isGameRunning = value }
construct new(idle, flap, horizontalPosition, verticalPosition, drag, jumpForce) {
_bird_idle = idle
_bird_flap = flap
_center = Vector.new(horizontalPosition + (idle.width * 0.5), verticalPosition + (idle.height*0.5))
_gravity = drag
_force = jumpForce
_velocityLimit = 1000
_isGameRunning = true
}
jump() {
_velocity = -_force
}
isTouchingCeiling() {
var birdTop = _center.y - (_bird_idle.height * 0.5)
if(birdTop < 0) {
return true
}
return false
}
isTouchingGround() {
var birdBottom = _center.y + (_bird_idle.height * 0.5)
if(birdBottom > height) {
return true
}
return false
}
}
You forgot to add the getter:
class Bird {
construct new(idle) {
_bird_idle = idle
}
bird_idle=(value){_bird_idle = value }
bird_idle{_bird_idle} // You need this if you want to access the field _bird_idle.
}
var my_bird = Bird.new("Idle")
my_bird.bird_idle = "Not Idle"
System.print(my_bird.bird_idle) // Output: Not Idle
I am doing this for a class, so I am not looking for someone to code this for me, just for a little guidance. Using Swift3 in Xcode 8. I fixed the previous errors and I think I'm making progress but...
class Cat {
var catName, catBreed, catColor: String
var catAge, catWeight: Int
init(name:String, age:Int, weight:Int, breed:String, color:String)
{
catName = name
catAge = age
catWeight = weight
catBreed = breed
catColor = color
}
func calculateAge (catAge: Int) -> Int
{
var humanYears = 0
if catAge == 1 {
humanYears = 15
} else if catAge == 2 {
humanYears = 24
} else if catAge > 2 {
humanYears = (24 + (catAge * 4))
}
print ("Your cat is \(humanYears) human years old!")
return humanYears
}
func createCats(name: String, age: Int, weight: Int, breed: String, color: String) -> String
{
let humanYears = calculateAge(catAge: age)
let catInfo : String = "\(name) is a \(color) \(breed) who weights \(weight) named \(name), and he is \(humanYears) human years old."
print (catInfo)
return catInfo
}
}
Cat.createCats()
I get an error at Cat.createCats() stating use of instance member 'createCats' on type 'Cat'; did you mean to use a value of type 'Cat' instead?
I have tried putting Cat in the (), I have tried naming all of my variables in there...
As I see in your code , you are re-declaring the variable "humanYears".
One is immediate after Class and second is in the function "calculateAge" . Edit your function "calculate" as below :
func calculateAge (catAge: Int) -> Int {
if catAge == 1 {
humanYears = 15
} else if catAge == 2 {
humanYears = 24
} else if catAge > 2 {
humanYears = (24 + (catAge * 4))
}
return humanYears
}
I figured out what I was doing wrong, thanks to you guys and another post on Stack Overflow that I searched up. Just in case it helps anyone here, I will post my final code below. My biggest issue was that I was trying to call the function before I created an instance of the class. This is not the finished version of the solution, but I was excited that I got it working so I wanted to post it.
Thanks again for all of your help,
class Cat
{
func calculateAge (catAge: Int) -> String
{
var humanYears = 0
if catAge == 1 {
humanYears = 15
} else if catAge == 2 {
humanYears = 24
} else if catAge > 2 {
humanYears = (24 + (catAge * 4))
}
return "Your cat is \(humanYears) human years old!"
}
func createCats(name: String = "Fluffy", age: Int = 1, weight: Int = 3, breed: String = "tabby", color: String = "brown") -> String
{
var catInfo : String
let humanYears = calculateAge(catAge: age)
catInfo = "\(name) is a \(color) \(breed) who weights \(weight) pounds named \(name), and he is \(humanYears) human years old."
print (catInfo)
return catInfo
}
}
let firstCat = Cat()
firstCat.createCats()
let secondCat = Cat()
secondCat.createCats(name: "bob")
I'm having trouble with the following line of code:
var participants = [String]()
var dict = [String: String]()
func createDictionary() {
var hat = participants
var loopCount = 0
for (keyIndex, key) in hat.enumerate() {
var valueIndex: Int {
var index: Int
repeat {
index = Int(arc4random_uniform(UInt32(hat.count)))
loopCount++
print(loopCount)
if loopCount > participants.count + 1000 {
createDictionary()
}
} while index == keyIndex || dict.values.contains(hat[index])
return index
}
dict[key] = hat[valueIndex]
}
}
My goal is for "dict" to contain a dictionary created from "participants". This function will work most of the time, but will sometimes enter into an infinite loop. I was trying to make it so that if it loops more than 1000 times or so, that the function would repeat and try again.
I think the problem is that I can't reset the values for "keyIndex" and "key" because those are "let constants". But I'm not sure.
Is there a way to reset the loop so those values? Or have the entire function retry?
So if anyone is interested, I was able to figure it out. I'm still new to this, so I'm sure others would have been able to figure it out quicker :)
Anyway, I updated the code as follows:
var participants = [String]()
var dict = [String: String]()
func createDictionary() {
var hat = participants
var drawName = [String: String]()
var loopCount = 0
for (keyIndex, key) in hat.enumerate() {
var valueIndex: Int {
var index: Int
repeat {
loopCount++
index = Int(arc4random_uniform(UInt32(hat.count)))
} while index == keyIndex || drawName.values.contains(hat[index]) && loopCount < hat.count + 50
return index
}
drawName[key] = hat[valueIndex]
}
if loopCount > hat.count + 30 {
self.createDictionary()
} else {
dict = drawName
}
}
mathielo was right that I was most likely looking at this the wrong way. Basically I just instructed the loop to not loop too many times, then recalled the function if it had to try too many times to get a value. The above code works without freezing the program.
I've made the following program to simulate the classic card game "War". But when I try to run it, it experiences stack overflow. Why? I thought my algorithm was as effective as it could be. Another weird thing that happens is that 1 out of 10 times the program will finish, returning a VERY low vale for the round count (around 26). The code is as follows:
Firstly, I have a class named Card.
package {
public class Card {
public var cardName:String;
public var suit:String;
public var number:int;
public function Card() {
}
}
}
Then I have the following code:
import flash.utils.getDefinitionByName;
var cardDeck:Array = new Array();
var suits:Array = new Array();
suits = ["Hearts", "Clubs", "Spades", "Diamonds"];
for each (var suit in suits)
{
for (var a = 1; a <= 13; a++)
{
var card:Card = new Card();
card.cardName = suit + a;
card.number = a;
card.suit = suit;
cardDeck.push(card);
}
}
var shuffledCardDeck:Array = new Array();
var randomPos:int = 0;
for (var b = 0; b < 52; b++) {
randomPos = Math.random()*cardDeck.length;
shuffledCardDeck[b] = cardDeck[randomPos];
cardDeck.splice(randomPos, 1);
}
var handOne:Array = new Array();
var handTwo:Array = new Array();
for (var c = 0; c < 26; c++) {
handOne.push(shuffledCardDeck[c]);
}
for (var d = 26; d < 52; d++) {
handTwo.push(shuffledCardDeck[d]);
}
var roundCount:int;
round();
function round() {
roundCount+=1;
var cardOne:Card = handOne[0];
var cardTwo:Card = handTwo[0];
if (cardOne.number < cardTwo.number) {
// Player two wins
handTwo.push(cardOne);
handOne.splice(0, 1);
} else if (cardOne.number > cardTwo.number) {
// Player one wins
handOne.push(cardTwo);
handTwo.splice(0, 1);
} else {
// Draw
handOne.splice(0,1)
handOne.push(cardOne);
handTwo.splice(0,1)
handTwo.push(cardTwo);
}
if (handOne.length == 0 || handTwo.length == 0) {
trace("Good game")
} else {
round();
}
}
trace(roundCount);
Flash runtime’s maximum recursion limit is default 1000, but can be set via the compiler argument default-script-limits. Instead of just recursion, call the function in an interval to prevent such stack overflow. It will be helpful even when you decide to show visually the process to the gamers.
setTimeout(round,50); //in place of round();
Source: http://www.designswan.com/archives/as3-recursive-functions-vs-loop-functions.html
How to merge these 2 collections?
Problem: When an ApplicationID is in listOfPM and listOfPM2, Test2 is null and should be a number
var listOfPM = from d in gbc
select new Tab24PresentationModel
{
ApplicationID = d.ApplicationID,
ApplicationName = d.ApplicationName,
Test1 = d.count,
Test2 = null
};
var listOfPM2 = from d in gbc2
select new Tab24PresentationModel
{
ApplicationID = d.ApplicationID,
ApplicationName = d.ApplicationName,
Test1 = null,
Test2 = d.count
};
var result = listOfPM.Union(listOfPM2);
Have tried removing the Test2 from list of PM and Test1 from listOfPM2 from each and get:
The type 'xxx.Tab24PresentationModel' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.
I can think of ways around this using multiple foreach's.. would like to use Linq!
You need to merge the two objects (with same ApplicationID) manually, no way around that.
Edit - try this:
var list = gbc.Union( gbc2 ).ToLookup( d => d.ApplicationID ).Select( g =>
{
var first = g.First();
var retVal = new Tab24PresentationModel
{
ApplicationID = first.ApplicationID,
ApplicationName = first.ApplicationName,
Test1 = first.count,
Test2 = null
};
var second = g.Skip(1).Take(1).SingleOrDefault();
if( null != second )
{
retVal.Test2 = second.count;
}
return retVal;
} );
Edit 2: hrm, that would only work if you don't want Test1 = null, Test2 = value when only the gbc2 exists. If that's not an issue, you should be ok.
Many thanks for the answers and comments - here is what I came up with.
// take each list in turn and either add or update
var result = new List<Tab24PresentationModel>();
foreach (var t in listOfPM)
{
var a = new Tab24PresentationModel
{
ApplicationID = t.ApplicationID,
ApplicationName = t.ApplicationName,
Test1 = t.Test1
};
result.Add(a);
}
// list2
foreach (var t in listOfPM2)
{
// is this already in result
if (result.Any(x => x.ApplicationID == t.ApplicationID))
{
var existing = result.First(x => x.ApplicationID == t.ApplicationID);
existing.Test2 = t.Test2;
}
else
{
var a = new Tab24PresentationModel
{
ApplicationID = t.ApplicationID,
ApplicationName = t.ApplicationName,
Test2 = t.Test2
};
result.Add(a);
}
}