Do different things on each iteration of a loop c# - c#

I am making a game for children on the Sifteo Cubes. I am trying to load a sentence on the cubes, word by word. I have some experience with the Sifteo Cubes but how can I solve this in a more beautiful way? More generic if that's possible.
foreach (CubeWrapper wrapper in mWrappers) {
if (i == 0) {
wrapper.setWord (w1);
} else if (i == 1) {
wrapper.setWord (w2);
} else if (i == 2) {
wrapper.setWord (w3);
} else if (i == 3) {
wrapper.setWord (w4);
} else if (i == 4) {
wrapper.setWord (w5);
}
i++;
}
I will always add w1 to the first wrapper and so on.
Any help would be appreciated!

You can do the following:
String[] words = new String[] {w1,w2,w3,w4,w5};
foreach (CubeWrapper wrapper in mWrappers)
{
wrapper.setWord(words[i++]);
}
This solution is working, but keep in mind, if the words array is smaller than the mWrappers collection you will receive a IndexOutOfBoundsException. So syncing the access to the array is now your work.

If you can't\don't want to change your class then you could use reflection to do something like this (Even though it's probably not the right thing to do here):
foreach (CubeWrapper wrapper in mWrappers) {
var name = "w" + (i+1).ToString();
var value = this.GetType().GetProperty(name).GetValue(this);
wrapper.setWord(value);
}
Example:
public class ABC
{
public int w1 { get; set; }
public int w2 { get; set; }
public int w3 { get; set; }
public ABC()
{
w1 = 7;
w2 = 8;
w3 = 9;
}
public void DoSomething()
{
var i = 1;
var name = "w" + (i + 1).ToString(); // w2
var value = (int)this.GetType().GetProperty(name).GetValue(this);
DoSomething(value);
}
public void DoSomething(int curr)
{
Console.WriteLine(curr); // 8
}
}
Usage:
ABC abc = new ABC();
abc.DoSomething();

You can get a random word from the array, using Random class like this...
String[] words = new String[] { "w1", "w2", "w3", "w4", "w5" };
Random r = new Random(0);
int randomNumber = r.Next(0, words.Length);
foreach (CubeWrapper wrapper in mWrappers)
{
wrapper.setWord(words[randomNumber]);
}

Related

Need to change values in classes without changing its reference

I am currently making an application which tracks information on players and monsters for a tabletop game.
Currently I've got classes for "Monsters". This class contains information such as its name, maxHP, speed, attacks etc. I've managed to make a Database which contains the default values for each type of monster. What I currently need to do is make it possible to change things such as name (Monster > Monster 1, Monster 2 etc), change its HP, and some other things.
I understand that I need to make a copy of such, but I am uncertain on how to do this.
What I currently tried is the following:
public class DatabaseService
{
public List<Player> Players { get; set; }
public List<Monster> AllMonsters { get; set; }
public List<Monster> ActiveMonsters = new List<Monster>();
public bool RollForHP = false;
//Main Database Service
public DatabaseService()
{
Players = GetPlayers();
AllMonsters = GetAllMonsters();
}
public void DoStuff()
{
AddMonsterByName("Goblin", 2);
AddMonsterByName("Adult White Dragon", 1);
AddMonsterByName("Duergar", 4);
foreach (Monster monster in ActiveMonsters) { Console.WriteLine(monster.Name); }
}
//Converts the .json list with all players to Classes, which are then stored in the list "Players" if the "IsInParty" is true
private List<Player> GetPlayers()
{
var path = #"C:\Users\MyName\source\repos\DndAdvancedInitiativeTracker\Logic\Database\Players.json";
var json = File.ReadAllText(path);
var players = JsonConvert.DeserializeObject<List<Player>>(json);
List<Player> inPartyPlayers = new List<Player>();
foreach (var player in players)
{
if (player.IsInParty == true) { inPartyPlayers.Add(player); }
}
return inPartyPlayers;
}
//Converts the .json list with all monsters to Classes, which are then stored in the list "AllMonsters"
private List<Monster> GetAllMonsters()
{
var path = #"C:\Users\MyName\source\repos\DndAdvancedInitiativeTracker\Logic\Database\Monsters.json";
var json = File.ReadAllText(path);
var monsters = JsonConvert.DeserializeObject<List<Monster>>(json);
return monsters;
}
//Adds a given monster to the "ActiveMonsters" list
public void AddMonsterByName(string monsterName, int amountOfMonsters)
{
for (int i = 0; i < amountOfMonsters; i++)
{
List<Monster> DatabaseCopy = AllMonsters.Clone();
DatabaseCopy = AllMonsters;
Monster monster = DatabaseCopy.Find(x => x.Name == monsterName);
Console.WriteLine(monster.Name);
var number = CheckIfNameExistsInList(monsterName);
monster.Name = monsterName + " " + (number + i).ToString();
ActiveMonsters.Add(monster);
}
}
private int CheckIfNameExistsInList(string monsterName)
{
var counter = 1;
foreach (var monster in ActiveMonsters)
{
if (monster.Name.Contains(monsterName))
{
counter += 1;
}
}
return counter;
}
}
In the "DoStuff" Method, I try to add 2 goblins, then a dragon, then a goblin again. The first goblin is named to "Goblin 1" correctly, but the second loop fails, because the AllMonsters' name for goblins is now "Goblin 1" because of the reference type, therefore, the second "Goblin" search in AllMonsters is never found, and returns null.
I'm not sure why you're copying your database (and doing so for every iteration of a for loop which is quite wasteful), but your current check code CheckIfNameExistsInList will always return 1 even if there are no matches in the list.
You can simplify your AddMonstersByName (and use a simple check for previous monster entries) as follows:
public void AddMonstersByName(string name, uint number = 1)
{
var count = AllMonsters.Count(x => x.Name.Contains(name));
for (var i = 1; i <= number; i++)
{
var num = count + i;
AllMonsters.Add(new Monster(){Name= name+num.ToString()});
}
}
This was tested in a simple Console App:
var dataService = new DataService();
dataService.AddMonstersByName("Goblin", 2);
dataService.AddMonstersByName("Dragon", 2);
dataService.AddMonstersByName("Goblin", 2);
foreach (var monster in dataService.AllMonsters)
{
Console.WriteLine($"{monster.Name}");
}
where
public class DataService
{
public List<Monster> AllMonsters = new List<Monster>();
public void AddMonstersByName(string name, uint number = 1)
{
var count = AllMonsters.Count(x => x.Name.Contains(name));
for (var i = 1; i <= number; i++)
{
var num = count + i;
AllMonsters.Add(new Monster(){Name= name+num.ToString()});
}
}
}
public class Monster
{
public string Name { get; set; }
}

I want to ask in the if statement if the cake is baked how do I do that in single-dimensional array? I'm stuck

using System;
namespace ConsoleApp12
{
class Cake
{
private string cakeType;
private int weight;
private bool baked;
public Cake(string cakeType, int weight)
{
this.cakeType = cakeType;
this.weight = weight;
this.baked = true;
}
public Cake(string cakeType, int weight, bool baked)
{
this.cakeType = cakeType;
this.weight = weight;
this.baked = baked;
}
public Cake(int weight)
{
this.cakeType = "chocolate";
this.weight = weight;
this.baked = true;
}
public string IsBaked()
{
int count = 0;
Cake[] CakeArr = new Cake[3];
for (int i = 0; i < CakeArr.Length; i++)
{
if (/* if cake is baked */)
{
return "The Cake is indeed baked...";
}
else
{
count++;
}
}
return "There are: " + count + " not baked cakes...";
}
public string GetCakeType() { return this.cakeType; }
public int GetWeight() { return this.weight; }
public bool GetBaked() { return this.baked; }
public void SetBaked(bool baked) { this.baked = baked; }
public void Sold(int weight) { this.weight -= weight; }
}
class Program
{
static void Main(string[] args)
{
Cake c1 = new Cake(1800);
Cake c2 = new Cake("cheese", 1200, false);
Cake c3 = new Cake("chocolate", 2100, true);
c1.Sold(400);
if (c1 == c3)
Console.WriteLine("aaa");
else
Console.WriteLine("bbb");
c3.Sold(700);
if (c1 == c2 || c2 == c3)
Console.WriteLine("ccc");
else
if (c1 == c3)
Console.WriteLine("ddd");
c1.Sold(1400);
c2.SetBaked(c1.GetBaked());
if (c2.GetBaked())
Console.WriteLine("eee");
Console.WriteLine(c2.IsBaked());
}
}
}
I did everything I need but I do not know how to make the system check if the cake is baked in an if statement...
It doesnt matter what everything else do like the other methods because they all supposed to work anyways I just need to find a solution to the method IsBaked in the class Cake.
Please help, thank you.
Assuming you want to check how many of c1, c2, c3 are baked, you might want to create an extension method:
public static class MyCakeExtensionMethods{
public static string HowManyAreNotBaked(this Cake[] cakeArr ){
int count = 0;
for (int i = 0; i < cakeArr.Length; i++)
{
if (!cakeArr[i].GetBaked())
{
count++;
}
}
if( count == 0){
return "all cakes are baked";
return "There are: " + count + " not baked cakes...";
}
}
Note that the body could be mostly simplified to CakeArr.Count(c => c.GetBaked());
But there are other issues with your code:
You should probably be using properties instead of get/set methods
You should probably not allow the cake type to be changed after creation. Unless you found some way to transform a cheese-cake into a chocolatecake in the real world.
You should probably change SetBaked(bool baked) into Bake(), since you cannot un-bake a cake.
You should probably add a check to Sold to ensure you cannot sell more cake than there is.

Processing int to name of list

I try to write a simple console application with Hanoi towers. But I am stuck at one point.
In my program I ask a person to write from to which tower wants to put the disk, but: I have 3 lists as towers, I'll ask for a number from gamer and now how I can build a "compare method"? Because I don't want to copy the same piece of code 6 times...
class Towers : Disks
{
//public Towers(int Value, int WhereItIs) : base(Value, WhereItIs) { }
public List<Disks> Tower1 = new List<Disks>();
public List<Disks> Tower2 = new List<Disks>();
public List<Disks> Tower3 = new List<Disks>();
public void Compare(int dyskFrom, int dyskWhere) {
}
public void Display() {
foreach(var i in Tower1){
Console.WriteLine("Where: {0} | Value: {1}", i.WhereItIs, i.Value);
}
}
public void Build(int TowerHigh) {
for (int i = TowerHigh; i > 0; i--) {
Tower1.Add(new Disks {Value = i, WhereItIs = 1 });
}
}
}
class Disks
{
public int Value; //wartosc krazka
public int WhereItIs; //na ktorej wiezy sie on znajduje
}
class Program
{
static void Main(string[] args)
{
Towers Tower = new Towers();
int TowerHigh;
Console.Write("Podaj wysokość wieży: ");
TowerHigh = int.Parse(Console.ReadLine());
Tower.Build(TowerHigh);
Tower.Display();
Tower.Compare(1, 2);
}
}
It's easier to create an array of Stack<Disk>(). This way you can select a tower by index.
I would use a Stack, because thats typically the functionality you need.
Something like: PSEUDO (typed in browser, no syntax checked)
class Disk
{
public int Size {get; set;}
}
static void Main(string[] args)
{
// create the Stack<Disk> array
Stack<Disk>[] towers = new Stack<Disk>[3];
// create each tower
for(int i=0;i<towers.Length;i++)
{
towers[i] = new Stack<Disk>();
// fill the towers.
for(int j=3;j>0;j--)
towers[i].Enqueue(new Disk { Size = j });
}
bool isHoldingDisk = false;
while(true)
{
DisplayTowers(towers);
if(isHoldingDisk)
Console.WriteLine("On what tower do you want to place it?");
else
Console.WriteLine("Choose a tower to pick a disk");
var key = Console.ReadKey(true);
var chosenTowerIndex = 0;
switch(key)
{
case(Key.Escape):
break;
case(Key.D1):
chosenTowerIndex = 0;
break;
case(Key.D1):
chosenTowerIndex = 1;
break;
case(Key.D1):
chosenTowerIndex = 2;
break;
// etc...
}
if((chosenTowerIndex < 1) || (chosenTowerIndex >= towers.Length))
continue;
// check here if you are holding a disk
if(isHoldingDisk)
{
// logic for testing if you can place the disk here...
// using towers[chosenTowerIndex]
// check if it is completed...
if(completed)
break;
isHoldingDisk = false;
}
else
{
// check if you can pickup a disk....(if there is any)
isHoldingDisk = true;
}
}
// final display...
DisplayTowers(towers);
Console.WriteLine("Thanks for playing");
}
static void DisplayTowers(Stack<Disk>[] towers)
{
// draw some fancy asc-ii art...
}

Creating list/array of class instances?

I'm fairly new to C# and I have just learned about creating custom classes. The problem is, I can't figure out how to take the 40~65 instances of this class and put them in a list/array (whichever one I need) where I can locate and choose one based on an attribute defined in it.
Here's the class I have created right now:
public class Team
{
protected int teamNum;
protected double averageMatchPoints;
protected string location;
protected int matchesPlayed;
protected int matchesPending;
protected int blowouts;
//Team Number
public void SetNumber(int num)
{
teamNum = num;
}
public int GetNumber()
{
return teamNum;
}
//Average Points per match
public void AverageMatchPoints(double p)
{
averageMatchPoints = p;
}
public double GetAverageMatchPoints()
{
return averageMatchPoints;
}
//location information
public void SetLocation(string l)
{
location = l;
}
public string GetLocation()
{
return location;
}
//Number of Played Matches
public void PlayedMatches(int mat)
{
matchesPlayed = mat;
}
public int GetPlayedMatches()
{
return matchesPlayed;
}
//Number of matches pending (not played)
public void PendingMatches(int pen)
{
matchesPending = pen;
}
public int GetPendingMatches()
{
return matchesPending;
}
//Number of Blowouts (matches where the robot was disbaled for any number of reasons)
public void SetBlowouts(int b)
{
blowouts = b;
}
public int GetBlowouts()
{
return blowouts;
}
}
Now, if I had 40~65 of these teams competing at an event and I made an instance of this class for each one, how would I populate a combobox with each team number (teamNum) and then locate one specific team out of all the instances in the program by their team numbers?
I recommend a dictionary!
// Declared somewhere
private Dictionary<int, Team> _teamDictionary = new Dictionary<int, Team>();
.
.
.
//Initialization code - I assume you have gotten your teams from a database or somewhere?
foreach (var team in myTeamsList)
{
_teamDictionary.Add(team.teamNum, team);
}
.
.
.
// Later when you want to locate a team:
var team = _teamDictionary[selectedTeamNum];
Have you tried creating a List yet?
List<Team> Teams { get; set; }
You can then bind your combobox to the list/collection/IEnumerable of all the teams that you have. To initialize the teams up to 40/60 do the following?
for(int i = 0; i < 60; i++)
{
Team t = new Team();
t.Name = "Team 1";
t.TeamNumber = i + 1;
Teams.Add(t);
}
List<Team> allTheTeams = new List<Team>();
for(var i = 0; i < 65; i++){
allTheTeams.Add(new Team { teamNum = i });
}
And to get the team with number 34:
allTheTeams.FirstOrDefault(x => x.teamNum == 34);
Like this:
Add a constructor to your class that takes the teamnumber:
(this is the best solution if every team needs to have a number. So you can not forget to set the team number as you can not create an object of type team without setting the number in the constructor)
public class Team
{
protected int _teamNum;
public Team(int teamNum)
{
_teamNum = teamNum;
}
public int getTeamNum()
{
return _teamNum;
}
//more logic
}
Populate a dictionary, the comboBox and get a team for its number:
Dictionary<int, Team> dictionary = new Dictionary<int, Team>();
int teamNum = 1;
// Add your Teams to a dictionary (example)
dictionary.Add(teamNum ,new Team(teamNum++));
dictionary.Add(teamNum, new Team(teamNum++));
dictionary.Add(teamNum, new Team(teamNum++));
// Populate a comboBox
foreach(KeyValuePair<int,Team> kvp in dictionary)
{
comboBox1.Items.Add(kvp.Value.getTeamNum().ToString());
}
// get a team for a given teamNumer
int targetTeamNumber = 2;
if (dictionary.ContainsKey(targetTeamNumber))
{
Team team = dictionary[targetTeamNumber];
// do something with the team
}

Get a count of items with a certain condition within a StackPanel's Children

I have an custom UserControl I created
public class MyObject : UserControl
{
public MyObject()
{
}
public bool IsFinished { get; set; }
}
I added lets say 10(will be dynamic) MyObject's to a StackPanel and every other item i set IsFinished to true.
private void DoSomething()
{
StackPanel panel = new StackPanel();
for (int i = 0; i <= 10; i++)
{
int rem = 0;
Math.DivRem(i, 2, out rem);
MyObject newObj = new MyObject();
if (rem == 0)
{
newObj.IsFinished = true;
}
panel.Children.Add(newObj);
}
}
Now I can add the following and get the answer I am looking for (5)
int FinishedItems = 0;
foreach (object o in panel.Children)
{
if (o.GetType() == typeof(MyObject))
{
if (((MyObject)o).IsFinished)
{
FinishedItems++;
}
}
}
2 Questions:
A. Is there a more eloquent way? maybe with Linq I'm still learning how to use that. From what I understand, that is what LINQ technically does.
B. Am I wrong about LINQ?
So you want to count the finished items:
int FinishedItems = panel.Children.OfType<MyObject>()
.Count(mo => mo.IsFinished);
You may try:
int FinishedItems = panel.Children.OfType<MyObject>().Where(mo=>mo.IsFinished).Count();

Categories