Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I get an index out of range when I make a empty guess, I also have problem with updating my score label. Currently it will go through the update but not perform it on the form. I’d also like to make sure the user can’t keep entering a valid letter to get more points, please help just got back to learning c# and projects like this help me learn
namespace Guess_The_Word
{
public partial class Form1 : Form
{
private int wrongGuesses = 0;
private int userGuesses;
private int score = 0;
private string secretWord = String.Empty;
private string[] words;
private string currentWord = string.Empty;
private string userGuess = string.Empty;
private string userInput = string.Empty;
private string randomInput = string.Empty;
public Form1()
{
InitializeComponent();
}
private void guessBtn_Click(object sender, EventArgs e)
{
string guess = userInputBox.Text.ToString();
char[] randomCharArray = currentWord.ToLowerInvariant().ToCharArray();
char[] userInputArray = guess.ToLowerInvariant().ToCharArray();
//Assume that userInput would never be superior than randomCharArray
//And contain only one char
for (int i = 0; i < randomCharArray.Length; i++)
{
if (userInputArray[0].Equals(randomCharArray[i])) // Here is where the error happens
{
UpdateScore();
}
}
// Clean userInput in form
userInputBox.Text = string.Empty;
}
private void resetGamebtn_Click(object sender, EventArgs e)
{
SetUpWords();
}
private void SetUpWords()
{
string path = (#"C:\commonwords.txt"); // Save the variable path with the path to the txt file
words = File.ReadAllLines(path);
int guessIndex = (new Random()).Next(words.Length);
currentWord = words[guessIndex];
wordlbl.Text = string.Empty;
for (int i = 0; i < currentWord.Length; i++)
{
wordlbl.Text += "*";
}
}
private void UpdateScore()
{
scorelbl.Text = Convert.ToString(score);
}
}
}
Make sure you check the length of the array before attempting to access specific indices whether known or not. The example below is kind of overkill on the logic, but it demonstrates the previous statement thoroughly.
if (userInputArray.Length > 0 && userInputArray.Length > i)
if (randomCharArray.Length > 0 && randomCharArray.Length > i)
if (userInputArray[0].Equals(randomCharArray[i]))
UpdateScore();
private void UpdateScore() {
score++;
scorelbl.Text = Convert.ToString(score);
}
I went over to .NET Fiddle and did a basic run through without all of the extra complexity of using arrays and I'm returning some pretty good results. The logic in the example below is pretty basic and will currently only handle the current word having only one of each letter. You'll have to expand on it from here to allow handling of multiple letters in words such as "banana" or "apple".
Hopefully this will get you headed in the right direction with your project, and I hope my answer above taught you what you needed to know about checking the length of arrays before attempting to access their indices.
using System;
using System.Collections.Generic;
public class Program
{
private static int score = 0;
private static string currentWord = string.Empty;
private static char userGuess = '`';
private static List<char> correctLetters = new List<char>();
public static void Main()
{
currentWord = "are";
do {
Console.WriteLine("Enter a letter: ");
userGuess = Console.ReadLine()[0];
} while (TestInput());
Console.WriteLine("The word was: " + currentWord);
Console.ReadLine();
}
private static bool TestInput() {
if (currentWord.ToLowerInvariant().Contains(userGuess.ToString().ToLowerInvariant())) {
correctLetters.Add(userGuess);
score++;
Console.WriteLine("Current Score: " + score);
}
if (correctLetters.Count == currentWord.Length)
return false;
return true;
}
}
i have debugged my code (below) and found out the problem is the Convert() method that converts the text from the textbox. but how i fix this problem?
i have a example of similar problem here.
code:
//METHODS
static string RollDice (int dice)
{
Random roll = new Random();
int rollOutput = roll.Next(1, dice);
//NOTE: VERY IMPORTANT! EVERY TIME THE INPUT GOES INTO THIS
//METHOD REMEMBER TO INCREACE IT BY ONE!
//AND NEVER LET THE USER TO ROLL TO DICE QUICKLY ONE AFTER ANOTHER!
string rollResult = rollOutput.ToString();
return rollResult;
}
static void TwiceD20(int bonus, bool advantage)
{
string firstRollString = RollDice(21) + bonus;
string secondRollString = RollDice(21) + bonus;
int firstRoll = Convert.ToInt32(firstRollString);
int secondRoll = Convert.ToInt32(secondRollString);
switch(advantage)
{
case true:
if (firstRoll >= secondRoll)
{
MessageBox.Show(firstRollString);
}
else
{
MessageBox.Show(secondRollString);
}
break;
case false:
if (firstRoll <= secondRoll)
{
MessageBox.Show(firstRollString);
}
else
{
MessageBox.Show(secondRollString);
}
break;
}
}
//BUTTONS
private void btn1d20_Click(object sender, EventArgs e)
{
MessageBox.Show("Roll Result: " + RollDice(21));
}
private void btnAdv_Click(object sender, EventArgs e)
{
TwiceD20(Convert.ToInt32(textBox1d20.Text), true);
}
private void btnDisAdv_Click(object sender, EventArgs e)
{
TwiceD20(Convert.ToInt32(textBox1d20.Text), false);
}
You have added a non-int into the string. So naturally you cannot convert that to an int because the string is not just an int anymmore.
string firstRollString = RollDice(21) + bonus; // This won't convert back to an int
string secondRollString = RollDice(21) + bonus; // This won't convert back to an int
int firstRoll = Convert.ToInt32(firstRollString);
int secondRoll = Convert.ToInt32(secondRollString);
Adding bonus to the string result of RollDice is simply appending the string "True" or "False" to the result of RollDice. I suspect that you think it is adding a numerical 0 or 1.
I would do as the comments suggest and have RollDice return a number. Then you can turn it into a string and manipulate it later as you see fit.
Or, if you don't want to return anything, just make a quick change to the order of operations.
int firstRoll = Convert.ToInt32(RollDice(21));
int secondRoll = Convert.ToInt32(RollDice(21));
string firstRollString = firstRoll + bonus;
string secondRollString = secondRoll + bonus;
But, not knowing for sure what you intend for your code to do, even that may not work for you.
I'm trying to generate a string of a random length which consists out of random chars.
To do so I have this code:
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
MyString test = new MyString();
test.Random();
Console.WriteLine(test.Value);
}
Console.ReadLine();
}
}
public class MyString
{
private string value = string.Empty;
private Random r = new Random();
public string Value
{
get { return this.value; }
set { this.value = value; }
}
public void Random()
{
int length = (r.Next() % (100)) + 1;
for(int i = 0; i < length; i++)
{
value = value + RandomChar();
}
}
public char RandomChar()
{
// 32 to 126
int c = (r.Next() % 95) + 32;
char ch = (char)c;
return ch;
}
}
Now, lets look at a part of the output:
As you can see, the output is far from random, it contains a lot of repeating strings. How is this possible, and how do I solve it?
It looks like you are creating a new instance of the Random class every time your MyString constructor is called. The Random class probably seeds itself based on the current time (to some resolution). Random number generators seeded with the same value will generate the same pseudo-random sequence.
The solution is to construct one instance of Random and use that everywhere.
http://msdn.microsoft.com/en-us/library/system.io.path.getrandomfilename.aspx
string randomName = Path.GetRandomFileName();
randomName = randomName.Replace(".", string.Empty);
// take substring...
I just want to know how to create simple animations like blinking, moving stuffs on C# console applications. Is there any special method for this?
Traditional Console Spinner:
static void Main(string[] args)
{
ConsoleSpiner spin = new ConsoleSpiner();
Console.Write("Working....");
while (true)
{
spin.Turn();
}
}
public class ConsoleSpiner
{
int counter;
public ConsoleSpiner()
{
counter = 0;
}
public void Turn()
{
counter++;
switch (counter % 4)
{
case 0: Console.Write("/"); break;
case 1: Console.Write("-"); break;
case 2: Console.Write("\\"); break;
case 3: Console.Write("|"); break;
}
Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
}
}
Here is my spinner. The purpose of it is to have a program do some work while the spinner displays to the user that something is actually happening:
public class Spinner : IDisposable
{
private const string Sequence = #"/-\|";
private int counter = 0;
private readonly int left;
private readonly int top;
private readonly int delay;
private bool active;
private readonly Thread thread;
public Spinner(int left, int top, int delay = 100)
{
this.left = left;
this.top = top;
this.delay = delay;
thread = new Thread(Spin);
}
public void Start()
{
active = true;
if (!thread.IsAlive)
thread.Start();
}
public void Stop()
{
active = false;
Draw(' ');
}
private void Spin()
{
while (active)
{
Turn();
Thread.Sleep(delay);
}
}
private void Draw(char c)
{
Console.SetCursorPosition(left, top);
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(c);
}
private void Turn()
{
Draw(Sequence[++counter % Sequence.Length]);
}
public void Dispose()
{
Stop();
}
}
And you use the class like this:
using (var spinner = new Spinner(10, 10))
{
spinner.Start();
// Do your work here instead of sleeping...
Thread.Sleep(10000);
}
Yes, there are quite a few methods for this.
In particular, you may want to look at the following Console methods:
SetCursorPosition (you can move the cursor around, and overwrite elements)
MoveBufferArea (copy/paste over the top of regions)
ForegroundColor and BackgroundColor (change coloring)
Great work with the ConsoleSpinner and the sequence implementation. Thanks for the code. I thought about sharing my customized approach.
public class ConsoleSpinner
{
static string[,] sequence = null;
public int Delay { get; set; } = 200;
int totalSequences = 0;
int counter;
public ConsoleSpinner()
{
counter = 0;
sequence = new string[,] {
{ "/", "-", "\\", "|" },
{ ".", "o", "0", "o" },
{ "+", "x","+","x" },
{ "V", "<", "^", ">" },
{ ". ", ".. ", "... ", "...." },
{ "=> ", "==> ", "===> ", "====>" },
// ADD YOUR OWN CREATIVE SEQUENCE HERE IF YOU LIKE
};
totalSequences = sequence.GetLength(0);
}
/// <summary>
///
/// </summary>
/// <param name="sequenceCode"> 0 | 1 | 2 |3 | 4 | 5 </param>
public void Turn(string displayMsg = "", int sequenceCode = 0)
{
counter++;
Thread.Sleep(Delay);
sequenceCode = sequenceCode > totalSequences - 1 ? 0 : sequenceCode;
int counterValue = counter % 4;
string fullMessage = displayMsg + sequence[sequenceCode, counterValue];
int msglength = fullMessage.Length;
Console.Write(fullMessage);
Console.SetCursorPosition(Console.CursorLeft - msglength, Console.CursorTop);
}
}
Implementation:
ConsoleSpinner spinner = new ConsoleSpinner();
spinner.Delay = 300;
while (true)
{
spinner.Turn(displayMsg: "Working ",sequenceCode:5);
}
Output:
You'll need to use Console.ForegroundColor, Console.BackgroundColor and Console.SetCursorPosition(int, int)
EDIT: For inspiration, Let's Dance
Just saw this and a few other threads about it and love this kind of stuff! I took Tuukka's nice piece of code and improved it a bit so the class can easily be set to just about any spin sequence. I'll probably add some accessors and an overloaded constructor to polish it off and put it in the ol' toolbox. Fun stuff!
class ConsoleSpinner
{
int counter;
string[] sequence;
public ConsoleSpinner()
{
counter = 0;
sequence = new string[] { "/", "-", "\\", "|" };
sequence = new string[] { ".", "o", "0", "o"};
sequence = new string[] { "+", "x" };
sequence = new string[] { "V", "<", "^", ">" };
sequence = new string[] { ". ", ".. ", "... ", "...." };
}
public void Turn()
{
counter++;
if (counter >= sequence.Length)
counter = 0;
Console.Write(sequence[counter]);
Console.SetCursorPosition(Console.CursorLeft - sequence[counter].Length, Console.CursorTop);
}
}
I took the anwser from #ThisGuy and modified it a bit, but I noticed, that sometimes the row is not cleared as it should.
static void Main(string[] args)
{
Console.WriteLine("1");
var tddf = XConsole.BusyIndicator("test 0 trtg fdfdfvdgd 4343", () =>
{
return "";
});
Console.WriteLine("2");
var tdd = XConsole.BusyIndicator("test 0 trtg fdfdfvdgd", () =>
{
Thread.Sleep(1);
return "";
});
Console.WriteLine("3");
var t = XConsole.BusyIndicator("test 1 trtg vdgd", () =>
{
Thread.Sleep(1000);
return "";
});
Console.WriteLine("4");
var xt = XConsole.BusyIndicator("test 2", () =>
{
Thread.Sleep(2000);
return "";
});
var xtx = XConsole.BusyIndicator("test 2 csds fsd fdsf ds s", () =>
{
Thread.Sleep(2000);
return "";
});
Console.WriteLine("5");
Thread.Sleep(4000);
}
Spinner class:
public class Spinner : IDisposable
{
private const string Sequence1 = #"/-\|";
private const string Sequence3 = #".o0o";
private const string Sequence2 = #"<^>v";
private const string Sequence4 = #"#■.";
private const string Sequence5 = #"▄▀";
private const string Sequence = #"└┘┐┌";
private string BusyMessage = "";
private int counter = 0;
private readonly int delay;
private bool active;
private readonly Thread thread;
public Spinner(int delay = 200)
{
this.delay = delay;
thread = new Thread(Spin);
}
public void Start()
{
active = true;
Console.CursorVisible = false;
if (!thread.IsAlive)
{
thread.Start();
}
}
public void Start(string busyMessage)
{
BusyMessage = busyMessage;
Start();
}
public void Stop()
{
active = false;
Console.CursorVisible = true;
ClearCurrentConsoleLine();
BusyMessage = "";
}
private static void ClearCurrentConsoleLine()
{
int currentLineCursor = Console.CursorTop;
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, currentLineCursor);
}
private void Spin()
{
while (active)
{
Turn();
Thread.Sleep(delay);
}
}
/// <summary>
/// Draws the busy indicator
/// </summary>
/// <param name="c">if empty char, then clear screen</param>
private void Draw(char c)
{
int left = Console.CursorLeft;
int top = Console.CursorTop;
Console.Write('[');
Console.ForegroundColor = ConsoleColor.Green;
Console.Write(c);
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write(']');
if (!string.IsNullOrEmpty(BusyMessage))
{
Console.Write(" " + BusyMessage);
}
//reset cursor position
Console.SetCursorPosition(left, top);
}
private void Turn()
{
Draw(Sequence[++counter % Sequence.Length]);
}
public void Dispose()
{
Stop();
}
}
My console class:
public static class XConsole {
public static T BusyIndicator<T>(Func<T> action)
{
T result;
using (var spinner = new Spinner())
{
spinner.Start();
result = action();
spinner.Stop();
}
return result;
}
public static T BusyIndicator<T>(string content, Func<T> action)
{
T result;
using (var spinner = new Spinner())
{
spinner.Start(content);
result = action();
spinner.Stop();
}
return result;
}
}
Why do I see this result sometimes?
1
2
3 st 0 trtg fdfdfvdgd ]
4
[└] test 2 csds fsd fdsf ds s
Looks like the Dispose didn't trigger? Or a new Task alredy started?
It should look like this:
1
2
3
4
[└] test 2 csds fsd fdsf ds s
UPDATE:
I added ClearCurrentConsoleLine(); and changed the Draw method, this fixed the issue.
i'm not TOO sure i know exactly what you're on about. but i'll give it a shot.
I think the biggest and best way to cause the "blinking" affect (or what i think the blinking affect is) is to use a carriage return.
The best way to explain it to you is to show you the Foo Bar experiment.
start a new project, and in your Main function, try this.
Console.WriteLine("Foo/nBar");
The output will look like this
Foo
Bar
But if you use a carriage return.
Console.WriteLine("Foo/rBar");
The output will look like this
Bar
The reason is that Foo is written, then the carriage return takes you BACK to the start of the line, then Bar is written. All you ever see is Bar.
This can be helpful for "Moving" things on one line, instead of rewriting the same things again on multiple lines.
A way to do progression would be to use Console.Write();
Try this.
Console.Write("Loading");
for(int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
Console.Write(".");
}
The output should be
Loading
Followed by a Fullstop every second for 10 seconds.
If you combine the Carriage return with the Console.Write(); function you can write multiple things on a single line, clear the line and write something else, or indeed, the same thing just moved slightly. (This would of course need more than i have shown you, like recording where the "object" you are controlling is situated. If you would like a short example i would be happy to do one, just comment and ask me for it :)
Edit:
I noticed people mentioning colour, which i forgot. If you were doing animation i guess colour would be a must.
ForegroundColor and BackgroundColor are where it's at.
note that ForegroundColor will apply to the next characters written to the console, it will not completely recolour the Console.
/Edit
I hope this helps,
Skintkingle ;)
I thought I'd chime in with my version of the previously listed code. Here it is:
class ConsoleSpinner
{
bool increment = true,
loop = false;
int counter = 0;
int delay;
string[] sequence;
public ConsoleSpinner(string sSequence = "dots", int iDelay = 100, bool bLoop = false)
{
delay = iDelay;
if (sSequence == "dots")
{
sequence = new string[] { ". ", ".. ", "... ", "...." };
loop = true;
}
else if (sSequence == "slashes")
sequence = new string[] { "/", "-", "\\", "|" };
else if (sSequence == "circles")
sequence = new string[] { ".", "o", "0", "o" };
else if (sSequence == "crosses")
sequence = new string[] { "+", "x" };
else if (sSequence == "arrows")
sequence = new string[] { "V", "<", "^", ">" };
}
public void Turn()
{
if (loop)
{
if (counter >= sequence.Length - 1)
increment = false;
if (counter <= 0)
increment = true;
if (increment)
counter++;
else if (!increment)
counter--;
}
else
{
counter++;
if (counter >= sequence.Length)
counter = 0;
}
Console.Write(sequence[counter]);
Console.SetCursorPosition(Console.CursorLeft - sequence[counter].Length, Console.CursorTop);
System.Threading.Thread.Sleep(delay);
}
}
Adds delay (unfortunately through Thread.Sleep() but, hey), the ability to loop the animation forwards and backwards (starts to reverse when it hits the end), and general improvements overall. Enjoy!
This would be my prefered method:
public sealed class Spinner
{
private static Lazy<Spinner> lazy =
new Lazy<Spinner>(()=> new Spinner());
public static void Reset()
{
lazy = new Lazy<Spinner>(()=> new Spinner());
}
public static Spinner Instance { get { return lazy.Value; }}
private readonly int _consoleX;
private readonly int _consoleY;
private readonly char[] _frames = { '|', '/', '-', '\\' };
private int _current;
private Spinner()
{
_current = 0;
_consoleX = Console.CursorLeft;
_consoleY = Console.CursorTop;
}
public void Update()
{
Console.Write(_frames[_current]);
Console.SetCursorPosition(_consoleX, _consoleY);
if (++_current >= _frames.Length)
_current = 0;
}
}
Call Spinner.Instance.Update() to start the spinner at the current position of the console. Any consecutive call will render the next frame at the same position.
Call Spinner.Reset() if you want to write more text and then add a new spinner at a new location.
This is the way i solved it, sure it could/can be shorter but, Im just not that smart yet :-)
void cc() { Console.Clear(); }
void cr() { Console.ReadKey(); }
byte Sleeptimer = 90;
void sleepy() { System.Threading.Thread.Sleep(Sleeptimer); }
string[] Loading = { #"-- ", #"\ ", #"| ", #"/ ", "Loading", " complete!" };
for (byte i = 0; i <= 15; i++)
{
cc();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(Loading[0] + Loading[4]);
sleepy();
cc();
Console.WriteLine(Loading[1] + Loading[4]);
sleepy();
cc();
Console.WriteLine(Loading[2] + Loading[4]);
sleepy();
cc();
Console.WriteLine(Loading[3] + Loading[4]);
sleepy();
cc();
if (i == 15) {
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(Loading[4] + Loading[5]);
cc();
Console.ForegroundColor = ConsoleColor.Cyan;
Next();
}
}
/*
Now i feel even more noob while reading your code.
I'm a newbie in programing.
Guess this way would work if i just incfement the index of each Loading down below right?
Learned too much today, forgot how this exactly works, to increment or to change the index i'd lile to acces
Console.WriteLine(Loading[2] + Loading[4]);
sleepy();
cc();
*/
This is animation with cancellationToken
private static void ClearCurrentConsoleLine()
{
int currentLineCursor = Console.CursorTop;
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, currentLineCursor);
}
public static async Task Start(CancellationToken ct)
{
await Task.Run(() =>
{
Thread.Sleep(2000);
Console.WriteLine();
string text = "Executing";
for (int i = 0; i <= 3; i++)
{
if (ct.IsCancellationRequested)
{
Console.SetCursorPosition(0, Console.CursorTop - 1);
ClearCurrentConsoleLine();
ct.ThrowIfCancellationRequested();
}
Thread.Sleep(1000);
Console.SetCursorPosition(0, Console.CursorTop - 1);
ClearCurrentConsoleLine();
Console.WriteLine(text);
if (i == 3)
{
text = "Executing";
i = 0;
}
text += ".";
}
});
}```