Reading the keys form a keyboard C# - c#

I have a console app in C# that does a animation with a word, in a loop. Its basically showing the word going from left to righ.
My idea is that if the user press upArrow the animation would start to go up , if he press left the word would satrt to go left... and so on
My question is, how can i have a loop running and also have the program listen for the keyboard key that will be pressed at any given moment?

I wrote a good and considerable code for you although you need to complete it yourself. It just follows the order of the Left Arrow key. You need to add some extra code for following the other orders. Also you have to care about indexoutofrangeexception. As you can see I have written some extra code to handle the left side of console. I hope you enjoy it.
static void Main(string[] args)
{
const string txt = "STACKOVERFLOW";
var x = 1;
var startPos = 0;
var col = 0;
while (true)
{
do
{
while (!Console.KeyAvailable && (startPos <= 100 || startPos >= 0))
{
startPos = col + x;
if (startPos < 0)
{
startPos = 0;
x = 1;
}
Console.SetCursorPosition(startPos, 0);
Console.WriteLine(txt);
col = startPos;
Thread.Sleep(500);
Console.Clear();
}
} while (Console.ReadKey(true).Key != ConsoleKey.LeftArrow);
x = -1;
}
}

I don't know if you have found a solution for your program yet, but here is a good tutorial you might find useful.
Basic C# Game Programming Moving Object on the form

Related

Updating certain values of text in a loop

I want to see numbers updated only in console app, here is how I try to achieve this:
int successEntryCount = 0;
int failedEntryCount = 0;
Console.WriteLine("App Started:");
foreach (var entity in entities)
{
var res = bll.AsiErtelemeIptalPaketiGonder(entity);
if (res.State == Framework.Entities.MessageResultState.SUCCESS)
successEntryCount++;
else
failedEntryCount++;
Console.WriteLine("success :{0}", successEntryCount);
Console.WriteLine("fail:{0}", failedEntryCount);
}
Of course it duplicates the line and Console.Clear() is not a good option since the text would be blinking too fast. I just want to see only these numbers updated.
Use Console.SetCursorPosition method. Let's take a look at this simple example:
int successEntryCount = 0,
failedEntryCount = 10,
l = Console.CursorLeft,
t = Console.CursorTop;
for (int i = 0; i < 2000; i++)
{
Thread.Sleep(100);
Console.SetCursorPosition(l, t);
Console.WriteLine("success :{0}", successEntryCount++);
Console.WriteLine("fail:{0}", failedEntryCount++);
//or
//Console.Write("success :{0} fail:{1}", successEntryCount++ , failedEntryCount++);
}
It will update/print values without flickering.
There is more options (if you find them more attractive for you) to achieve same thing, for example:
Console.Write("\rsuccess :{0} fail:{1}", successEntryCount++, failedEntryCount++); //Carriage return
\r represents a carriage return (character 13) which means the cursor returns to the start of the line.
or
Console.Write("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bsuccess :{0} fail:{1}", successEntryCount++ , failedEntryCount++); //Using backspaces
\b is backspace character (character 8).
References: MSDN Escape Sequences
You can use Console.SetCursorPosition to set the cursor position. Also not to loose the existing console logs (already logged like - App Started: in your case), you can set the cursor position based on retrieved left and top position. The current left and right position can be retrieved using Console.CursorLeft and Console.CursorTop properties.
int successEntryCount = 0;
int failedEntryCount = 0;
Console.WriteLine("App Started:");
int left = Console.CursorLeft;
int right = Console.CursorTop;
foreach (var entity in entities)
{
var res = bll.AsiErtelemeIptalPaketiGonder(entity);
if (res.State == Framework.Entities.MessageResultState.SUCCESS)
successEntryCount++;
else
failedEntryCount++;
Console.SetCursorPosition(left, right);
Console.WriteLine("success :{0}", successEntryCount);
Console.WriteLine("fail:{0}", failedEntryCount);
}
Instead of
Console.WriteLine("success :{0}", successEntryCount);
Console.WriteLine("fail:{0}", failedEntryCount);
you might try something like
Console.Write("success :{0} fail:{1} \r", successEntryCount, failedEntryCount);

How to recall a loop after it runs and its condition is reset

Not sure if I've numbed my mind trying to figure this but I'm trying to get a loop to trigger again after it runs by changing its condition in a later branch of code based on user input. Here's the code:
int moveend = 1;
for (int move = 0; move < moveend; move++)
{
if (move < 1)
{
Console.WriteLine("Enter a direction to move\n");
//forloop that allows the output to cycle the legth of array and branch to a new line on 4th output
for (int i = 0; i < width; i++)
{
//for loop code
}
//This is the code i'm using to re trigger the previous loop with "move = 0"
ConsoleKeyInfo kb = Console.ReadKey();
if (kb.Key == ConsoleKey.UpArrow)
{
map[7, 1] = 1;
map[11, 1] = 0;
move = 0;
Console.WriteLine("FIre");
}
}
else
{
Console.WriteLine("END");
}
}
I'm not sure why it is that I can see the "Fire" with this code but it doesn't loop again despite the loop condition being reset within the loop. I expected it to reprint the loop info with the updated array coordinates map[7, 1] = 1; map[11, 1] = 0; but it doesn't. Am I overlooking something or is there something I'm missing about loops?
The reason is that you set move to 0, but it is already zero.
The loop can loosely be translated to this:
int move = 0;
while (move < moveend)
{
... rest of your code
move++;
}
So move is 0 the whole time throughout the loop, and is increased at the end, and then it is no longer < moveend.
To keep running the loop, perhaps you don't want a for loop at all?
bool keepRunning = true;
while (keepRunning)
{
keepRunning = false;
... rest of your code
if (...)
keepRunning = true; // force another run through the loop
}
I am not sure why are you doing it like that I think this might help you to accomplish your task
bool dirtyBool = true;
while(dirtyBool)
{
if (move < 1)
{
Console.WriteLine("Enter a direction to move\n");
//forloop that allows the output to cycle the legth of array and branch to a new line on 4th output
for (int i = 0; i < width; i++)
{
//for loop code
}
//This is the code i'm using to re trigger the previous loop with "move = 0"
ConsoleKeyInfo kb = Console.ReadKey();
if (kb.Key == ConsoleKey.UpArrow)
{
map[7, 1] = 1;
map[11, 1] = 0;
move = 0;
dirtyBool=false;
Console.WriteLine("FIre");
}
}
else
{
dirtyBool=false;
Console.WriteLine("END");
}
}
I have added a variable dirtyBool of type Bool which will make loop it again. Modify the code according to your usablility

No error but something is wrong with DataGridView

I roughly translated vb.net code to c# for a simple POS system i'm coding for school. But when i try to add things to the datagrid using button click event there is no change in the datagrid. there are no errors. the datagrid is not connected to a database, at least not yet.
here's the code where i insert things to the datagrid:
private void txtAdd_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtProduct.Text) & !string.IsNullOrEmpty(txtQuantity.Text) & !string.IsNullOrEmpty(txtPrice.Text))
{
var with = dataSales;
int ii = 0;
int orderproduct = 0;
int count = 0;
for (ii = 0; ii <= with.RowCount - 1; ii++)
{
if (txtProduct.Text == Convert.ToString(dataSales[0, ii].Value))
{
count = count + 1;
if (count != 0)
{
orderproduct = Convert.ToInt32(dataSales[2, ii].Value) + Convert.ToInt32(txtQuantity.Text);
dataSales[2, ii].Value = orderproduct;
dataSales[3, ii].Value = Convert.ToInt32(dataSales[2, ii].Value) * Convert.ToInt32(dataSales[1, ii].Value);
}
else
{
if (count == 0)
{
float sum = Convert.ToInt32(txtPrice.Text) * Convert.ToInt32(txtQuantity.Text);
dataSales.Rows.Add(txtProduct.Text, txtPrice.Text, txtQuantity.Text, sum);
count = 0;
}
txtProduct.Clear();
txtQuantity.Clear();
txtPrice.Clear();
}
}
else
{
MessageBox.Show("Nothing is Selected", "Error");
}
}
}
}
Follow your counter and you will understand why you never get anything added. You start with 0 but add +1 every single time there is text to add. PUt it in debug and watch.
EDITED: Due to your comment you do not know how to debug. Open the .cs file in Visual Studio, Click on the left margin for the line that tests for text in the fields (the line below):
if (!string.IsNullOrEmpty(txtProduct.Text) & !string.IsNullOrEmpty(txtQuantity.Text) & !string.IsNullOrEmpty(txtPrice.Text))
Now start the program, enter text and run it. It will stop on that line. You can then hit F11 and it will go to the line that increments the counter. This means you will always run this branch.
if (count != 0)
{
orderproduct = Convert.ToInt32(dataSales[2, ii].Value) + Convert.ToInt32(txtQuantity.Text);
dataSales[2, ii].Value = orderproduct;
dataSales[3, ii].Value = Convert.ToInt32(dataSales[2, ii].Value) * Convert.ToInt32(dataSales[1, ii].Value);
}
NOTE: You do not need this:
if (count == 0)
{
}
Why? You have already sent anything not 0 to the other branch. The else is sufficient at this point, and no need to waste a cycle determining if something that will ALWAYS be zero is zero

Auto-Updating in Console Application

I have a console Application that Asks The user to answer question, The score is display at the upper-right of the screen, I want the score to be auto-Updates when a user gives a correct answer.
public void L1Timer()
{
Console.Clear();
int ch = 0, score = 0;
Console.Write("Chances : " + ch);
Console.CursorLeft = 40;
Console.Write("Marks : " + score);
for (int time = 0; time <= 100000; time++)
{
Console.SetCursorPosition(65, 0);
Console.Write("Time Elapsed : " + time + " Secs");
Console.CursorLeft = 40;
Thread.Sleep(1000);
}
}
public void Level1()
{
Console.WriteLine("\n\n");
Console.CursorLeft = 40;
Console.WriteLine("C _ _ E _ _ _ T _ _ N");
Console.WriteLine("\n\n");
int tot = 0;
while (tot != 70)
{
Console.Write("Guess : ");
string gues = Console.ReadLine();
if ((gues == "E") || (gues == "L") || (gues == "B") || (gues == "R"))
{
tot += 10;
}
}
}
static void Main(string[] args)
{
VocEnhancer VE = new VocEnhancer();
Thread T1 = new Thread(new ThreadStart (VE.L1Timer));
Console.WriteLine("\n\n\n\n\n");
Thread T2 = new Thread(new ThreadStart(VE.Level1));
T1.Start();
T2.Start();
}
This is my Code...I don't know what to add to auto-update the scores.
Without your code, we can only assume and my suggestion as follows:
string question = "CEO of Microsoft";
string actualAnswer ="STEVE BALLMER";
Console.WriteLine(question);
string userAnswer = "";
Console.WriteLine(userAnswer);
int score = 0;
if(actualAnswer.Trim() == userAnswer.ToUpper().Trim())
{
score++;
}
First a warning: console is not meant to display graphics, menus, or to be drawn on. It is meant to be written upon, one line at the time. For all things graphics there are windows, and windows should be used, not consoles. However, if you are just playing around and making fun at your leisure time then go ahead and write characters at strange places in the console.
To move the cursor use SetCursorPosition method. To find out where the cursor currently is use CursorLeft and CursorTop properties. When you want to write something at fixed coordinates save current cursor position, change to fixed position, write the text, and change back to old position.
But what should happen when all text reaches the end of the screen, and text at the top disappears? Well, there are ways to solve this, but don't bother. Just use window instead of console.

Space Invaders health/array issues

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
}

Categories