I have a game kinda like minecraft, but from a top down perspective, adding blocks is done by when the player left-clicks it adds the block at the specified position, right-clicking on a placed block deletes the block.
The problem I was having was that when the player left-clicks it adds the block and its position to a list (for saving to XML later), so the logical conclusion is that when the player right-clicks it removes said block from the game, and its position from its list.
This is the method that I was using which generated lag:
for (int b = 0; b < game.blocklist.Count; b++)
{
for (int v = 0; v < game.blockpos1.Count; v++)
{
if (game.blocklist[b].visible == true)
{
if (game.cursor.boundingbox.Intersects(game.blocklist[b].blockrectangle) && mousestate.RightButton == ButtonState.Pressed && game.player.Builder == true)
{
if (game.blocklist[b].blockposition.X == game.blockpos1[v].X && game.blocklist[b].blockposition.Y == game.blockpos1[v].Y)
{
game.blockpos1.RemoveAt(v);
game.blocklist.RemoveAt(b);
break;
}
}
}
}
}
Now this is the method that I replaced it with which reduces lag immensely and still achieves the same effect I want:
for (int b = 0; b < game.blocklist.Count; b++)
{
if (game.blocklist[b].visible == true)
{
if (game.cursor.boundingbox.Intersects(game.blocklist[b].blockrectangle) && mousestate.RightButton == ButtonState.Pressed && game.player.Builder == true)
{
if (game.blocklist[b].blockposition.X == game.blockpos1[b].X && game.blocklist[b].blockposition.Y == game.blockpos1[b].Y)
{
game.blockpos1.RemoveAt(b);
game.blocklist.RemoveAt(b);
break;
}
}
}
}
Why does this generate so much lag? I just need clarification as to what I did wrong so I don't do it again.
for (int b = 0; b < game.blocklist.Count; b++)
{
for (int v = 0; v < game.blockpos1.Count; v++)
{
if (game.blocklist[b].visible == true)
{
in this version, basically for every item in blocklist ( X ) whether it was visible or not you are iterating every item in blockpos1 (Y). So you do X * Y loops. You then reduced it to X loops and only evaluated visible items.
Given the way the code is written in the question, I'd check these two things before even trying to loop
mousestate.RightButton == ButtonState.Pressed && game.player.Builder == true
because they will never change during those loops. so if they aren't true to start with, don't even bother looping.
Also as Preseton says in the comments, no need to compare things to true.... you only need to do
mousestate.RightButton == ButtonState.Pressed && game.player.Builder
and
if (game.blocklist[b].visible)
Related
In the beginning i will tell that I'm new with C# and Programming. Trying to learn as much as i can alone.
My first learning project is simple. Moving trough array 10x10 by using "W, S, A, D". It is "game" which is letting user to move his character trough array. The problem is that i want "my character" to move as long as his position will be out of range. So i think i'm trying to make infitive loop which is printing position and lets moving forward. If i'm using for example do{}while(true), position is changing all the time after pressing one key. I'm looking for suggestion how should i construct loop for this kind of "movement".
I'm attaching my code which is responsible for moving character.
int axisx = 0;
int axisy = 0;
var movement = Console.ReadKey();
int[,] level = new int[10, 10];
if (movement.Key.ToString() == "W"){axisy = axisy+1;}
else if (movement.Key.ToString() == "S"){axisy = axisy-1;}
else if (movement.Key.ToString() == "D"){axisx = axisx+1;}
else if (movement.Key.ToString() == "A"){axisx = axisx-1;}
Console.WriteLine("{2} is on position:{0},{1}", axisx, axisy, Player1.getBuilderName());
if (movement.Key == ConsoleKey.Escape)
{
Console.WriteLine("You pressed Escape, Goodbye");
}
You can use a while(true) loop:
int axisx = 0;
int axisy = 0;
while (true)
{
var movement = Console.ReadKey();
if (movement.KeyChar == 'W' || movement.KeyChar == 'w')
{
axisy += 1;
}
else if (movement.KeyChar == 'S' || movement.KeyChar == 's')
{
axisy -= 1;
}
else if (movement.KeyChar == 'D' || movement.KeyChar == 'd')
{
axisx += 1;
}
else if (movement.KeyChar == 'A' || movement.KeyChar == 'a')
{
axisx -= 1;
}
Console.WriteLine("{2} is on position:{0},{1}", axisx, axisy, Player1.getBuilderName());
if (movement.Key == ConsoleKey.Escape)
{
Console.WriteLine("You pressed Escape, Goodbye");
break;
}
}
The break; in the ConsoleKey.Escape block will get you out of the loop.
You can also use movement.KeyChar instead of movement.Key.ToString(), strings are immutable in .NET, so every time you do a ToString() you are creating a new string.
Once again I cannot find a solution myself (I have tried using Array.IndexOf(db, accnum) with a pos > -1 return boolean, but have reverted to this loop after I couldn't make it work).
So, I thought using db.Length would leave 'a' at the length of all the non-null elements in the array, however it seems to count the whole array, meaning that when the loop reaches a null element it causes an error. Is there a way to halt the loop count when it runs out of objects in the array?
void withdrawal()
{
int accnum;
double withdrawal;
//get and parse input details
accnum = int.Parse(tbNameEnt.Text);
withdrawal = double.Parse(tbBalaEnt.Text);
//check if account exists within existing objects
int a = db.Length;
for (int i = 0; i < a; i++)
{
if (db[i].GetAccNo() == accnum)
{
pos = i;
//deduct from balance
db[pos].SetBalance(db[pos].GetBalance() - withdrawal);
WithMess(); //success message
hide_form();
MakeWith2.Visible = false;
show_menu();
break;
}
else if ((db[i].GetAccNo() != accnum) && (i == db.Length - 1))
{
//account doesn't exist message
MessageBox.Show("Account does not exist");
}
}
}
If there are null items that pad the array.. break out of the loop when you reach one:
for (int i = 0; i < a; i++) {
if (db[i] == null)
break;
// the rest
Alternatively, use LINQ to filter the null items out:
foreach (var item in db.Where(x => x != null)) {
// loop here
}
I am comparing two excel files and for my current test - I have two files exactly the same each containing one column and 5 rows. When I check if they are equal or not, it fails and says that one of the files has added items to it.
Not sure if I am checking something the wrong way:
bool areEqual = false;
if (fileB.excelRows.Count() == fileA.excelRows.Count())
{
int i = 0;
while ((i < fileB.excelRows.Count()) && (fileB.excelRows[i] == fileA.excelRows[i]))
{
i += 1;
}
if (i == fileB.excelRows.Count())
{
areEqual = true;
}
}
if (areEqual)
MessageBox.Show("The files are the same");
else
{
....
}
Use the SequenceEqual method on excelRows[i].rowHash.
Instead of:
while ((i < fileB.excelRows.Count()) && (fileB.excelRows[i] == fileA.excelRows[i]))
Change it to:
while ((i < fileB.excelRows.Count()) &&
(fileB.excelRows[i].rowHash.SequenceEqual(fileA.excelRows[i].rowHash)))
I created 10 x 10 TextBoxes and the user should input the words into the relevant TextBoxes for the position of the words. And I save everything into a textfile like this:
Then on WPF side , I read the textfile and populate the TextBoxes in a panel but the problem is that the crossword puzzle has down and across hints that lead you to the answer and each hint will have a number to indicate which is which. However I can't think of a way to link the number's puzzle number to the hints down and across number. This is how it looks like now:
Notice the numbers (I edited them in paint to visualize what I want) beside the across and down, I need that numbers to be displayed.
In my database, I stored the location of the file in a table, and the hints and answer in another table like this:
And this is the hints (across and down) and answer:
I am using Entity framework lambda expressions to retrieve the across and down.
Appreciate any help on this to link the assign the numbers to Across and Down from the puzzle.
This is my code to display the puzzle :
protected void Across()
{
IList<ModelSQL.puzzlecontent> lstAcross = daoPuzzleContent.GetAcross();
foreach (ModelSQL.puzzlecontent lista in lstAcross)
{
Label tbA = new Label();
tbA.Content = lista.Hint;
tbA.Width = Double.NaN;
tbA.BorderBrush = Brushes.CadetBlue;
tbA.BorderThickness = new Thickness(2);
stackPanel1.Width = Double.NaN;
stackPanel1.Children.Add(tbA);
words.Add(lista.Answer);
}
}
protected void AddPuzzle()
{
// foldername of the txt file.
// using (StreamReader reader = File.OpenText((#daoWordPuzzle.GetfileURL())))
string[] fileData = File.ReadAllLines(#"C:\Users\apr13mpsip\Desktop\OneOrganizer\OneOrganizer\WordPuzzle\educational.txt");
string[] lineValues;
int row = 0;
int col;
int hint = 1;
string[][] rowcol = new string[fileData.Length][];
foreach (string line in fileData)
{
lineValues = line.Split(new string[] { "," }, StringSplitOptions.None);
rowcol[row] = new string[lineValues.Length];
col = 0;
foreach (string value in lineValues)
{
rowcol[row][col] = value;
col++;
}
row++;
}
for (int i = 0; i < rowcol.GetLength(0) ; i++)
{
for (int j = 0; j < rowcol[i].GetLength(0) ; j++)
{
int iadd = i+1 < rowcol.GetLength(0) ? i+1 : 100;
int iminus = i-1 >= 0 ? i-1 : 100;
int jadd = j+1 < rowcol.GetLength(0) ? j+1 : 100;
int jminus = j-1 >= 0 ? j-1 : 100;
var self = rowcol[i][j]; // current value
var top = iminus == 100 ? "" : rowcol[iminus][j];
var bottom = iadd == 100 ? "" : rowcol[iadd][j];
var left = jminus == 100 ? "" : rowcol[i][jminus];
var right = jadd == 100 ? "" : rowcol[i][jadd];
//ACROSS HORIZONTAL
if (
(!String.IsNullOrEmpty(self) && !String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(top) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && !String.IsNullOrEmpty(right) && String.IsNullOrEmpty(bottom) && !String.IsNullOrEmpty(top) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && !String.IsNullOrEmpty(right) && String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(top) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && !String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && !String.IsNullOrEmpty(top) && String.IsNullOrEmpty(left))
)
{
wordAcross = "";
for (int k = 0; k < 10; k++)
{
wordAcross += rowcol[i][k];
if (k == 9)
{
puzzlewordAcross.Add(wordAcross);
// print hello and live
}
}
}
//DOWN VERTICAL
if (
(!String.IsNullOrEmpty(self) && String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(top) && !String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(top) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && !String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(top) && String.IsNullOrEmpty(left))
)
{
wordDown = "";
for (int k = 0; k < 10; k++)
{
wordDown += rowcol[k][j];
if (k == 9)
{
puzzlewordDown.Add(wordDown);
// print holy and leducated
}
}
}
//Check Top , Left , Bottom , Right value.
if (
(!String.IsNullOrEmpty(self) && String.IsNullOrEmpty(top) && !String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && String.IsNullOrEmpty(top) && String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && !String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && !String.IsNullOrEmpty(top) && !String.IsNullOrEmpty(right) && String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && !String.IsNullOrEmpty(top) && !String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && String.IsNullOrEmpty(top) && String.IsNullOrEmpty(right) && !String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(left)) ||
(!String.IsNullOrEmpty(self) && String.IsNullOrEmpty(top) && !String.IsNullOrEmpty(right) && String.IsNullOrEmpty(bottom) && String.IsNullOrEmpty(left))
)
{
TextBox tbox = new TextBox();
tbox.Height = 50;
tbox.Width = 50;
tbox.Text = hint.ToString();
wrapPanel1.Children.Add(tbox);
tbox.GotFocus += (source, e) =>
{
if (!string.IsNullOrEmpty(tbox.Text))
{
string Str = tbox.Text.Trim();
double Num;
bool isNum = double.TryParse(Str, out Num);
if (isNum)
tbox.Text = "";
}
else
{
tbox.Text = "";
}
};
hint++;
}
else
{
TextBox tbox2 = new TextBox();
tbox2.Height = 50;
tbox2.Width = 50;
if (String.IsNullOrEmpty(self))
{
tbox2.Background = Brushes.Black;
tbox2.Focusable = false;
}
wrapPanel1.Children.Add(tbox2);
}// end of top bottom left right.
}
}
} // End of AddPuzzle()
Code to display Across and Down :
protected void Down()
{
IList<ModelSQL.puzzlecontent> lstDown = daoPuzzleContent.GetDown();
foreach (ModelSQL.puzzlecontent listd in lstDown)
{
Label tbD = new Label();
tbD.Content = listd.Hint;
tbD.Width = Double.NaN;
tbD.BorderBrush = Brushes.CadetBlue;
tbD.BorderThickness = new Thickness(2);
stackPanel2.Width = Double.NaN;
stackPanel2.Children.Add(tbD);
}
}
protected void Across()
{
IList<ModelSQL.puzzlecontent> lstAcross = daoPuzzleContent.GetAcross();
foreach (ModelSQL.puzzlecontent lista in lstAcross)
{
Label tbA = new Label();
tbA.Content = lista.Hint;
tbA.Width = Double.NaN;
tbA.BorderBrush = Brushes.CadetBlue;
tbA.BorderThickness = new Thickness(2);
stackPanel1.Width = Double.NaN;
stackPanel1.Children.Add(tbA);
words.Add(lista.Answer);
}
}
You may need to re-define your data model here because I think you have failed at the first hurdle - systems analysis. It catches us all out when we just want to write code and always means a big refactor.
Think about your domain here. Crossword puzzles. If we are a reading a newspaper puzzle and you dont know the answer to a clue, what do you say when you you ask a friend.
6 letters, clue is 'blah blah'
...followed by any letters that you already know.
Now we know that the puzzle needs to know how many letters in each answer and that each answer needs a clue. We also know that letters are hidden until you fill them out but we need to know the right answer at some point.
How does the puzzle present itself in the back of the paper? Clues are not written as 1,2,3 etc. They are 4 down, 1 across etc. Now we know that you need some position data stored.
You can achieve this is 2 ways.
1. Have each clue as its own entry complete with text
Clue '1'
Direction 'Across'
Position '1,1'
Answer 'Hello'
Description 'Greeting'
Work out the grid size from the entries and position letters accordingly.
Pros: Easy to work with. All the information in one place
Cons: Possible data corruption. This method can define 2 different letters in the same position.
2. Seperate Entries but answer text in grid
This is very similar to how you have it now but your seperate the text into a CSV grid as you demonstrate in the first screenshot. You then have entries for the clues as in method 1. but omit the 'Answer' field.
Your code will have to :
work out the grid size
populate a grid
populate the list of
clues
convert the users entries to a CSV text file so that you
can validate the input against the answers and
tell the user if
As for linking the clues to the entry text boxes. Set the Tooltip property of each textbox with descriptions of the clues that include the letter.
they got it right.
Finally (and this is probably the bit you want), add the correct number to the entry text box, you have to take advantage on WPF's layout pipeline. Dont just put a textbox in your grid, put another grid in! I'll show you how it should look in XAML, but you may want to generate it in code.
<Grid>
<TextBlock x:Name="TextBlock_NumberLabel"/>
<TextBox x:Name="TextBox_LetterEntry"/>
<Grid>
Use that instead of a plain textbox in any square where you want a number.
I've been doing some exercises to learn C#. I've been doing XNA and making a space invaders clone.
So far, everything is dandy, but I have come across some walls when coding.
The issues and the supporting code are as follows:
My top of row of invaders have 2 health points, take 2 hits to destroy and yield more points. However, when one is hit, and destroyed, the rest of the top of row are reduced to 1 HP, and take 1 hit to destroy - which is not my desired result.
The offending code I suspect is:
if (playerBullet != null && Type1Invaders != null)
{
Rectangle rectMissile = new Rectangle((int)playerBullet.getX(), playerBullet.getY(), playerBulletIMG.Width, playerBulletIMG.Height);
for (int count = 0; count < 11; count++)
{
Rectangle rectInvader = new Rectangle(Type1Invaders[count].getX(), Type1Invaders[count].getY(), invader1.Width, invader1.Height);
if (Type1Invaders[count].getVis() && rectMissile.Intersects(rectInvader))
{
Type1Invaders[count].setHP(Type1Invaders[count].getHP() - 1);
shootTimer = 0;
if (Type1Invaders[count].getHP() == 0)
{
explosionInstance.Play();
playerBullet = null;
Type1Invaders[count].setVis(false);
score = score + Type1Invaders[count].getPointValue();
}
}
}
}
My second error resides in how I'm detecting the leftmost and rightmost invaders in a row. When an entire row has been destroyed, I get a nullreferenceerror. (Those are a nightmare..)
Anyway, this is the offending code
The method of finding the left and right most invaders
var LeftMost5 = Type5Invaders.Where(i => i.getVis()).FirstOrDefault();
var RightMost5 = Type5Invaders.Where(i => i.getVis()).LastOrDefault();
And the if statement is throwing the null error
if (RightMost5.getX() >= RightGameEdge)
{
Type5.setDir(-1);
for (int count = 0; count < 11; count++)
{
invaderMoveInstance5.Play();
Type5Invaders[count].MoveY(8);
}
}
It only happens with the rightmost, but I can assume it will happen to the left too - I'm assuming I can apply the same logic to fix this error to the left side too.
I can supply more information and snippets if this is not sufficient.
Thanks in advance for the assistance!
For the first issue. I suppose that when a bullet kills an invader, you can say that that bullet won't kill another invader. Therefore, you can add a break; to stop looping. Like this:
if (Type1Invaders[count].getVis() && rectMissile.Intersects(rectInvader))
{
Type1Invaders[count].setHP(Type1Invaders[count].getHP() - 1);
shootTimer = 0;
if (Type1Invaders[count].getHP() == 0)
{
explosionInstance.Play();
playerBullet = null;
Type1Invaders[count].setVis(false);
score = score + Type1Invaders[count].getPointValue();
}
break;
}
For the second error, the FirstOrDefault method returns null in case your collection is empty (after you have killed all type 5 invaders). You simply need to check if it is null or not, like this:
var LeftMost5 = Type5Invaders.Where(i => i.getVis()).FirstOrDefault();
var RightMost5 = Type5Invaders.Where(i => i.getVis()).LastOrDefault();
if(RightMost5 != null)
{
// this means we have a non-null invader
if (RightMost5.getX() >= RightGameEdge)
{
Type5.setDir(-1);
for (int count = 0; count < 11; count++)
{
invaderMoveInstance5.Play();
Type5Invaders[count].MoveY(8);
}
}
}
else
{
//this means that the invader does not exist anymore, so we do nothing
}