What does IndexOutofRangeException mean? - c#
It says that in my array that I have gone over the index. My program is a Number Guessing game played by 5 players (5 indexes). I have used arrays to create the object and player classes.
I have reached a stump where my program crashes within the second or third round of the game. I noticed that during my second round, the index did not loop property: the loop counts the index 1 to 5 in the first loop, then counts 2 to 5 in the second loop, then if I even get to the 3rd round of the loop, all the indexes are shuffled around meaning I can't go from 1 to 5.
As each player gets 3 guesses, use those 3 guesses and your out of the game. I have taken the array of object I created for the player, created a temporary array smaller than the previous and referenced that to achieve the current array.
I looked over my references in the code and found as much code as I could fix, I cannot find the bug that is causing my System.IndexOutOfRangeException. It is being caused by my guessing game class.
Here is my GuessingGame Class:
using System; // only this using statement is needed here.
namespace GuessingGame
{
class GuessingGame
{
#region instance attributes
private const int GUESSES_ALLOWED = 3;
private const int NUMBER_OF_PLAYERS_TO_START = 5;
private const int MIN_VALUE = 1;
private const int MAX_VALUE = 15;
private Player[] players;
private Random randomSource;
#endregion
public GuessingGame()
{
Console.WriteLine("Starting Constructor of GuessingGame");
players = new Player[NUMBER_OF_PLAYERS_TO_START];
randomSource = new Random();
string playerName = "";
for (int index = 0; index < players.Length; index++)
{
Console.Write("What is the name for player #"
+ (index +1) + "?\t");
playerName = Console.ReadLine();
players[index] = new Player(playerName, randomSource);
Console.Write("\n");
}
Console.WriteLine("Ending GuessingGame Constructor");
}
public GuessingGame(string [] playerNames)
{
Console.WriteLine("Starting Constructor of GuessingGame");
players = new Player[playerNames.Length];
randomSource = new Random();
for (int index = 0; index < playerNames.Length; index++)
{
players[index] = new Player(playerNames[index], randomSource);
}
}
public void playGame()
{
int numberOfPlayersWhoHavePlayedThisRound = 0;
int index = 0;
bool[] playedThisRound = null;
string playerGuessEntry = "";
int playerGuessValue = -1;
Player[] tempArray = new Player[players.Length - 1];
bool roundOver = false;
Console.WriteLine(
"Starting playGame - press any key to continue");
//Console.Read()
while (roundOver == false) // Is this the right condition?
{
playedThisRound = new bool[players.Length];
while (playedThisRound[index] == false)
{
do
{
Console.Write(players[index].getName()
+ ", Enter a number between "
+ MIN_VALUE.ToString()
+ " and " + MAX_VALUE.ToString()
+ " inclusive\t");
playerGuessEntry = Console.ReadLine();
Console.Write("\n");
}
while (!int.TryParse(playerGuessEntry,
out playerGuessValue)
|| playerGuessValue < MIN_VALUE
|| playerGuessValue > MAX_VALUE);
if(playerGuessValue < MIN_VALUE || playerGuessValue > MAX_VALUE)
{
Console.Write("Invalid guess- try again");
}
else
{
Console.WriteLine("You entered "
+ playerGuessValue.ToString());
players[index].makeAGuess(playerGuessValue);
playedThisRound[index] = true;
if (index == players.Length)
{
Console.WriteLine("End of Round");
index = 0; //edit?
numberOfPlayersWhoHavePlayedThisRound = 0;
}
}
if (players[index].getGuessesUsed() == 3)
{//creating a temp array
Console.WriteLine("Guesses MAXED");
tempArray = players[index].deletePlayerFromArray(players, index);
players = tempArray; // referencing
bool[] tempBooleanArray = new bool[playedThisRound.Length - 1];//reducing size of played this round array
Console.WriteLine("Playedthisround length: " + playedThisRound.Length + " \nThe Index: " + index.ToString());
tempBooleanArray = players[index].deletePlayerBool(playedThisRound, index);
playedThisRound = tempBooleanArray;
Console.WriteLine("New Player Array Size: " + players.Length);
Console.WriteLine("New Boolean Array Size: " + playedThisRound.Length);
}
if (index == players.Length - 1)
{
index = 0;
numberOfPlayersWhoHavePlayedThisRound = 0;
}
if (players.Length == 1)
{
roundOver = true;
}
index++;
numberOfPlayersWhoHavePlayedThisRound++;
}
Console.WriteLine("WINNER:" + players[index].getName() +
"\nWins: " + players[index].getWins() + "\nArray Size: " + players.Length.ToString());
}//end of while
Console.WriteLine("Ending playGame - "
+ "press any key to continue");
Console.Read();
}
public bool playersAlreadyPlayed(bool[] thePlayer)
{
bool havePlayed = false;
for (int plays = 0; plays < thePlayer.Length; plays++)
{
if (thePlayer[plays] == false)
{
havePlayed = false;
}
else
{
havePlayed = true;
}
}
return havePlayed;
}
static void Main(string[] args)
{
GuessingGame newGame = new GuessingGame();
newGame.playGame();
}
}
}
And Here is the Player Class
using System;
namespace GuessingGame
{
class Player
{
private String name;
private int winningNumber;
private int guessesUsed;
private int wins;
private Random myWinningNumberSource;
public Player(string newName, Random random)
{
name = newName;
guessesUsed = 0;
wins = 0;
myWinningNumberSource = random;
winningNumber = myWinningNumberSource.Next(1, 16);
}
public bool makeAGuess(int guessValue)
{
bool isWinner = false;//edit
if (guessValue == winningNumber)
{
wins++;
Console.WriteLine("Congradulations, You have guessed correct number!\n");
Console.WriteLine("You have a total of " + wins + " wins!");
Console.WriteLine("You have " + (3 - guessesUsed) + " guesses left!\n");
winningNumber = myWinningNumberSource.Next(1, 16);
isWinner = true; //edit
}
else
{
guessesUsed++;
Console.WriteLine("Oh no! You have guessed incorretly!");
Console.WriteLine("You have used " + guessesUsed + " and have " + (3 - guessesUsed) + " guesses left!");
Console.WriteLine("HINT: You should have guessed " + winningNumber);
isWinner = false;
if (guessesUsed > 3)
{
Console.WriteLine("Sorry you have Lost, Game Over");
}
}
return isWinner;
}
public int getGuessesUsed()
{
return guessesUsed;
}
public string getName()
{
return name;
}
public int getWins()
{
return wins;
}
public Player[] getWinner(Player[] nPlayers)
{
int maxScore = 0; //edit
Player[] winningPlayers;
winningPlayers = new Player[5];
for (int i = 0; i < nPlayers.Length; i++)
{
if (nPlayers[i].wins >= maxScore)
{
winningPlayers[i].wins = nPlayers[i].getWins();
winningPlayers[i].name = nPlayers[i].getName();
}
}
return winningPlayers;
}
public bool[] deletePlayerBool(bool[] playedThisRound, int removeIndex)//edit
{
bool[] newArray = new bool[playedThisRound.Length - 1];
int tempIndex = 0;
for (int i = 0; i < playedThisRound.Length; i++)
{
if (i != removeIndex)
{
newArray[tempIndex++] = playedThisRound[i];
}
}
return newArray;
}
public Player[] deletePlayerFromArray(Player[] nPlayers, int removeIndex)
{
Player[] newArray = new Player[nPlayers.Length - 1];
int tempIndex = 0;
for (int i = 0; i < nPlayers.Length; i++)
{
if (i != removeIndex)
{
newArray[tempIndex++] = nPlayers[i];
}
}
return newArray;
}
}
}
i is within the bounds of nPlayer length not 0-4.
public Player[] getWinner(Player[] nPlayers)
{
int maxScore = 0; //edit
Player[] winningPlayers;
winningPlayers = new Player[5];
for (int i = 0; i < nPlayers.Length; i++)
{
if (nPlayers[i].wins >= maxScore)
{
winningPlayers[i].wins = nPlayers[i].getWins();
winningPlayers[i].name = nPlayers[i].getName();
}
}
return winningPlayers;
}
It means that you are trying to access an index bigger than the array. In the line:
while(playedThisRound[index] == false)
You don't check the boundaries before using the index, and your crash is probably there.
It means that you are trying to access an item in an array with an index higher than the limit of the array.
Related
how can i bubble sort array that storing a class field?
void Bubblesort(City []cities, int num) { for(int i = 0; i < num - 1; i++) { for (int j = 0; j < num - 1 - i; j++) { if (cities[j].CityTemperature < cities[j].CityTemperature + 1) { var tempvariable = cities[j]; cities[j] = cities[j + 1]; cities[j + 1] = tempvariable; } } } for (int i = 0; i < num; i++) { Console.WriteLine(cities[i].ToString()); } } static void Main(string[] args) { Console.WriteLine("welcome to enter the name of the city and its temperature between -60 and 60 Celsius \n you will have to enter 4 elements of each :-) \n\n\n\n"); City[] cities = new City[4]; Program myProgram = new Program(); var num = cities.Length; for (int i = 0; i < cities.Length; i++) { cities[i] = new City(); Console.Write("Name of City ?: "); cities[i].CityName = Console.ReadLine(); Console.Write("what Temp ?: "); cities[i].CityTemperature = System.Convert.ToInt32(System.Console.ReadLine()); Console.Clear(); } myProgram.Bubblesort(cities, num); Console.WriteLine("press a button of choice and hit enter to close the program, \n Byebye :-)"); Console.ReadKey(); } } /// My City class private string name; private int temperature; public string CityName { get { return name; } set { name = value; } } public int CityTemperature { get { return temperature; } set { temperature = value; } } public override string ToString() { return "City: " + CityName + " City temperature: " + CityTemperature; } So basically user input City name and City temperature that are stored into fields of the class, i want to bubblesort the array by the temperature so it will make an output sorted from coldest to warmest. can you see where to begin with ? i been trying to figure out if im passing wrong arguments when calling the function and been trying to change withing the loops and experimenting. im thinking maybe that i dont compare the temperature values and it does something else. however the sorting is never occuring. appreciate the time you take to look at this.*
Why does CS0136 error keep on popping up?
I keep on receiving this CS0136 error and I'm unsure why? using System; namespace Lab2_1 { class Program { static void Main(string[] args) { Action<string> cw = Console.WriteLine; int[] numbers = new int[10]; int currentIndex = 0; bool repeat = true; do { cw("Please enter an interger: "); string line = Console.ReadLine(); if (line == "exit") { repeat = false; } else { try { int number = int.Parse(line); cw("The number you entered was: " + number); numbers[currentIndex] = number; currentIndex++; } catch (FormatException) { cw("That wasn't a number!"); } } } while (repeat); Console.WriteLine("Press any key to exit."); { while (repeat) ; for (int i = 0; i < currentIndex; i++) { Console.WriteLine(numbers[i]); } currentIndex++; if (currentIndex == numbers.Length) { int expandedNumberOfCells = currentIndex + 10; } int expandedNumberOfCells = currentIndex + 10; int[] expandedNumbers = new int[expandedNumberOfCells]; for (int i = 0; i < currentIndex; i++) { expandedNumbers[i] = numbers[i]; } numbers = expandedNumbers; } } } }
From this page you can see what error CS0136 is. You could not declare expandedNumberOfCells repeatedly, you can slightly modify your code: int expandedNumberOfCells = currentIndex + 10; int[] expandedNumbers = new int[expandedNumberOfCells]; if (currentIndex == numbers.Length) { expandedNumberOfCells = currentIndex + 10; } for (int i = 0; i < currentIndex; i++) { expandedNumbers[i] = numbers[i]; } numbers = expandedNumbers;
breaks while loop when all die rolls the same number
using System; using System.Collections.Generic; namespace AnyDice { class Program { static void Main(string[] args) { int diceSides; int rollDie; int count = 0; bool keepRolling = true; List<int> num = new List<int>(); Random random = new Random(); Console.Write("Write the number of sides of your die: "); diceSides = Convert.ToInt32(Console.ReadLine()); Console.WriteLine("Type the numbers of the die"); for (int i = 0; i < diceSides; i++) { int rank = 1 + i; Console.Write(rank + "~~> "); num.Add(Convert.ToInt32(Console.ReadLine())); } num.Sort(); Console.WriteLine("\nHere's the die and its contents"); for (int i = 0; i < num.Count; i++) { Console.Write("["); Console.Write(num[i]); Console.Write("]"); } Console.WriteLine("\nHow many times do you want to roll at once"); rollDie = Convert.ToInt32(Console.ReadLine()); while (keepRolling) { for (int i = 0; i < rollDie; i++) { Console.Write("["); Console.Write(num[random.Next(num.Count)]); Console.Write("]"); count++; } Console.ReadLine(); } Console.WriteLine("It took you " + count + " attempts"); Console.ReadLine(); } } } For example if (4,4,4,4) is rolled or (2,2) in any "n" number of column the while loop breaks. I thought of storing each die rolled value in another arraylist and comparing each value in it. If its all equal then it breaks.. but I have no clue on how to implement it.
We have Linq. It lives in the System.Linq namespace and this might help you. I'll should two ways of checking if all die are the same: int first = dies.First(); if (dies.All(i => i == first)) { // break if all are equals to the first die } Or using Distinct we can filter out any copies. if (dies.Distinct().Count() == 1) { // if we only have unique items and the count is 1 every die is the same }
I am not 100% sure I understand your requirement, but in any case, you should write a separate function that returns a flag indicating whether the array is in a state that should trigger a break. bool KeepRolling(int[] num) { for (int i=0; i<num.Length; i++) { if (num[i] >= i) return false; } return true; } Then just call it from within your loop: keepRolling = KeepRolling(num);
while (keepRolling) { rolls.Clear(); for (int i = 0; i < rollDie; i++) { var firstRoll = num[random.Next(num.Count)]; rolls.Add(firstRoll); Console.Write(firstRoll + " "); count++; } if (rolls.Distinct().Count() == 1) { Console.WriteLine("It took you " + count + " attempts"); keepRolling = false; break; } Console.ReadLine(); }
Why Is This Code Running Longer Character Combinations Than Necessary?
I'm a math student with little to no experience programming, but I wrote this to act like a brute force algorithm. It seems to run fine except that it runs all the password combinations out to 3 characters for passwords as short as 2. Also I'm sure there's a way to refactor the for and if statements as well. Any help would be appreciated, thanks. I've already been testing to see if some of the if statements aren't executing, and it looks like the statements with "console.writeln(Is this executing)" aren't executing but I'm not really sure. public Form1() { InitializeComponent(); } static char[] Match ={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j' ,'k','l','m','n','o','p', 'q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','C','L','M','N','O','P', 'Q','R','S','T','U','V','X','Y','Z','!','?',' ','*','-','+'}; private string[] tempPass; private void button1_Click(object sender, EventArgs e) { string tempPass1 = "lm"; string result = String.Empty; int passLength = 1; int maxLength = 17; tempPass = new string[passLength]; for (int i = 0; i < Match.Length; i++) { if (tempPass1 != result) { tempPass[0] = Match[i].ToString(); result = String.Concat(tempPass); if (passLength > 1) { for (int j = 0; j < Match.Length; j++) { if (tempPass1 != result) { tempPass[1] = Match[j].ToString(); result = String.Concat(tempPass); if (passLength > 2) { for (int k = 0; k < Match.Length; k++) { if (tempPass1 != result) { tempPass[2] = Match[k].ToString(); result = String.Concat(tempPass); if (tempPass[0] == "+" && tempPass[1] == "+" && tempPass[2] == "+" && tempPass1 != result) { Console.WriteLine("This will execute?"); passLength++; tempPass = new string[passLength]; k = 0; j = 0; i = 0; } else if (result == tempPass1) { Console.WriteLine("Broken"); Console.WriteLine("This is big gay: " + result); break; } } } } if (tempPass[0] == "+" && tempPass[1] == "+" && tempPass1 != result) { Console.WriteLine("Did this execute?"); passLength++; tempPass = new string[passLength]; j = 0; i = 0; } else if (result == tempPass1) { Console.WriteLine("Broken"); Console.WriteLine("This is bigger gay: " + result); break; } } } } //tempPass[1] = "World!"; //Console.WriteLine(result); if (tempPass[tempPass.Length - 1] == "+" && tempPass1 != result) { passLength++; tempPass = new string[passLength]; Console.WriteLine(tempPass.Length + " " + result + " " + "Success"); Console.WriteLine(i); i = 0; /**update j = 0; k = 0; l = 0; m = 0;*/ } else if (result == tempPass1) { Console.WriteLine("Broken"); Console.WriteLine("This is biggest gay: " + result); } } } }
Play with this; modified from my answer here. It'll show you all the 2 and 3 length combinations. Clicking the button will start/stop the generation process. You need a button, label, and a timer: public partial class Form1 : Form { private Revision rev; public Form1() { InitializeComponent(); rev = new Revision("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!? *-+", "00"); label1.Text = rev.CurrentRevision; } private void button1_Click(object sender, EventArgs e) { timer1.Enabled = !timer1.Enabled; } private void timer1_Tick(object sender, EventArgs e) { rev.NextRevision(); if (rev.CurrentRevision.Length == 4) { timer1.Stop(); MessageBox.Show("Sequence Complete"); // make it start back at the beginning? rev = new Revision("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!? *-+", "00"); label1.Text = rev.CurrentRevision; } else { label1.Text = rev.CurrentRevision; } } } public class Revision { private string chars; private char[] values; private System.Text.StringBuilder curRevision; public Revision() { this.DefaultRevision(); } public Revision(string validChars) { if (validChars.Length > 0) { chars = validChars; values = validChars.ToCharArray(); curRevision = new System.Text.StringBuilder(values[0]); } else { this.DefaultRevision(); } } public Revision(string validChars, string startingRevision) : this(validChars) { curRevision = new System.Text.StringBuilder(startingRevision.ToUpper()); int i = 0; for (i = 0; i <= curRevision.Length - 1; i++) { if (Array.IndexOf(values, curRevision[i]) == -1) { curRevision = new System.Text.StringBuilder(values[0]); break; } } } private void DefaultRevision() { chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; values = chars.ToCharArray(); curRevision = new System.Text.StringBuilder(values[0]); } public string ValidChars { get { return chars; } } public string CurrentRevision { get { return curRevision.ToString(); } } public string NextRevision(int numRevisions = 1) { bool forward = (numRevisions > 0); numRevisions = Math.Abs(numRevisions); int i = 0; for (i = 1; i <= numRevisions; i++) { if (forward) { this.Increment(); } else { this.Decrement(); } } return this.CurrentRevision; } private void Increment() { char curChar = curRevision[curRevision.Length - 1]; int index = Array.IndexOf(values, curChar); if (index < (chars.Length - 1)) { index = index + 1; curRevision[curRevision.Length - 1] = values[index]; } else { curRevision[curRevision.Length - 1] = values[0]; int i = 0; int startPosition = curRevision.Length - 2; for (i = startPosition; i >= 0; i += -1) { curChar = curRevision[i]; index = Array.IndexOf(values, curChar); if (index < (values.Length - 1)) { index = index + 1; curRevision[i] = values[index]; return; } else { curRevision[i] = values[0]; } } curRevision.Insert(0, values[0]); } } private void Decrement() { char curChar = curRevision[curRevision.Length - 1]; int index = Array.IndexOf(values, curChar); if (index > 0) { index = index - 1; curRevision[curRevision.Length - 1] = values[index]; } else { curRevision[curRevision.Length - 1] = values[values.Length - 1]; int i = 0; int startPosition = curRevision.Length - 2; for (i = startPosition; i >= 0; i += -1) { curChar = curRevision[i]; index = Array.IndexOf(values, curChar); if (index > 0) { index = index - 1; curRevision[i] = values[index]; return; } else { curRevision[i] = values[values.Length - 1]; } } curRevision.Remove(0, 1); if (curRevision.Length == 0) { curRevision.Insert(0, values[0]); } } } }
C# array won't work
I have created a piece of code to create an array of 100 elements which will randomize based on the numbers from a set array. However whenever I enter "y" I am looking the array to delete the last element and add a new random element to the start and move everything in between one to the right to allow for this. However at the moment it is completely changing the array every time I enter "y". Can anyone help with this? using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; namespace Rextester { public class Program { public static void Main(string[] args) { int[] values = { 1, 2, 3, 4, 5, 6 }; int Min = values[0]; int Max = values[5] + 1; int w = 0 ; int[] rndValues = new int[100]; Random rndNum = new Random(); Console.WriteLine("Random001 " + w); for (int i = 0; i < rndValues.Length; i++) { rndValues[i] = rndNum.Next(Min, Max); } Console.WriteLine("Random " + w); foreach(var item in rndValues) { Console.Write(item.ToString() + " "); } if (w==0) { Console.WriteLine(Environment.NewLine); prob(rndValues, Min, Max,w); Console.WriteLine(Environment.NewLine); w++; } if (w>0) { while(true) { Console.WriteLine("To change elements in the array press y"); // read input var s = Console.ReadLine(); if(s == "y") { //rndValues[99] = 0; for(int i = 0; i == rndValues.Length; i++) { if (i != rndValues.Length) { rndValues[rndValues.Length-i] = rndValues[(rndValues.Length-i)-1]; } else if (i == rndValues.Length) { rndValues[0] = rndNum.Next(Min, Max); } } } else { break; } prob(rndValues, Min, Max,w); } } } public static void prob(int[] rndValues, int Min, int Max, int w ) { double[] count = new double[rndValues.Length]; //Loop through min to max and count the occurances for (int i = Min; i <Max; i++) { for (int j = 0; j < rndValues.Length; j++) { if (rndValues[j] == i) { count[i] = count[i] + 1; } } } //For displaying output only foreach(var item in rndValues) { Console.Write(item.ToString() + " "); } Console.WriteLine("W " + w); for (int i = Min; i < Max; i++) { count[i] = (count[i] / rndValues.Length) * 100; Console.WriteLine("Probability of the number " + i + " is " + count[i]); } } } } Thanks.