I created an IF Statement for my XNA game which makes my characters leave their classroom(screen). There are 40 characters, in lines of 10. 'Dest' means destination of the character. This code is in my update method and I have a list of characters in my initialize method:
if (activeCharacter.DestX < 680)
{
activeCharacter.DestX = activeCharacter.DestX + 6;
}
else if (activeCharacter.DestY < 600) //600
{
activeCharacter.DestY = activeCharacter.DestY + 6;
}
else if (activeCharacter.DestY == 600)
{
activeCharacter = classroom[(Random.Next(classroom.Count))];
Console.WriteLine(activeCharacter.DestY);
The aim is to have random characters leave the classroom. When a character from the 1st row leaves, another random character will leave straight after and another depending on if it's from the first row. However if a character from any other row except the 1st leaves, only one character will go.
Can someone please tell me stop this from happening?
Thanks!
DestY is incremented by 6, until it is bigger then or equal to 600. However the final else if only checks for equal to 600.
Changing the final check to:
else if (activeCharacter.DestY >= 600)
Or simply:
else
Will most likely solve your problem.
Related
I am having trouble with an assignment about finding the shortest total path in a grid, while visiting all the correct tiles in the correct order.
We are supposed to emulate manually inputting a word, like when using a controller to write something, and find the least amount of commands (up, down, left, right) needed to do so.
Our input is the grid, parameters, and the word we are supposed to work with.
I store them like this (with example inputs):
Height = 2;
Width = 2;
Content = "ABCC";
Word = "ABC";
grid = new char[Height, Width];
Contents = Content.ToCharArray();
Words = Word.ToCharArray();
int ch = 0;
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
if (ch < Contents.Length)
{
grid[i, j] = Contents[ch];
ch++;
}
}
}
The actual way I compute the shortest path is like so:
public void GridSearch( int a, int FirstX, int FirstY, int PathLength)
{
int NewPath;
int NewX;
int NewY;
int SecondX = 0;
int SecondY = 0;
for (int i = 0; i < Height; i++)
{
for (int j = 0; j < Width; j++)
{
if (grid[i, j] == Words[a])
{
SecondX = i;
SecondY = j;
NewPath = PathLength;
NewPath += Math.Abs(FirstX - SecondX);
NewPath += Math.Abs(FirstY - SecondY);
NewX = SecondX;
NewY = SecondY;
if (a < Words.Length-1)
{
GridSearch(a+1, NewX, NewY, NewPath);
}
else
{
if (FinalPath > NewPath ^ FinalPath == -1)
{
FinalPath = NewPath;
}
}
}
}
}
We are also supposed to "click" when on the correct tile, so I am adding the length of "Words" to the total of commands.
In this case, the shortest path between the letters would be 2 (right, down) and the length is 3, so 5 is the correct answer.
This is also what my program gets, however when I try to send it in, the automated checker says it only passes 1 out of 5 tests, which is an improvement over the 0 that I had until recently, but still not actually good.
Sadly it does not say which inputs it used to make my program fail, and after a day of trying things I am out of ideas on how to fix it, could anyone please point out the, no doubt, obvious mistake I am making and help me fix this program?
EDIT: The assignment instructions as written (since a commenter asked for them):
Some devices allow text entry using a grid of letters. The grid
contains a movable cursor, which begins in the upper-left-hand corner.
Arrow keys move the cursor up, down, left and right and Enter key
chooses the letter under cursor.
For example, if the input grid looks like this:
ABCDEFGH
IJKLMNOP
QRSTUVWX
YZ
we can enter the text "HELLO" with the following sequence of keys
(which is only one of many possible sequences):
right
right
right
right
right
right
right
Enter
left
left
left
Enter
down
left
Enter
Enter
right
right
right
Enter
Write a program that for a given grid (which may contain both
lowercase and uppercase letters) and text (which may also contain
non-alphabetic characters) determines and writes out the minimum
number of keystrokes required to enter the given text.
Caution: Each letter may appear more than once in the grid!
The input begins with numbers indicating the width and height of the
grid (each on its own line).
A single line follows containing the contents of the entire grid (in
row-major order, i.e. with one row after another).
The rest of the lines contain the text to be entered. ! You should
ignore any characters in the text that are not present in the grid.
Example:
Input:
3
3
ABCBFECDF
ABCDEFA
Output:
15
In this example, the grid has the form
ABC
BFE
CDF
It is possible to enter the text ABCDEFA in many possible ways; 15
keystrokes is the length of the shortest of these.
Revising my previous answer, it is likely that you have not counted the "enter" keystroke. I.e. you should add one to the candidate path length for each letter:
...
NewY = SecondY;
**NewPath++;**
if (a < Words.Length - 1)
...
This gives a correct length of 15 keypresses on your example set of "ABCBFECDF" / "ABCDEFA".
Note that this type of code greatly benefits from a type that represents a pair of x/y coordinate, like a Point or Vector2i, so you don't have to repeat a bunch of calculations for both x and y coordinates. I would also recommend following common coding conventions like
declare local variables in the smallest possible scope, not at the top of the method
Use "camelCasing" for local variables
Prefer pure methods whenever possible, i.e.
I would still recommend reading up on Djikstra or A*, since these should be more generally applicable and be more efficient.
For some reason this code makes the numbers jump around in place value.
For an ex.
If I add the numbers up to up to 10 when I subtract one time it will change to 90 if I subtract again it goes to 80.
If I start adding again 90 turns into 01...
So somewhere in my code I must be telling it to do this...
I have tried a few different things but the same thing keeps happening.
int x;
int y;
Console.WriteLine("X:" + (x=0) + "Y:" + (y=0));
//Change Coordinates
while(true){
ConsoleKey key = Console.ReadKey().Key;
Console.SetCursorPosition(Console.CursorLeft, Console.CursorTop -1);
Console.WriteLine("X:"+x +"Y:"+y);
if (key == ConsoleKey.UpArrow){
y=y+1;
}
else if (key == ConsoleKey.DownArrow){
y=y-1;
}
}
You need
Console.WriteLine($"X:{x,2} Y:{y,2}");
You were not printing y for a start. But your main problem was that you were leaving old characters in the line once you had got to 2 digits. THis forces the output to be always 2 digits wide
I'm aware (from similar posts) that infinite while loops are notorious for causing Unity3d to crash. I'm tring to impliment a while loop within something I'm working on, which I'm fairly sure isn't 'infinite', yet causes the game to crash.
The idea of the logic is to check a list of integers for consecutive numbers and use that as the basis to apply a bonus. The list contains 'effective shots', and has a new int added every time a shot is fired - the more consecutive effective shots, the higher the bonus.
Here's what I have:
int count = 0;
int firstItem = 0;
int multiples = 3;
int currentMultiple = 0;
int bonusX = 0;
foreach (int i in effectiveShots)
{
if (count == 0)
{
firstItem = i;
count = 1;
}
else if (i == firstItem + count)
{
count++;
}
}
while (count >= multiples)
{
currentMultiple = multiples;
if (count == currentMultiple + multiples)
{
bonusX += 1;
}
if (bonusX > 10 || gameOver)
break;
UnityEngine.Debug.Log(bonusX);
}
The logic to check for consective entries in the effectiveShots list was taken from #Jon Skeet's answer here. Though this appears to work, I think that this may be the issue. As soon as a shot is missed, count needs to be reset. Any ideas or suggestions?
The while loop should then be entered once the count of consecutive effective shots has reached the first multiple, i.e. 3 shots. Then, for every set of consequtive effective shots thereafter, increment the bonus, for example:
3 shots: bonusX = 1
6 shots: bonusX = 2
9 shots: bonusX = 3
12 shots: bonusX = 4
and repeat this until `count` is no longer >= 3, i.e. the player missed a shot.
The issue is that as soon as I hit 3 consequtive shots and enter this loop, the game crashes. I dont think I would call this an infinite loop, since missing a shot - setting count == 0 - would mean the while conditions are no longer true, so drop out of the loop (I think?). I also added an additional check to break out of the loop under certain circumstances, but this doesnt make a difference.
If you are able to give a steer as to how to fix this crashing, or have a suggestion on a better approach in general, it would be appreciated!
Nothing in your while loop changes the value of either count or multiples and so the condition will always evaluate to the same value => Infinite loop
else if (userAnswer.Equals("2"))
{
blankspace();
Console.WriteLine("How many squares would you like to see? ");
double num = Convert.ToInt32(Console.ReadLine());
while (0 >= num)
{
Console.WriteLine(num * num);
}
}
My problem is that I don't know where to go from here. I had previously been able to output just one square, but I need to know how to output a list instead of just a single number.
Here's what your code currently says:
If the user input is 2:
Add a blank space -- Console.WriteLine() ??
Ask how many squares they want
Get their input
Get the square of their input while their input is less than 0
As you can see, things go reasonably well until you hit the loop. What I think you're really trying to do is this:
Get their input
Generate that number of perfect squares
To accomplish this, your loop should look something more like this:
for (int i = 1; i <= num; i++)
{
Console.WriteLine(i * i);
}
This says the following:
Start at 1
square the current number (i)
add 1 to the number (i)
repeat until you reach the user's number (num)
So if the input is 3, you'll get 1, 2, and 3 squared. If you want to square specific numbers the logic needs to change a bit, but this should at least accomplish your basic goal.
EDIT: If you want to keep the while loop, all you really need to do is add num-- (subtract 1 from num) and switch the comparison to 0 <= num (assuming you want positive numbers) to stop the infinite loop. This will generate the squares in descending order (3, 2, 1) but accomplish the same result.
You're hitting an infinite loop because num never changes so if it doesn't start at 0, it can never be 0.
I've searched online for a diff algorithm but none of them do what I am looking for. It is for a texting contest (as in cell phone) and I need the entry text compared to the master text recording the errors along the way. I am semi-new to C# and I get most of the string functions and didn't think this was going to be that hard of a problem, but alas I just can't wrap my head around it.
I have a form with 2 rich-text-boxes (one on top of the other) and 2 buttons. The top box is the master text (string) and the bottom box is the entry text (string). Every contestant is sending a text to an email account, from the email we copy and paste the text into the Entry RTB and compare to the Master RTB. For each single word and single space counts as a thing to check. A word, no matter how many errors it has, is still 1 error. And for every error add 1 sec. to their time.
Examples:
Hello there! <= 3 checks (2 words and 1 space)
Helothere! <= 2 errors (Helo and space)
Hello there!! <= 1 error (extra ! at end of there!)
Hello there! How are you? <= 9 checks (5 words and 4 spaces)
Helothere!! How a re you? <= still 9 checks, 4 errors(helo, no space, extra !, and a space in are)
Hello there!# Ho are yu?? <= 3 errors (# at end of there!, no w, no o and extra ? (all errors are still under the 1 word)
What I have so far:
I've created 6 arrays (3 for master, 3 for entry) and they are
CharArray of all chars
StringArray of all strings(words) including the spaces
IntArray with length of the string in each StringArray
My biggest trouble is if the entry text is wrong and it's shorter or longer than the master. I keep getting IndexOutOfRange exceptions (understandably) but can't fathom how to go about checking and writing the code to compensate.
I hope I have made myself clear enough as to what I need help with. If anyone could give some code examples or something to shoot me in the right path would be very helpful.
Have you looked into the Levenshtein distance algorithm? It returns the number of differences between two strings, which, in your case would be texting errors. Implementing the algorithm based off the pseudo-code found on the wikipedia page passes the first 3 of your 4 use cases:
Assert.AreEqual(2, LevenshteinDistance("Hello there!", "Helothere!");
Assert.AreEqual(1, LevenshteinDistance("Hello there!", "Hello there!!"));
Assert.AreEqual(4, LevenshteinDistance("Hello there! How are you?", "Helothere!! How a re you?"));
Assert.AreEqual(3, LevenshteinDistance("Hello there! How are you?", "Hello there!# Ho are yu??")); //fails, returns 4 errors
So while not perfect out of the box, it is probably a good starting point for you. Also, if you have too much trouble implementing your scoring rules, it might be worth revisiting them.
hth
Update:
Here is the result of the string you requested in the comments:
Assert.AreEqual(7, LevenshteinDistance("Hello there! How are you?", "Hlothere!! Hw a reYou?"); //fails, returns 8 errors
And here is my implementation of the Levenshtein Distance algorithm:
int LevenshteinDistance(string left, string right)
{
if (left == null || right == null)
{
return -1;
}
if (left.Length == 0)
{
return right.Length;
}
if (right.Length == 0)
{
return left.Length;
}
int[,] distance = new int[left.Length + 1, right.Length + 1];
for (int i = 0; i <= left.Length; i++)
{
distance[i, 0] = i;
}
for (int j = 0; j <= right.Length; j++)
{
distance[0, j] = j;
}
for (int i = 1; i <= left.Length; i++)
{
for (int j = 1; j <= right.Length; j++)
{
if (right[j - 1] == left[i - 1])
{
distance[i, j] = distance[i - 1, j - 1];
}
else
{
distance[i, j] = Min(distance[i - 1, j] + 1, //deletion
distance[i, j - 1] + 1, //insertion
distance[i - 1, j - 1] + 1); //substitution
}
}
}
return distance[left.Length, right.Length];
}
int Min(int val1, int val2, int val3)
{
return Math.Min(val1, Math.Min(val2, val3));
}
You need to come up with a scoring systems that works for you're situation.
I would make a word array after each space.
If a word is found on the same index +5.
If a word is found on the same index +-1 index location +3 (keep a counter how much words differ to increase the +- correction
If a needed word is found as part of another word +2
etc.etc. Matching words is hard, getting up with a rules engine that works is 'easier'
I once implemented an algorithm (which I can't find at the moment, I'll post code when I find it) which looked at the total number of PAIRS in the target string. i.e. "Hello, World!" would have 11 pairs, { "He", "el", "ll",...,"ld", "d!" }.
You then do the same thing on an input string such as "Helo World" so you have { "He",...,"ld" }.
You can then calculate accuracy as a function of correct pairs (i.e. input pairs that are in the list of target pairs), incorrect pairs (i.e. input pairs that do not exists in the list of target pairs), compared to the total list of target pairs. Over long enough sentences, this measure would be very accurate fair.
A simple algorithm would be to check letter by letter. If the letters differ increment the num of errors. If the next pairing of letters match, its a switched letter so just continue. If the messup matches the next letter, it is an omission and treat it accordingly. If the next letter matches the messed up one, its an insertion and treat it accordingly. Else the person really messed up and continue.
This doesn't get everything but with a few modifications this could become comprehensive.
a weak attempt at pseudocode:
edit: new idea. look at comments. I don't know the string functions off the top of my head so you'll have to figure that part out. The algorithm kinda fails for words that repeat a lot though...
string entry; //we'll pretend that this has stuff inside
string master; // this too...
string tempentry = entry; //stuff will be deleted so I need a copy to mess up
int e =0; //word index for entry
int m = 0; //word index for master
int errors = 0;
while(there are words in tempentry) //!tempentry.empty() ?
string mword = the next word in master;
m++;
int eplace = find mword in tempentry; //eplace is the index of where the mword starts in tempentry
if(eplace == -1) //word not there...
continue;
else
errors += m - e;
errors += find number of spaces before eplace
e = m // there is an error
tempentry = stripoff everything between the beginning and the next word// substring?
all words and spaces left in master are considered errors.
There are a couple of bounds checking errors that need to be fixed here but its a good start.