Unity 4 C# - IndexOutOfRangeException: Array index is out of range - c#

Apologies if this is answered somewhere else but I believe my problem is very specific and I haven't got the slightest clue, based on past experience in python, why this code returns the error:
IndexOutOfRangeException: Array index is out of range.
(wrapper stelemref) object:stelemref (object,intptr,object)
MissionGen.Start () (at Assets/Scripts/MissionGen.cs:59)
I am currently in the process of learning C# in the Unity engine, and have created a small class experimentation script designed to generate missions using OOP, selecting target names from an array - but obviously, I have no idea why this won't work. As I believe the equivalent error in python only occurs when I have tried to refrence an array element that doesn't exist. And though this is probably also the case here, due to the way the code is written, I don't understand why. Anyway, here is the full script!:
// Simple mission generation script, using arrays and object orientated programming. Designed to be
// upgraded at a later date.
using UnityEngine;
using System.Collections;
// Mission generation template
public class MissionGen : MonoBehaviour {
public string[] t_list_t = new string[] {"Dave", "Johnson", "Hadaki", "Tim", "Timothy", "Chris Roberts"};
public string[] t_list_c_col = new string[] {"Blue", "Yellow", "Green", "Black", "Orange", "Purple"};
public string[] t_list_h_col = new string[] {"Black", "Green", "Orange", "Blue", "Red", "Brown"};
public class MissionTemplate {
// Mission properties
public int id;
public string t_name;
public string t_coat;
public string t_hat;
public string type;
public int reward1;
public string reward2;
// A method, for displaying the attributes of an individual mission.
public void ShowMission () {
print ("MISSION ID: " + id);
print ("TARGET NAME: " + t_name);
print ("TARGET COAT COLOUR: " + t_coat);
print ("TARGET HAT COLOUR: " + t_hat);
print ("MISSION TYPE: " + type);
print ("REWARD 1 (Money): " + reward1);
print ("REWARD 2 (Item): " + reward2);
}
}
// Mission array generation. Change the array range to generate more missions for use in the game.
void Start() {
// Change this variable to decide how many missions to generate:
int gen = 50;
// Change the above variable to designate the number of missions to generate.
MissionTemplate[] MISSION = new MissionTemplate[gen];
for (int i = 1; i <= gen; i++)
{
int t_pick = Random.Range (0,5);
int t_coat_col = Random.Range (0,5);
int t_hat_col = Random.Range (0,5);
MISSION[i] = new MissionTemplate();
MISSION[i].id = i;
MISSION[i].t_name = t_list_t[t_pick];
MISSION[i].t_coat = t_list_c_col[t_coat_col];
MISSION[i].t_hat = t_list_h_col[t_hat_col];
MISSION[i].type = "Assassination";
MISSION[i].reward1 = 0;
MISSION[i].reward2 = "";
}
for (int i = 1; i <= gen; i++)
{
MISSION[i].ShowMission();
}
}
}
As a breakdown, I believe the problems arise between the following code:
for (int i = 1; i <= gen; i++)
{
int t_pick = Random.Range (0,5);
int t_coat_col = Random.Range (0,5);
int t_hat_col = Random.Range (0,5);
MISSION[i] = new MissionTemplate();
MISSION[i].id = i;
MISSION[i].t_name = t_list_t[t_pick];
MISSION[i].t_coat = t_list_c_col[t_coat_col];
MISSION[i].t_hat = t_list_h_col[t_hat_col];
MISSION[i].type = "Assassination";
MISSION[i].reward1 = 0;
MISSION[i].reward2 = "";
}
for (int i = 1; i <= gen; i++)
{
MISSION[i].ShowMission();
}
}
}
And:
public class MissionGen : MonoBehaviour {
public string[] t_list_t = new string[] {"Dave", "Johnson", "Hadaki", "Tim", "Timothy", "Chris Roberts"};
public string[] t_list_c_col = new string[] {"Blue", "Yellow", "Green", "Black", "Orange", "Purple"};
public string[] t_list_h_col = new string[] {"Black", "Green", "Orange", "Blue", "Red", "Brown"};
Any help would be much appreciated!
Thanks,

This is the problem:
MissionTemplate[] MISSION = new MissionTemplate[gen];
for (int i = 1; i <= gen; i++)
{
...
MISSION[i] = new MissionTemplate();
Aside from violating normal naming conventions, arrays in C# are 0-based - for example, the valid indexes for an array of length 5 are 0, 1, 2, 3 and 4.
So your for loop should be:
for (int i = 0; i < gen; i++)
Or more "obviously correctly" (IMO):
for (int i = 0; i < MISSION.Length; i++)
That makes it obvious to anyone reading the code that you're staying within the bounds of the MISSION array, without having read the array creation statement.

Related

C# function for creating jagged array

I have a problem where I want to create a jagged array. But the size of this jagged array is variable.
Does this work the same way as filling an normal array like this?
int[] terms = new int[400];
for (int runs = 0; runs < 400; runs++)
{
terms[runs] = value;
}
The values I use are defined like this:
public static string[] nodeCassette0 = { "03", "08" };
public static string[] nodeCassette1 = { "04", "09" };
public static string[] nodeCassette2 = { "05", "10" };
public static string[] nodeCassette3 = { "06", "11" };
public static string[] nodeCassette4 = { "07", "12" };
Depending on the size required by the user a new variable nodeCassette needs to be filled according to the required size. The order in which the array is filled is always the same, it starts at 0 and ends at 4.
This should be like that but I don't know how to dynamically create it:
public string[][] nodeCassette =
{
nodeCassette0,
nodeCassette1,
nodeCassette2,
nodeCassette3,
nodeCassette4
};
Here's an example of how to create such a jagged array:
int[] sizes = new int[] { 3, 2, 1, 1, 3 };
int[][] jagged = new int[sizes.Length][];
for (int i = 0; i < sizes.Length; i++)
{
jagged[i] = new int[sizes[i]];
for (int j = 0; j < sizes[i]; j++)
{
jagged[i][j] = (i + 1) * (j + 1);
}
}
That produces:
It's no different with strings:
int[] sizes = new int[] { 3, 2, 1, 1, 3 };
string[][] jagged = new string[sizes.Length][];
for (int i = 0; i < sizes.Length; i++)
{
jagged[i] = new string[sizes[i]];
for (int j = 0; j < sizes[i]; j++)
{
jagged[i][j] = $"{i}_{j}";
}
}
We can use reflexion and Linq.
using System.Reflection;
using System.Linq;
Having this dedicated class to store the arrays by default, as well as initialize a complete list of possible elements, and offer a method to obtain a slice, i.e. a list made up of the first n-elements:
static class DefaultArrays
{
static public string[] NodeCassette0 = { "03", "08" };
static public string[] NodeCassette1 = { "04", "09" };
static public string[] NodeCassette2 = { "05", "10" };
static public string[] NodeCassette3 = { "06", "11" };
static public string[] NodeCassette4 = { "07", "12" };
static public List<string[]> All { get; private set; }
static public List<string[]> Take(int count)
{
return All.Take(count).ToList();
}
static public void Initialize()
{
All = typeof(DefaultArrays).GetFields()
.Where(field => field.FieldType == typeof(string[]))
.OrderBy(field => field.Name.Length)
.ThenBy(field => field.Name)
.Select(field => (string[])field.GetValue(null))
.ToList();
}
static DefaultArrays()
{
Initialize();
}
}
The Initialize method is created this way to possibly allow updating of the entire list in case the arrays are modified at runtime, otherwise the code can be placed directly in the constructor and all arrays marked readonly.
Here is the algorithm for All:
We get all fields of the static class by its type name.
We filter to select only those being of type array of string.
We order by the fields name string length.
Then by this name, thus we finally get for example 1, 2, 30, 40 from 40, 30, 2, 1.
We do a projection to get the reference of the value instead of the field name using it.
And we transform the Linq query into a List<string> object instance to return.
It uses a pseudo-natural numeric sort assuming all arrays are named:
"[same_same][number_without_trailing_left_0]"
Else we can use a custom comparer:
How do I sort strings alphabetically while accounting for value when a string is numeric?
sort string-numbers
Test
var slice = DefaultArrays.Take(3);
string msg = string.Join(Environment.NewLine, slice.Select(item => string.Join(", ", item)));
Console.WriteLine(msg);
Output
03, 08
04, 09
05, 10
Warning
The slice contains a list of references toward original arrays, thus any modification of a cell of an array in this list will be reflected in the matching array in the static class.
Else we need to copy the arrays with Array.Copy instead of using Linq.Take:
static public List<string[]> TakeCopy(int count)
{
var list = new List<string[]>();
foreach ( int index in Enumerable.Range(0, Math.Min(count, All.Count)))
{
int length = All[index].Length;
var array = new string[length];
Array.Copy(All[index], array, length);
list.Add(array);
}
return list;
}

Shuffling Algorithm for Stroop Effect

I'm working on a small C# Winforms application that replicates several visual experiments concerning cognitive psychology. Instead of using premade images, I was trying to create them programmatically to train my skills.
Now I'm working on the Stroop Effect and I'm attempting to reproduce the following image:
I prepared two distinct arrays, one containing the colors and one containing the name of the colors:
Color[] colors =
{
Color.Blue,
Color.Red,
Color.Black,
Color.Green
};
String[] names =
{
"BLUE",
"RED",
"BLACK",
"GREEN"
};
The first step is easy. All I have to do is to draw the strings using their respective ForegroundColor, such that names[0] will be printed using colors[0], names[1] will be printed using colors[1] and so on...
And here comes the hard part of the task. Once the string array has been shuffled:
Random r = new Random();
String[] namesRandom = names.OrderBy(x => r.Next()).ToArray();
I have to shuffle the colors array too. But this must be achieved making sure that no color is being matched with its correct name. So, for example, this will be correct:
"BLACK" Color.Green
"GREEN" Color.Red
"RED" Color.Blue
"BLUE" Color.Black
and this will be wrong:
"BLACK" Color.Black -> Matching Color/Name
"GREEN" Color.Red
"RED" Color.Blue
"BLUE" Color.Green
Any idea about how to accomplish this efficiently? I would like to avoid the shuffle until condition is met approach.
P.S. = drawing strings on a Bitmap is not a problem and I don't need help on this development task.
[EDIT]
For 10k-ers that downvote for not being able to associate the concept of shuffle until condition is met with a few lines of code or because they think I'm trying to get my work done while I play Tetris, here is a quick implementation of my current algorithm:
public class Program
{
private static Random s_Random = new Random();
public static void Main(String[] args)
{
Color[] colors =
{
Color.Blue,
Color.Red,
Color.Black,
Color.Green
};
String[] names =
{
"BLUE",
"RED",
"BLACK",
"GREEN"
};
while (MatchingPairs(colors, names))
{
colors = Shuffle(colors);
names = Shuffle(names);
}
for (Int32 i = 0; i < colors.Length; ++i)
Console.WriteLine(colors[i].Name.ToUpperInvariant() + " | " + names[i]);
}
private static Boolean MatchingPairs(Color[] colors, String[] names)
{
for (Int32 i = 0; i < colors.Length; ++i)
{
if (colors[i].Name.ToUpperInvariant() == names[i])
return true;
}
return false;
}
private static T[] Shuffle<T>(T[] array)
{
return array.OrderBy(x => s_Random.Next()).ToArray();
}
}
So, as you can see, I can use my fingers to type code. I'm just wondering if there is a better approach to obtain the same result.
This is maybe not the best approach, but it should work fine. One way to solve this would be to assign random names until you have only two left (where index i == Count - 2). At that point, if the name of the item at index i + 1 is one of the remaining choices, use that for the item at index i.
Here's some sample code that uses a console application (and ConsoleColor), but the concept is the same. I've used a class that combines a ConsoleColor and a string, so if you want to use arrays it would need some modification.
First the class:
class NamedColor
{
public ConsoleColor Color { get; set; }
public string Name { get; set; }
public NamedColor(ConsoleColor color, string name)
{
Color = color;
Name = name;
}
}
And a method that prints out a list of these objects to the Console:
static void PrintColors(IEnumerable<NamedColor> colors)
{
Console.BackgroundColor = ConsoleColor.Gray;
Console.Write(new string(' ', 80));
foreach (var color in colors)
{
Console.ForegroundColor = color.Color;
Console.Write(color.Name + " ");
}
Console.Write(new string(' ', 139)); // Ugly, hard-coded length for simplicity
}
Then we can create a method that will take a list of these objects, shuffle all the names between them, and return that new list:
static NamedColor[] ShuffleNames(NamedColor[] colors)
{
var names = colors.Select(c => c.Name).ToList();
var shuffled = new NamedColor[colors.Length];
for (int i = 0; i < colors.Length; i++)
{
string name;
// If there are only two items left, and our list of names contains
// the *next* item's name, then we must take that name for this item
if (i == colors.Length - 2 && names.Contains(colors[i + 1].Name))
{
name = colors[i + 1].Name;
}
else
{
// Choose a random name from all names except this item's name
var candidateNames = names.Where(n => !n.Equals(colors[i].Name)).ToList();
name = candidateNames[rnd.Next(candidateNames.Count)];
}
shuffled[i] = new NamedColor(colors[i].Color, name);
names.Remove(name);
}
return shuffled;
}
Then we can shuffle our list, then shuffle the names, and then print out the list like so:
private static Random rnd = new Random();
static void Main(string[] args)
{
var correctColors = new NamedColor[]
{
new NamedColor(ConsoleColor.Blue, "BLUE"),
new NamedColor(ConsoleColor.Black, "BLACK"),
new NamedColor(ConsoleColor.Red, "RED"),
new NamedColor(ConsoleColor.Green, "GREEN"),
};
PrintColors(correctColors);
for (int count = 0; count < 10; count++)
{
// Shuffle the items, then shuffle the names
var shuffledColors = correctColors.OrderBy(c => rnd.NextDouble()).ToArray();
shuffledColors = ShuffleNames(shuffledColors);
PrintColors(shuffledColors);
}
Console.ResetColor();
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output
You could do the following:
Implement a rule of valid colors for each name:
Func<string, IEnumerable<Color>> validColorsRule = s =>
{
switch (s)
{
case "BLUE": return colors.Except(new[] { Color.Blue });
case "RED": return colors.Except(new[] { Color.Red });
case "BLACK": return colors.Except(new[] { Color.Black });
case "GREEN": return colors.Except(new[] { Color.Green });
default: throw new NotSupportedException();
}
};
Build the shuffled Color array with Enumerable.Aggregate:
Color[] colorRandom =
namesRandom.Aggregate(Enumerable.Empty<Color>(),
(acc, n) =>
acc.Concat(new[] {
validColorsRule(n).Except(acc)
.OrderBy(x => r.Next())
.FirstOrDefault() }))
.ToArray();
You could reformulate as a pseudo-random problem.
Generate a random integer between 1 and n-1(say i) and shift the color array(use a copy of it) by that i
Now generate a random sequence between 0 and n-1 without replacement and print the name and color
static void Main(string[] args)
{
ConsoleColor[] colors =
{
ConsoleColor.Blue,
ConsoleColor.Red,
ConsoleColor.Black,
ConsoleColor.Green
};
String[] names =
{
"BLUE",
"RED",
"BLACK",
"GREEN"
};
Random r = new Random();
int i = 0;
while(i==0)
i=r.Next() % (names.Length-1);
List<int> rndList = Enumerable.Range(0,names.Length).OrderBy(x => r.Next()).ToList();
Console.BackgroundColor = ConsoleColor.White;
foreach(int j in rndList)
{
int k = (j+i) % (colors.Length);
Console.ForegroundColor = colors[k];
Console.Write(names[j] + " ");
}
}
I think that you are trying to create a random derangement. A web search for this finds a paper about the efficient generation of such things at http://epubs.siam.org/doi/pdf/10.1137/1.9781611972986.7 - "Generating Random Derangements" by Martinez, Panholzer, and Prodinger. However the paper also shows that, even as n gets possibly very large, the chance of a randomly chosen permutation being a derangement remains very close to 1/e, so the simple solution of just generating a random permutation and checking to see if it is a derangement, repeating until this is true, may in practice be efficient enough for most purposes.

SimpleSpriteSequence and getRandom

I have an Gameobject that contains several prefabs, As in the picture below
public SimpleSpriteSequence birds;
Randomizer setBirds;
setBirds = new Randomizer(birds.sprites);
int index = setBirds.getRandom();
birds.setCurrentSpriteIndex(index);
In the image below we see the population of the array
Invoke("Interface", 1f);
Now with the help of the random I get a random bird from the array. But the problem is that the bird can be repeated. All I want is that at least 6 times in a row when the Invoke("Interface", 1f); function does not repeat the bird.So in principle I have to do so 6 times the bird does not repeat itself. To be a random of these birds but 6 times to be different birds. No I know if I explained it properly, but I hope you understand the idea.
Here is code but it is written in console application since i do not have your code and it is writen with custom class of Birds but you will adapt it to your code. If you need help with it i will help you.
class Birds
{
public int birdID;
public string birdName;
//public Sprite birdSprite;
}
class Program
{
static Random rnd = new Random();
static Birds[] birds = new Birds[10];
static int nBirdsSpawned = 0;
static List<int> spawnedBirds = new List<int>();
static void Main(string[] args)
{
//Database of my birds ;)
birds[0] = new Birds();
birds[1] = new Birds();
birds[2] = new Birds();
birds[3] = new Birds();
birds[4] = new Birds();
birds[5] = new Birds();
birds[6] = new Birds();
birds[7] = new Birds();
birds[8] = new Birds();
birds[9] = new Birds();
birds[0].birdID = 0;
birds[0].birdName = "Bird 1";
birds[1].birdID = 1;
birds[1].birdName = "Bird 2";
birds[2].birdID = 2;
birds[2].birdName = "Bird 3";
birds[3].birdID = 3;
birds[3].birdName = "Bird 4";
birds[4].birdID = 4;
birds[4].birdName = "Bird 5";
birds[5].birdID = 5;
birds[5].birdName = "Bird 6";
birds[6].birdID = 6;
birds[6].birdName = "Bird 7";
birds[7].birdID = 7;
birds[7].birdName = "Bird 8";
birds[8].birdID = 8;
birds[8].birdName = "Bird 9";
birds[9].birdID = 9;
birds[9].birdName = "Bird 10";
int i = 0;
while (i < 100)
{
RandomSpawn();
i++;
}
Console.Write("Finished");
Console.ReadKey();
}
static void CheckForBirdSpawn(int birdID)
{
if (nBirdsSpawned <= 6)
{
if (!spawnedBirds.Contains(birdID))
{
spawnedBirds.Add(birdID);
SpawnBird(birdID);
}
else
{
Console.WriteLine("Bird " + birds[birdID].birdName + " is already spawned!");
}
}
else
{
SpawnBird(birdID);
}
}
static void SpawnBird(int birdID)
{
Console.WriteLine(birds[birdID].birdName);
nBirdsSpawned++;
}
static void RandomSpawn()
{
int r = rnd.Next(0, 10);
CheckForBirdSpawn(r);
}
}
Until first 6 birds are spawned it check if bird is already spawned and if it is it doesn't allow it's spawning. After 6 birds are spawned it allows every bird to be spawned.
Here is output in console app:
I know this is a mainly code reply but how about you try something a little like this?
Populate a list of the bird indexes.
Pick a random index within that list.
Decrease all already spawned birds' Values.
If any reach zero, re-add the birds index into the availableBird list.
Spawn the bird, while adding it's index as Key and the amount of spawning delay needed until it can be spawned again as the Value.
Remove the birds index from the list.
Do the spawn whenever necessary, this will spawn every frame since it is found in a Coroutine which has an infinite while loop.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class burd : MonoBehaviour {
public bool spawning;
private System.Random rnd = new System.Random();
private Dictionary<int, int> spawnedBurdies = new Dictionary<int, int>();
private List<int> availableBurdies = new List<int>();
// Use this for initialization
void Start () {
for (int index = 0; index < 10; index++)
{
availableBurdies.Add(index);
}
StartCoroutine(SpawnBurdies());
}
private IEnumerator SpawnBurdies()
{
while (true)
{
if (spawning)
{
int burdIndex = rnd.Next(availableBurdies.Count);
spawnBurd(availableBurdies[burdIndex]);
availableBurdies.RemoveAt(burdIndex);
}
yield return new WaitForFixedUpdate();
}
}
private void spawnBurd(int burdIndex)
{
Debug.Log("Spawned burd #" + burdIndex);
List<int> burdieKeys = new List<int>();
foreach (var burdie in spawnedBurdies) { burdieKeys.Add(burdie.Key); }
foreach (var burdieKey in burdieKeys)
{
spawnedBurdies[burdieKey]--;
if(spawnedBurdies[burdieKey] <= 0)
{
spawnedBurdies.Remove(burdieKey);
availableBurdies.Add(burdieKey);
}
}
spawnedBurdies.Add(burdIndex, 6);
}
}
This solution would save you from attempting to spawn birds that can't be spawned; but if there are less birds than the minimum spawns to wait for, an Argument out of range error would be thrown.

Unexpected Symbol for Project

I'm having some trouble understanding why "unexpected symbol" exists for my code. I'm using for loops for a project and these few lines of code are giving me problems. I'm guessing it has something to do with not putting brackets/ semi-colins somewhere, but I don't know where it would be. Could I get some help identifying where I need to correct this error?
enter image description here
enter image description here
Here's the full code where the errors exist
// Use this for initialization
void Start()
{
string[] imagesNames = new string[3] { "portrait01", "portrait02", "portrait03" };
//images [0] = CreateSprite ("portrait01");
//images[1] = CreateSprite ("portrait02");
//images[2] = CreateSprite ("portrait03");
string[] professionNames = new string[3] {"Karate fighter", "Ninja Figher", "Samurai Fighter"};
string[] professionDescriptions = new string[3] { "Use hand to hand combat for powerful attacks! Req: Strength = 13 and Special = 10",
"Use high stealth and sneak attacks to suprize you enemies! Req: Speed = 15 or Strength = 9",
"Use your wisdom to reverse attacks with 2x the power! Req: Wisdom = 14 or Special = 13" };
string[] professionImageNames = new string[3] { "profession01", "profession02", "profession03"};
int[] [] minRequirements = { new int [3] {11, 11, 12}, new int[3] {11,13,12}, new int[3] {11,11,16} };
professions = new Profession[3]
for (int i = 0; i < 3; i++)
{
professions[i] = CreateProfession (name[i], description[i], profimages[i], minRequirements[i]);
}
for (int i = 0; i < professionNames.Length; i++) //this starts at least one of the loops
{
profession[i] = createItem(professionNames[i], professionDescriptions[i], professionImageNames[i], minRequirements[i]);
}
//profession01 = createItem("Karate Fighter", "Use hand to hand combat for powerful attacks!", "portrait01");
//profession02 = createItem("Ninja Fighter", "Use high stealth and sneak attacks to suprize you enemies!", "portrait02");
//profession03 = createItem("Samurai Fighter", "Use your wisdom to reverse attacks with 2x the power!", "portrait03");
for (int i = 0; i < imagesNames.Length; i++) //creates a for loop for the images
{
images[i] = CreateSprite(imagesNames[i]); //makes it so the images come from CreatSprite
//array
}
portraitImage.sprite = images[currentImage]; //renders the current images
profession.characterManager = this;
for (in i = 0; i < minRequirement.Length; i++) {
profession.requirements [i] = profession.CreateRequirement { Attribute [i], minRequirement[i];
}
return profession;
}
You are missing a ; on this line:
professions = new Profession[3]
These types of errors should be pretty apparent, usually you always want to inspect the line above the first error, missing a semi-colon is probably the most common programming "error", and it was a lot worse before IDE's highlighted error lines.
The second error, as pointed out by Lazy Coder, is a missing t on the last for loop:
for (int i = 0; i < minRequirement.Length; i++)
Again, should be apparent from reviewing the errors. It should be giving an error "Identifier expected; 'in' is a keyword"
// Use this for initialization
void Start()
{
string[] imagesNames = new string[3] { "portrait01", "portrait02", "portrait03" };
//images [0] = CreateSprite ("portrait01");
//images[1] = CreateSprite ("portrait02");
//images[2] = CreateSprite ("portrait03");
string[] professionNames = new string[3] {"Karate fighter", "Ninja Figher", "Samurai Fighter"};
string[] professionDescriptions = new string[3] { "Use hand to hand combat for powerful attacks! Req: Strength = 13 and Special = 10",
"Use high stealth and sneak attacks to suprize you enemies! Req: Speed = 15 or Strength = 9",
"Use your wisdom to reverse attacks with 2x the power! Req: Wisdom = 14 or Special = 13" };
string[] professionImageNames = new string[3] { "profession01", "profession02", "profession03"};
int[] [] minRequirements = { new int [3] {11, 11, 12}, new int[3] {11,13,12}, new int[3] {11,11,16} };
professions = new Profession[3] //WERE IS THE PROFESSION CLASS CREATED?
//PROFESSIONS NEEDS TO HAVE A TYPE var profession = new Proffession[3];
for (int i = 0; i < 3; i++)
{
professions[i] = CreateProfession (name[i], description[i], profimages[i], minRequirements[i]); //CreateProffession is not implemented on your example, the signature could be like public Profession CreateProfession(string name, string description des, string proofImage, int[] minRequirement)
}
for (int i = 0; i < professionNames.Length; i++) //this starts at least one of the loops
{
//DID YOU MEAN professions
profession[i] = createItem(professionNames[i], professionDescriptions[i], professionImageNames[i], minRequirements[i]);
}
//profession01 = createItem("Karate Fighter", "Use hand to hand combat for powerful attacks!", "portrait01");
//profession02 = createItem("Ninja Fighter", "Use high stealth and sneak attacks to suprize you enemies!", "portrait02");
//profession03 = createItem("Samurai Fighter", "Use your wisdom to reverse attacks with 2x the power!", "portrait03");
for (int i = 0; i < imagesNames.Length; i++) //creates a for loop for the images
{
//DID YOU MEAN imagesNames
images[i] = CreateSprite(imagesNames[i]); //makes it so the images come from CreatSprite
//array
}
portraitImage.sprite = images[currentImage]; //renders the current images //WHERE IS currentImage created?
profession.characterManager = this;
//FOR is for(int i=0 , int with t
for (in i = 0; i < minRequirement.Length; i++) {
profession.requirements [i] = profession.CreateRequirement { Attribute [i], minRequirement[i];
}
return profession;
}

C# assigning value to array

I'm trying to write a program that would shuffle 13 playing cards from ace to king. Deal 2 cards out and add up the value that's assigned to each card. ace = 11, king = 10, jack = 10, queen = 10, ten = 10, nine = 9, eight = 8 and so on... sort of like blackjack.
so far I'm only able to shuffle the cards and print out two cards randomly but i don't know how to assign a value to each card, add them up and print it out. example, if my two random cards is King and Eight then i would want the program to print out..
King
Eight
18
here's what i got...
static void Main(string[] args)
{
string[] Cards = new string[] {"Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "jack", "Queen", "King", "Ace"};
for (int x = 0; x < 100; x++) // looping the shuffle 100 times to maximize the randomness
{
for (int i = Cards.Length; i > 0; i--) //shuffle
{
string temp;
Random random = new Random();
int r = random.Next(i);
temp = Cards[r];
Cards[r] = Cards[i-1];
Cards[i-1] = temp;
}
}
Console.WriteLine(Cards[0]); //first random card
Console.WriteLine(Cards[1]); //second random card
Console.ReadKey();
}
For a great example of programming a card game, do a google search for KarliCards from the book Beginning Visual C# 2012 (you can easily find a full PDF, but I won't post a link because I'm not sure if it's legal). It has lots of stuff like how to use regular operators (+) on things like classes or structs.
Anyway, what you're looking for is an enum. It's very similar to the Dictionary(string)(int) suggested by Rob (I'm not sure how to write triangle brackets). Here's an example of how it works:
enum CardValue
{
One = 1,
Two = 2,
Three = 3,
Four = 4
}
static void Main(string[] args)
{
int myInt = (int)CardValue.One;
Console.WriteLine("output should be 1: " + myInt);
int mySum = (int)CardValue.One + (int)CardValue.Three;
Console.WriteLine("output should be 4: " + mySum);
Console.ReadKey();
}
My first language was Perl, so I tend to see everything as a struct instead of a class. There's always more than one way to do it....
public enum CardSuits
{
Clubs,
Spades,
Hearts,
Diamonds
}
public enum CardValues
{
Ace = 1,
Two = 2,
Three = 3,
Four = 4
}
public struct Card
{
public CardValues Value; // Card.Value = CardValues.Ace
public CardSuits Suit; // Card.Suit = CardSuits.Spades
public override string ToString()
{
// Card.ToString() == "Ace of Spades"
return String.Format(Value + " of " + Suit);
}
public string ToStringAsInteger()
{
// Card.ToStringAsInteger() == "1 of Spades"
return String.Format((int)Value + " of " + Suit);
}
}
static void Main(string[] args)
{
Card AceOfSpades = new Card();
AceOfSpades.Value = CardValues.Ace;
AceOfSpades.Suit = CardSuits.Spades;
Card TwoOfClubs = new Card();
TwoOfClubs.Value = CardValues.Two;
TwoOfClubs.Suit = CardSuits.Clubs;
int mySum = (int)AceOfSpades.Value + (int)TwoOfClubs.Value;
Console.WriteLine("Sum of Ace (1) and Two (2) is: " + mySum); // should be 3
Console.WriteLine("output of AceOfSpades.ToString() is: " + AceOfSpades.ToString());
Console.WriteLine("output of AceOfSpades.ToStringAsInteger is: " + AceOfSpades.ToStringAsInteger());
Console.ReadKey();
}
Here's how I would do this:
var cards = new Dictionary<string, int>()
{
{ "Two", 2 }, { "Three", 3 }, { "Four", 4 }, { "Five", 5 }, { "Six", 6 },
{ "Seven", 7 }, { "Eight", 8 }, { "Nine", 9 }, { "Ten", 10 }, { "Jack", 10 },
{ "Queen", 10 }, { "King", 10 }, { "Ace", 11 },
};
var random = new Random();
var selected = cards.OrderBy(c => random.Next()).Take(2).ToArray();
foreach (var card in selected)
{
Console.WriteLine(card.Key);
}
Console.WriteLine(selected.Sum(c => c.Value));
Running this, I get (for example):
Two
Ten
12
Now, just for a bit more info on your existing code.
Calling Random random = new Random(); within a loop will result in many (if not all) of the random numbers being the same. You should use a single instance of Random only.
There is no need for the for (int x = 0; x < 100; x++) loop as a single pass of the for (int i = Cards.Length; i > 0; i--) loop is sufficient to randomize the cards.

Categories

Resources