How to remove array element from user entered array - c#

HI I'm creating a menu driven program that holds three arrays: one for the person's last name, one for the points scored and one for the player number. I made a deletemethod and deleteplayer method that is suppose to when the user enters a players number delete the player number, last name and points from the user entered list but when I use the delete method it clears the entire list. I am not sure on on how to fix this. I also have to keep the program in the main class.
Any Help would be appreciated please and thank you
static void ProcessDelete( Int32[] playerNumbers, ref Int32 playerCount, String[] playerLastName, Int32[] playerPoints)
{
Int32[] newArray = new Int32[playerNumbers.Length]; String[] newArray2 = new String[playerLastName.Length]; Int32[] newArray3 = new Int32[playerPoints.Length];
int index = Array.IndexOf(playerNumbers, 0);
{
for (int i = 0; i < playerNumbers.Length; i++)
playerNumbers[i] = 0;
}
// String[] playerLastName = new String[] { null, null, null };
for (int i = 0; index < playerLastName.Length; index++)
playerLastName[i] = " ";
for (int i = 0; i < 10; i++)
{
//Console.WriteLine(newArray2[i]);
}
for (int i = 0; i < playerPoints.Length; i++)
playerPoints[i] = 0;
}
static void DeletePlayer(Int32[] playerNumbers, String[] playerLastName, Int32[] playerPoints, ref Int32 playerCount, Int32 MAXPLAYERS)
{
int player;// Player number to delete
int playerindex;//index of the player number in Array
if (playerCount < MAXPLAYERS)
{
player = GetPositiveInteger("\nDelete Player: please enter the player's number");
playerindex = GetPlayerIndex(player, playerNumbers, playerCount);
if (playerindex != -1)
{
{
Console.WriteLine("\nDelete Player: Number - {0}, Name - {1}, Points - {2}", playerNumbers[playerindex], playerLastName[playerindex], playerPoints[playerindex]);
Console.WriteLine("Succesfully Deleted");
Console.WriteLine();
ProcessDelete( playerNumbers, ref playerCount, playerLastName, playerPoints);
}
}
else
Console.WriteLine("\nDelete Player: player not found");
}
else
Console.WriteLine("\nDelete Player: the roster is empty");
}
}
}

In an object-oriented language, you would generally create a class to capture this information.
Let me know if you need any explanation because, as always, there's more than one way to do this.
Updated with CurrentScore, AddPlayerToGame() function, and incrementing playercount
class Program {
static void Main(string[] args) {
//Create firstPlayer
Player firstPlayer = new Player {
PlayerId = 1,
DisplayName = "Goober",
LastName = "Smith"
};
// Create secondPlayer
Player secondPlayer = new Player {
PlayerId = 2,
DisplayName = "Destructor",
LastName = "Henry"
};
// Create game instance
Game currentGame = new Game();
// Add players to game
currentGame.AddPlayerToGame(firstPlayer);
currentGame.AddPlayerToGame(secondPlayer);
// Player scores a point
secondPlayer.CurrentScore++;
// Player clicks LeaveGame, etc.
currentGame.PlayerLeavesGame(firstPlayer);
}
}
public class Player {
public int PlayerId { get; set; } // I assume the same as player numbers
public string DisplayName { get; set; }
public string LastName { get; set; }
public int CurrentScore { get; set; }
}
public class Game {
private static readonly int MAXPLAYERS = 10;
public Game() {
Players = new List<Player>();
}
public List<Player> Players { get; private set; }
private int _PlayerCount = 0;
public int PlayerCount {
get {
return _PlayerCount;
}
set {
_PlayerCount = value;
}
}
/// <summary>
/// Tries to add a player to the game
/// </summary>
/// <param name="playerThatJoinedGame"></param>
/// <returns>True if the player was added and the game wasn't full</returns>
public bool AddPlayerToGame(Player playerThatJoinedGame) {
if (PlayerCount < MAXPLAYERS) {
Players.Add(playerThatJoinedGame);
PlayerCount++;
return true;
}
else {
return false;
}
}
/// <summary>
/// Removes a player from the game
/// </summary>
/// <param name="playerThatQuit">The leaving player</param>
public void PlayerLeavesGame(Player playerThatQuit) {
// Removes the player from the game
Players.Remove(playerThatQuit);
PlayerCount--;
}
}

If all the information in the lists is logically related why aren't you using Lists or Dictionaries?
Something like this:
using System.Collections.Generic;
class Player{
public int Number;
public string LastName;
public int Points;
}
class PlayerManager{
static Dictionary<int,Player> dctOfPlayers= new Dictionary<int, Player>();
public static AddNewPlayer(Player newPlayer){
dctOfPlayers.Add(newPlayer.Number,newPlayer);
}
public static RemovePlayer(int playerNumber){
dctOfPlayers.Remove(playerNumber);
}
}
You could use a list of Players and make loops to find the user ID too...
Also if for any reason you want to preserve the Player entry and just reset the information then you can:
using System.Collections.Generic;
class Player{
public int Number;
public string LastName;
public int Points;
public ResetInfo(){
Number=0;
LastName="";
Points=0;
}
}
class PlayerManager{
static Dictionary<int,Player> dctOfPlayers= new Dictionary<int, Player>();
public static AddNewPlayer(Player newPlayer){
dctOfPlayers.Add(newPlayer.Number,newPlayer);
}
public static RemovePlayer(int playerNumber){
dctOfPlayers[layerNumber].ResetInfo();
}
}

Related

I get an index out of range error but not sure why? [duplicate]

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed 1 year ago.
Hi I'm doing something in C# and I've ran into an index out of range error and I don't get why. I have a list with objects that hold a string. User gets to add a number of string values and thus filling the list with that same number of objects. When I later try to access the list elements using a for loop it gives me the index out of range error! This is a parody of my code that basically sums it up:
class game
{
public List<Player> PlayerList = new List<Player>();
public List<Player> Playerlist
{
get { return PlayerList; }
}
public static int PlayerCount = 0;
public void PlayGame()
{
Console.WriteLine("ENTER NUMBER OF PLAYERS: ");
PlayerCount = int.Parse(Console.ReadLine());
for (int n = 1; n < PlayerCount + 1; n++)
{
Console.WriteLine("ENTER NAME FOR PLAYER " + n + ":");
PlayerList.Add(new Player() { PlayerName = Console.ReadLine() });
}
Player playeraccess = new Player();
playeraccess.AddTurns();
}
public class Player
{
private static int throw1;
public int Throw1
{
get { return throw1; }
set { throw1 = value; }
}
private static int throw2;
public int Throw2
{
get { return throw2; }
set { throw2 = value; }
}
private static int throw3;
public int Throw3
{
get { return throw3; }
set { throw3 = value; }
}
int firstruncheck = 0;
int turnloop = 0;
int turncounter = 0;
List<Turns> playerturn = new List<Turns>();
public Player(string playername = "")
{
PlayerName = playername;
}
public string PlayerName { get; set; }
public override string ToString()
{
return base.ToString();
}
public void AddTurns()
{
game gameaccess = new game();
for(turnloop = 0; turnloop < game.PlayerCount; turnloop++)
{
gameaccess.Playerlist[turnloop].playerturn.Add(new Turns());
On This last line I get an index out of range error. But it shouldn't happen since User has added elements into PlayerList, right?
You are creating a new player list with every instance of game but keeping track of the count in a static variable (one instance of the count for all instances of the game).
To fix this you should decide whether you are keeping track of players per game (non-static list and count) or per run of your program (static list and count). For the latter, read up on static constructors.

How to swap out a sprite in Unity2D based on a Dictionary entry?

I'm very new to Unity and programming in C# altogether, so apologies if this is a little elementary;
Basically I want to change a sprite in my game for 10 seconds, and then change back to the original sprite. I have stored this sprite in a dictionary entry, as well as the sprites that I wish to change to in a List. I create these dictionary entries with a loop that filters in the correct name for the sprites and other entry values based on our position in the loop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class PaddleAbilities : MonoBehaviour
{
public Dictionary<string, Ability> AbilitiesDictionary = new Dictionary<string, Ability>();
[Header("GUI Sprites")]
public List<Sprite> abilitySprites;
[Header("Ability Costs")]
public int Q_Cost;
public int W_Cost;
public int E_Cost;
public int R_Cost;
[Header("Ability Cooldowns")]
public float Q_Cooldown;
public float W_Cooldown;
public float E_Cooldown;
public float R_Cooldown;
//ability ready timers
public bool Q_Ready = true;
public bool W_Ready = true;
public bool E_Ready = true;
public bool R_Ready = true;
//access Scripts
[Header("Other")]
public GameManager gameManager;
public Paddle paddle;
public int Score;
public string thisPlayer;
private Vector2 Position;
void Awake()
{
//get our Game Objects
gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
paddle = this.gameObject.GetComponent<Paddle>();
//Get resource position
Position = this.gameObject.transform.position;
}
void Start()
{
//which player is this script assigned to?
if (Position.x < 0)
{
thisPlayer = "P1";
Score = gameManager.scoreValueP1;
}
else if (Position.x > 0)
{
thisPlayer = "P2";
Score = gameManager.scoreValueP2;
}
for (int i = 1; i < 5; i++)
{
int Cost = 0;
switch (i)
{ case 1:
Cost = Q_Cost;
break;
case 2:
Cost = W_Cost;
break;
case 3:
Cost = E_Cost;
break;
case 4:
Cost = R_Cost;
break;
}
float Cooldown = 0;
switch (i)
{ case 1:
Cooldown = Q_Cooldown;
break;
case 2:
Cooldown = W_Cooldown;
break;
case 3:
Cooldown = E_Cooldown;
break;
case 4:
Cooldown = R_Cooldown;
break;
}
if(thisPlayer == "P1")
{
string P1Name = "Ability" + i + "_P1";
AbilitiesDictionary.Add(P1Name, new Ability(P1Name, GameObject.Find(P1Name).GetComponent<SpriteRenderer>().sprite, Cost, Cooldown));
}
else if (thisPlayer == "P2")
{
string P2Name = "Ability" + i + "_P2";
AbilitiesDictionary.Add(P2Name, new Ability(P2Name, GameObject.Find(P2Name).GetComponent<SpriteRenderer>().sprite, Cost, Cooldown));
}
}
}
public class Ability
{
public string SpriteName { get; set; }
public Sprite AbilitySprite { get; set; }
public int AbilityCost { get; set; }
public float AbilityCooldown { get; set; }
public Ability(string spriteName, Sprite abilitySprite, int abilityCost, float abilityCooldown)
{
this.SpriteName = spriteName;
this.AbilitySprite = abilitySprite;
this.AbilityCost = abilityCost;
this.AbilityCooldown = abilityCooldown;
}
}
void Update()
{
AbilitiesRead();
if (thisPlayer == "P1")
{
Score = gameManager.scoreValueP1;
}
else if (thisPlayer == "P2")
{
Score = gameManager.scoreValueP2;
}
}
//Key press check gets called in update
public void AbilitiesRead()
{
if (Input.GetKeyDown(KeyCode.Q) && Q_Ready && Score >= AbilitiesDictionary["Ability1_" + thisPlayer].AbilityCost)
{
Debug.Log(thisPlayer + " attempted to spawn a ball.");
StartCoroutine(ServeBall());
}
}
//ENUMERATORS v
private IEnumerator SkillDuration(float WaitTime)
{
//Debug.Log("Skill is active. Waiting for skill to deactivate.");
yield return new WaitForSeconds(WaitTime);
}
private IEnumerator ServeBall()
{
gameManager.serveTowards = paddle.Opponent; //make sure we serve at our opponent when this ability is called
gameManager.SpawnBall(1); //spawn a Ball (the ball will use this paddle.Opponent to determine which direction to go in.)
Q_Ready = false; //this ability is now on cooldown.
Score -= AbilitiesDictionary["Ability1_" + thisPlayer].AbilityCost; //deduct our Ability Cost
AbilitiesDictionary["Ability1_" + thisPlayer].AbilitySprite = abilitySprites[1]; //swap out Q_sprite for this player to the greyscale version "Q_Ability_onCooldown.psd"
yield return StartCoroutine(SkillDuration(AbilitiesDictionary["Ability1_" + thisPlayer].AbilityCooldown)); //WaitForSeconds for the amount of time we want to cooldown for.
AbilitiesDictionary["Ability1_" + thisPlayer].AbilitySprite = abilitySprites[0]; //swap out Q_sprite for this player to the color version "Q_Ability.psd"
Q_Ready = true; //this ability is now ready to be used again.
}
}
Here are my sprites in the Hierarchy. I was able to confirm that my dictionary entry DOES find the sprites, but when I set that entry equal to the sprite in the list that I want to change to, nothing happens on the Unity side of things.
Ability Sprites in Hierarchy
AbilitiesDictionary.Add(P1Name, new Ability(P1Name, GameObject.Find(P1Name).GetComponent<SpriteRenderer>().sprite, Cost, Cooldown));
Instead of referencing the sprite itself, you should reference the SpriteRenderer and exchange the sprite of the SpriteRenderer like this:
In your AbilityClass reference the Renderer:
public class Ability
{
public string SpriteName { get; set; }
public SpriteRenderer AbilitySprite { get; set; }
public int AbilityCost { get; set; }
public float AbilityCooldown { get; set; }
public Ability(string spriteName, Sprite abilitySprite, int abilityCost, float abilityCooldown)
{
this.SpriteName = spriteName;
this.AbilitySprite = abilitySprite;
this.AbilityCost = abilityCost;
this.AbilityCooldown = abilityCooldown;
}
}
Add the Renderer to your Class
if(thisPlayer == "P1")
{
string P1Name = "Ability" + i + "_P1";
AbilitiesDictionary.Add(P1Name, new Ability(P1Name, GameObject.Find(P1Name).GetComponent<SpriteRenderer>(), Cost, Cooldown));
}
Exchange the sprite:
AbilitiesDictionary["Ability1_" + thisPlayer].AbilitySprite.sprite = abilitySprites[1];
The code is untested so no guaratee there are no spelling errors ;)

C# Assigning to strings from a public class and list

so far my code does the following.
Ask user for a numeric amount for 'players'
Then asks for names for each of the players which is added to a list and class
I'd like to call those names from the list or class (not really sure how class works) and assign it to a new string. Here's what I got so far:
public class NameVariable
{
public int ID { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
bool IsUserWrong = false;
Console.WriteLine("Write amount of players");
while (!IsUserWrong)
{
int TotalPlayers;
while (!Int32.TryParse(Console.ReadLine(), out TotalPlayers))
{
Console.WriteLine("Value must be numeric.");
}
if (TotalPlayers >= 12 && TotalPlayers <= 16)
{
List<NameVariable> PlayerList = new List<NameVariable>();
for (int index = 0; index < TotalPlayers; index++)
{
Console.WriteLine("Enter player {0}'s name:", index + 1);
PlayerList.Add(new NameVariable
{
Name = Console.ReadLine(),
ID = index
});
}
// string player1 = ???
// string player2 = ???
// and so on for 12-16 players
}
else
{
Console.WriteLine("Please enter a value between 12 and 16.");
}
}
}
}
I know that a foreach loop can be used to display all of the variables in the NameVariable class. Would just like to know how to assign each variable to a different string.
Before using the class I just used the list which worked by using
string player1 = PlayerList[0];
string player2 = PlayerList[1];
// and so on for the remaining players
Thanks in advance!
it's just
string player1 = PlayerList[0].Name;
string player2 = PlayerList[1].Name;
...
Essentially your list contains NameVariable objects. PlayerList[index] gives you the object, and .Name gives you the property value of the object.
If you want a specific player name by a specific ID number, you can use LINQ (just to give you a hint)
string player = PlayerList.Where(p => p.ID == WhateverIDNumber).First().Name;
While the answer to your immediate question, i.e., how to access properties of a class object, is as others have shown, I feel like this code has a bigger problem. That is you're trying to do too much in one function, namely, Main(). So I advice to in fact try and refactor your code so that one function does one thing. Something like:
public static int GetNumberOfPlayers()
{
Console.Write("Enter number of players: ");
int totalPlayers;
while (!Int32.TryParse(Console.ReadLine(), out totalPlayers))
{
Console.WriteLine("Value must be numeric.");
}
return totalPlayers;
}
public static List<NameVariable> GetPlayerList(int num)
{
var list = new List<NameVariable>();
for (int i = 0; i < num; i++)
{
Console.WriteLine("Enter player {0}'s name:", i + 1);
list.Add(new NameVariable
{
Name = Console.ReadLine(),
ID = i
});
}
return list;
}
public static void DisplayPlayers(List<NameVariable> list)
{
foreach(var player in list)
{
Console.WriteLine("Player {0}, Name: {1}", player.ID, player.Name);
}
}
public static void CantThinkOfAGoodName()
{
while (true)
{
int totalPlayers = GetNumberOfPlayers();
if (totalPlayers > 16 || totalPlayers < 12)
{
Console.WriteLine("Please enter a value between 12 and 16.");
}
else
{
var playerList = GetPlayerList(totalPlayers);
DisplayPlayers(playerList);
break;
}
}
}
public static void Main()
{
CantThinkOfAGoodName();
Console.ReadLine();
}
Not sure if it helps but you can use an indexer to get players by name.
public NameVariable this[string name]
Let's say you create a class for the colection
public class NameColection : List<NameVariable>
{
public NameVariable this[string name]
{
get
{
return this.FirstOrDefault(n => n.Name == name);
}
}
}
Then you access players by name
var players = new NameColection()
{
new NameVariable() { ID = 1 , Name = "John" },
new NameVariable() { ID = 2 , Name = "Paul" },
new NameVariable() { ID = 3 , Name = "George" },
new NameVariable() { ID = 4 , Name = "Ringo" }
};
var player1 = players["John"];
As NameColection inhertits from List, you will be able to add, remove or modify items the usual way.

How to set properties in the same class?

I am having difficulties setting the values of certain variables. In my GameController class I want the user to input the number of players. I then want my code to create an array that will hold scores for each of the players.
class Program
{
static void Main(string[] args)
{
Game GC = new Game();
GC.GetNumberPlayers();
GC.SetInitialScores();
}
}
class Game
{
private int players;
private int[] scores;
private string[] playerNames;
public int Players
{
get { return players; }
set { players = value; ; }
}
public int[] Scores
{
get { return scores; }
set { scores = value; }
}
public int GetNumberPlayers()
{
string playersString;
Console.WriteLine("Enter number of players");
playersString = Console.ReadLine();
Int32.TryParse(playersString, out players);
return players;
}
public int[] SetInitialScores()
{
for (int i = 0; i < players; i++ )
{
scores[i] = 0;
}
return scores;
}
}
A few things:
GetNumberPlayers returns an integer, you are not doing anything with it due to calling it as GC.GetNumberPlayers();
If you wanted to have the value of GetNumberPlayers(), you would need to call it like int numPlayers = GC.GetNumberPlayers();
Since you are setting players value in your try parse, there is not really any reason to return it since you're using it only internally (or if you were using it externally by assigning it to a variable as in above)
The same holds true for your function SetInitialScores, with an additional problem. Arrays need their length to be declared as a part of their initialization. You are not initializing the array at all, and are thus running into a run time error. You could initialize the array based on the value entered in players like this:
public void SetInitialScores()
{
scores = new int[players];
for (int i = 0; i < players; i++ )
{
scores[i] = 0;
}
}
Here's a Fiddle demonstrating: https://dotnetfiddle.net/JmHsLQ
and the fully modified code:
public class Program
{
public static void Main(string[] args)
{
Game GC = new Game();
var players = GC.GetNumberPlayers();
var scores = GC.SetInitialScores();
Console.WriteLine("You entered {0} players!", players);
Console.WriteLine("Printing scores");
foreach (int val in scores)
{
Console.WriteLine(val);
}
}
}
public class Game
{
private int players = 0;
private int[] scores;
private string[] playerNames;
public int Players
{
get { return players; }
set { players = value; ; }
}
public int[] Scores
{
get { return scores; }
set { scores = value; }
}
public int GetNumberPlayers()
{
string playersString;
Console.WriteLine("Enter number of players");
playersString = Console.ReadLine();
Int32.TryParse(playersString, out players);
return players;
}
public int[] SetInitialScores()
{
scores = new int[players];
for (int i = 0; i < players; i++ )
{
scores[i] = 0;
}
return scores;
}
}

Give an Array a Value

I am trying to make a game where an image appears, and if it is not clicked the image should disappear. I need help giving my array a value of three, then subtract it in another method.
Code:
NameCount = -1;
NameCount++;
Grid.SetColumn(mole, ranCol);
Grid.SetRow(mole, ranRow);
grid_Main.Children.Add(mole);
for (int i = 0; i < NumofImages; i++)
{
//Where I must give a value to the array of the array to 3 for every image that appears.
}
//Where I am trying to make the image disappear after 3 seconds.
private void deleteMole()
{
NumofImages = TUtils.GetIniInt(Moleini, "NumPictures", "pictures", 8);
NumberofImages = Convert.ToInt32(NumofImages);
for (int j = 0; j < NumofImages; j++)
{
CounterArray[j]--;
if (CounterArray[j] == 0)
{
//Not Sure How to delete image
Thanks for the help!
You could keep track of the images in another array.
After you add the image to the view you should also add it to the array:
images[j] = mole;
Then later:
if (CounterArray[j] == 0)
{
grid_Main.Children.Remove(images[j]);
}
But using static arrays and separating data is not a good idea.
If you can you should better aggregate all the metadata and the image together in the same structure:
class Mole
{
public int Counter { get; set; }
public Control Image { get; set; }
}
and manage them in a single List<Mole>; adding and removing them will be simpler.
Here is some code that illustrates the idea (won't compile):
class Mole
{
public int X { get; set; }
public int Y { get; set; }
public int Counter { get; set; }
public Control Image { get; set; }
public bool IsNew { get; set; }
}
class Test
{
IList<Mole> moles = new List<Mole>();
private static void AddSomeMoles()
{
moles.Add(new Mole{ X = rand.Next(100), Y = rand.Next(100), Counter = 3, Image = new PictureBox(), IsNew = true });
}
private static void DisplayMoles()
{
foreach (Mole mole in moles)
{
if (mole.IsNew)
{
grid_Main.Children.Add(mole.Image);
mole.IsNew = false;
}
}
}
private static void CleanupMoles()
{
foreach (Mole mole in moles)
{
mole.Counter -= 1;
if (mole.Counter <= 0)
{
grid_Main.Children.Remove(mole.Image);
moles.Remove(mole);
}
}
}
static void Main()
{
while (true)
{
AddSomeMoles();
DisplayMoles();
Thread.Sleep(1000);
CleanupMoles();
}
}
}
If you want to give every element in a List a certain value, use a foreach loop. In this case, it would look like:
foreach(int currentElement in CounterArray)
{
currentElement = 3;
}
This will loop through each element of the List and set it to 3.
EDIT: If you're using an array, which you are, you would do the following:
for (int i = 0; i < CounterArray.Length; i++)
{
CounterArray[i] = 3;
}

Categories