Swift variable inside variable for iteration - swift

I have very redundant code that I need to simplify as I am expanding and I am not sure how to do this. I have a lot of buttons that get updated and images changed quite often. Depending on what button is lit up and what is going on in the program, I change the state of a lot of buttons at once. I would like to create a function that can iterate multiple parts of the function. . .for example, below is a chunk of code that is repeated 1 time per button that I have, which at this point is going to be 48. . .
if sharedData.Channel1Mute != nil {
if sharedData.Channel1Mute == "True" {
self.Channel1Button.setImage(UIImage(named: "w1"), for:UIControlState())
}
else {
self.Channel1Button.setImage(UIImage(named: "g1"), for:UIControlState())
}
if sharedData.Channel2Mute != nil {
if sharedData.Channel2Mute == "True" {
self.Channel2Button.setImage(UIImage(named: "w2"), for:UIControlState())
}
else {
self.Channel2Button.setImage(UIImage(named: "g2"), for:UIControlState())
}
...
...
ect
...
This isn't correct coding but I would like this to function something like this which would be MUCH shorter and scalable . . .
for NUMBER in 1...48 {
if sharedData.Channel[NUMBER]Mute != nil {
if sharedData.Channel[NUMBER]Mute == "True" {
self.Channel[NUMBER]Button.setImage(UIImage(named: "w[NUMBER]"), for:UIControlState())
}
else {
self.Channel[NUMBER]Button.setImage(UIImage(named: "g[NUMBER]"), for:UIControlState())
}
}
This is frustrating because my current code does the exact same thing like 48 times but I have to rewrite the whole code again with each number in the if statement in each copy.

Related

When to use keyword return in Scala

I learned early on that there is no reason to use the return keyword in Scala (as far as I'm aware). That being said I found an example where simply changing adding the return keyword made my function work, where it previously didn't.
The code in question comes from my solution to the Advent of Code day 7 challenge.
def containsShinyGoldBag(bagContents: Map[String, List[String]], currentBag: String): Boolean = {
val contents = bagContents(currentBag)
if (bagContents(currentBag).contains("shiny gold") ) {
// Base Case: Bag Found in list of bags
true
} else if (contents == List.empty){
// Base Case: Dead End
false
} else {
// Continue searching down list
// Ideal solution ( gives same result as the working solution without return keyword )
// for (b <- contents) containsShinyGoldBag(bagContents, b)
// Working solution
for (b <- contents) {
if (containsShinyGoldBag(bagContents, b)) {
println(s"Found one! $b inside a $currentBag")
return true // <--- culprit
}
else false
}
false
}
}
// In the main function
var count = 0
for (bag <- bagContents.keys) {
if (containsShinyGoldBag(bagContents, bag)) {
count = count + 1
}
}
println(s"There are $count way to bring a shiny gold bag!")
When I run the code without return I end up with count = 7, which is the number of bags directly containing a shiny gold bag, rather than the correct number which counts bags that contain a shiny gold bag somewhere inside of one of their other bags down the line.
A function returns the value of the last expression it evaluates; in your case that will be one of:
true after if (bagContents(currentBag).contains("shiny gold") );
false after else if (contents == List.empty);
the last false.
true is not in such a position, so you need return to, well, make the function return it. Otherwise it's evaluated and ignored because you don't do anything with it. So is else false in the same for, actually, it can be removed without changing the meaning.
The alternative to avoid return here is
contents.exists(b => containsShinyGoldBag(bagContents, b))

avoid Number Format Exception while parseing to integer

I'm trying to check if the text area has only numbers or not, but i got this problem Number Format Exception while clicking on the Edit Button, any Ideas how to solve it.
ArrayList<CarRental> List= CarRent.getList();
String text=EditTF.getText().trim();
char [] txt=text.toCharArray();
Character a=null;
boolean isnotDigit=false;
int index;
for(int i=0;i<txt.length;i++)
{
if(!a.isDigit(txt[i]))
{
isnotDigit=true;
break;
}
else
{
isnotDigit=false;
continue;
}
}
if(isnotDigit==false)
{
index=Integer.parseInt(text.trim());
PrintList_Summary.setIndex(index);
EditDetails.nameTF.setText(List.get(index).getName());
EditDetails.sizeCOB.setSelectedItem(List.get(index).getSize());
EditDetails.daysTF.setText(List.get(index).getDays()+"");
if(List.get(index).getCarType().equalsIgnoreCase("Luxury"))
{
EditDetails.LuxRB.setSelected(true);
}
else if(List.get(index).CarType().equalsIgnoreCase("Truck"))
{
EditDetails.truckRB.setSelected(true);
}
if(List.get(index).getDriver())
{
EditDetails.yesRB.setSelected(true);
}
else
{
EditDetails.noRB.setSelected(true);
}
EditDetails.Frame.setVisible(true);
}
else
{
JOptionPane warning=new JOptionPane();
warning.showMessageDialog(null,"Element Index CAN ONLY be an INTEGER.","Invalid Index",WIDTH);
}
Use try catch to handle exceptions.
try{
index = Integer.parseInt(text.trim());
//etc
}catch(NumberFormatException ex){
//whatever happens when the exception is thrown (not an integer)
}
You can use that instead of the if(!a.isDigit(txt[i])) for. If it can't be parsed, then it will go intro the catch.
Also, you can use !isnotDigit instead of isnotDigit == false.
I would use String.matches() for your check instead of doing it yourself. Scrap the for-loop and change your if-condtion from isnotDigit==false to text.matches("[0-9]+"). After this Integer.parseInt(text) should definitly work.
This uses a regular expression to check if your string consists only of digits and at least one digit. For further reference on regular expression see the javadoc for Pattern.

Why isn't my score recording on the playerprefs is there GetFloat method?

Why isn't my score recording on the playerprefs ? is there GetFloat method? Can anyone help me to post the least score of my game it just like the most least seconds will get the best time record ever
var myTimer: float = 0;
var GUITimer: GUIText;
function Start() {
}
function Update() {
GUITimer.text = "Time: " + myTimer;
if (myTimer > -1) {
myTimer += Time.deltaTime;
}
}
function OnTriggerEnter(other: Collider) {
if (other.tag == "FinishLine") {
SaveTime();
}
}
function OnGUI() {
GUI.Label(Rect(10, 10, 500, 200), myTimer.ToString());
}
function SaveTime() {
if (myTimer < PlayerPrefs.GetInt("JeepneyScore3")) {
PlayerPrefs.SetInt("JeepneyScore3", myTimer);
}
Application.LoadLevel("Levels");
}
I see three problems:
First, you're tracking a float, but calling GetInt() and SetInt(). Keep your data types consistent. You should either round/floor/etc, or call GetFloat() and SetFloat().
Second, you're not calling Save(), which means your changes will never write to disk. You might consider something like this:
PlayerPrefs.SetFloat("JeepneyScore3", myTimer);
PlayerPrefs.Save();
Third, you're not handling the case where no data exists. You could check for existing data with HasKey(), but in this case it's simpler to rely on the second form of GetFloat(). The default form, which you're calling, returns zero if the requested key isn't set:
//returns value of "foo", or zero if no such value
var prevBest = PlayerPrefs.GetFloat("foo");
If you're looking for a time below the player's previous best, but the default "best" is already 0.0, you're going to have a hard time beating that time.
You can instead provide your own default value:
//returns value of "foo", or ten thousand if no such value
var prevBest = PlayerPrefs.GetFloat("foo", 10000.0);
Finally, you should make sure that SaveTime() is actually being called at the appropriate time. You could add a simple debug line, like this:
Debug.Log("SaveTime was called");
And then make sure that's showing up. If not, you need to fix your collision check.

insertion sort on linked list

//I wrote java code for insertion method on doubly linked list but there is a infinite loop //when I run it. I'm trying to find a bug, but have not found so far. any suggestions?
//it is calling a helper function
public IntList insertionSort ( ) {
DListNode soFar = null;
for (DListNode p=myHead; p!=null; p=p.myNext) {
soFar = insert (p, soFar);
}
return new IntList (soFar);
}
// values will be in decreasing order.
private DListNode insert (DListNode p, DListNode head) {
DListNode q=new DListNode(p.myItem);
if(head==null){
head=q;
return head;
}
if(q.myItem>=head.myItem){
DListNode te=head;
q.myNext=te;
te.myPrev=q;
q=head;
return head;
}
DListNode a;
boolean found=false;
for(a=head; a!=null;){
if(a.myItem<q.myItem){
found=true;
break;
}
else{
a=a.myNext;
}
}
if(found==false){
DListNode temp=myTail;
temp.myNext=q;
q.myPrev=temp;
myTail=q;
return head;
}
if(found==true){
DListNode t;
t=a.myPrev;
a.myPrev=q;
t.myNext=q;
q.myPrev=t;
q.myNext=a;
}
return head;
}
Your code is a bit hard to read through but I noticed a few problems
First:
handling the case where you are inserting a number at the head of the list:
if(q.myItem>=head.myItem){
DListNode te=head;
q.myNext=te;
te.myPrev=q;
q=head;
return head;
}
specifically the line q=head; and the return. q=head can be removed, and it should return q not head because q is the new head. I think what you meant to do was head=q; return head;. The current code will essentially add the new node on the front but never return the updated head so they will "fall off the edge" in a way.
Second:
I am assuming myTail is some node reference you are keeping like myHead to the original list. I don't think you want to be using it like you are for the sorted list you are constructing. When you loop through looking for the place to insert in the new list, use that to determine the tail reference and use that instead.
DListNode lastCompared = null;
for(a=head; a!=null; a=a.myNext) {
lastCompared = a;
if(a.myItem<q.myItem) {
break;
}
}
if( a )
{
// insert node before a
...
}
else
{
// smallest value yet, throw on the end
lastCompared.myNext = q;
q.myPrev = lastCompared;
return head;
}
Finally make sure myPrev and myNext are being properly initialized to null in the constructor for DListNode.
disclaimer I didn't get a chance to test the code I added here, but hopefully it at least gets you thinking about the solution.
A couple stylistic notes (just a sidenote):
the repeated if->return format is not the cleanest in my opinion.
I generally try and limit the exit points in functions
There are a lot of intermediate variables being used and the names are super
ambiguous. At the very least try and use some more descriptive
variable names.
comments are always a good idea. Just make sure they don't just explain what the code is doing - instead try and
convey thought process and what is trying to be accomplished.

do something when counter = x

I have a counter that make counter++ every time one image touches another image.
Now what I want to do is: if counter=2; do something, but I always get an error:
Assignment makes pointer from integer without a cast
Here is a part of the code:
-(void)checkcollision {
if(CGRectIntersectsRect(flakeImage.frame, viewToRotate.frame)) {
counter++;
}
}
-(void)checknumber {
if(counter=2) {
viewToRotate.alpha=0;
}
}
Are you perhaps doing this:
if (counter = 2) {
// Do something.
}
This is a common error in if statements. The correction would be:
if (counter == 2) { // Note the "==", instead of "="
// Do something.
}
This is just a guess though - I would need to see some more information about the error, or about what you want to do.
EDIT
Ah - have seen your newly posted code, confirming what I stated above. Your code reads that you are trying to assign the value '2' to counter in the if statement. You want the == to make this a check for equality.