StackOverFlow Exception while creating objects in C# - c#

I am trying to display the details of the movie but I am getting StackOverFlow exception in cast class where I am returning actorNames array.
I am trying to make the movie object. In movie object, I am creating objects for Cast and Genre class and passing them in movie class constructor with the data.
Kindly let me know how I can correct this issue. This issue might exist for Genre class as well. Please let me know if there is any case like that as well.
// Genre Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment_4
{
class Genre
{
private static Dictionary<string, string> genre = new Dictionary<string, string>();
public string[] genreName { get { return genreName; } set { } }
public string[] genreDescription { get { return genreDescription; } }
public Genre() {
setGlobalGenreDictionary();
}
public Genre(string[] nameOfGenre) {
this.genreName = nameOfGenre;
setGenreDecsription(nameOfGenre);
}
public void setGenreDecsription(string[] genreName) {
int i = 0;
foreach(KeyValuePair<string, string> gen in genre) {
if (gen.Key == genreName[i]) {
genreDescription[i] = gen.Value;
}
i++;
}
}
public void setGlobalGenreDictionary() {
genre.Add("Action", "Associated with particular types of spectacle (e.g., explosions, chases, combat)");
genre.Add("Adventure", "Implies a narrative that is defined by a journey (often including some form of pursuit) and is usually located within a fantasy or exoticized setting. Typically, though not always, such stories include the quest narrative. The predominant emphasis on violence and fighting in action films is the typical difference between the two genres.");
genre.Add("Animation", "A film medium in which the film's images are primarily created by computer or hand and the characters are voiced by actors. Animation can otherwise incorporate any genre and subgenre and is often confused as a genre itself");
genre.Add("Comedy", "Defined by events that are primarily intended to make the audience laugh");
genre.Add("Drama", "Focused on emotions and defined by conflict, often looking to reality rather than sensationalism.");
genre.Add("Fantasy", "Films defined by situations that transcend natural laws and/or by settings inside a fictional universe, with narratives that are often inspired by or involve human myths. The genre typically incorporates non-scientific concepts such as magic, mythical creatures, and supernatural elements.");
genre.Add("History", "Films that either provide more-or-less accurate representations of historical accounts or depict fictional narratives placed inside an accurate depiction of a historical setting.");
genre.Add("Horror", "Films that seek to elicit fear or disgust in the audience for entertainment purposes.");
genre.Add("Noir", "A genre of stylish crime dramas particularly popular during the 1940s and '50s. They were often reflective of the American society and culture at the time.");
genre.Add("Science Fiction", "Films are defined by a combination of imaginative speculation and a scientific or technological premise, making use of the changes and trajectory of technology and science. This genre often incorporates space, biology, energy, time, and any other observable science.");
genre.Add("Thriller", "Films that evoke excitement and suspense in the audience. The suspense element found in most films' plots is particularly exploited by the filmmaker in this genre. Tension is created by delaying what the audience sees as inevitable, and is built through situations that are menacing or where escape seems impossible.");
genre.Add("Western", "A genre in which films are set in the American West during the 19th century and embodies the \"spirit, the struggle and the demise of the new frontier.\" These films will often feature horse riding, violent and non-violent interaction with Native-American tribes, gunfights, and technology created during the industrial revolution.");
}
}
}
//Movie Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment_4
{
class Movie
{
int movieId;
string movieTitle;
string storyline;
double rating;
int year;
Cast cast;
Genre genre;
public Movie(int id, string title, string story, double rating, int yr, Cast castObj, Genre genObj) {
movieId = id;
movieTitle = title;
storyline = story;
this.rating = rating;
year = yr;
this.cast = castObj;
this.genre = genObj;
}
public void getMovie() {
Console.WriteLine("Movie:" + this.movieTitle + "\n"
+ "Year:" + this.year + "\n"
+ "IMDB Rating:" + this.rating + "/10\n "
+ "Storyline:" + this.storyline );
Console.WriteLine("Cast:");
try
{
int noOfMembers = this.cast.actorNames.Length;
for (int i = 0; i < noOfMembers; i++)
{
Console.WriteLine(cast.roles + ":" + cast.actorNames);
}
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
}
int noOfGenres = this.genre.genreName.Length;
for (int i = 0; i < noOfGenres; i++)
{
Console.WriteLine(this.genre.genreName + ":" + this.genre.genreDescription);
}
}
}
}
//Cast Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment_4
{
class Cast
{
public string[] actorNames {
get
{
return actorNames;
}
set { } }
public string[] roles { get { return roles; } set { } }
int referenceToMovie;
public Cast(string[] actorNames, string[] roles, int reference) {
this.actorNames = actorNames;
this.roles = roles;
this.referenceToMovie = reference;
}
}
}
//Main Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment_4
{
class Program
{
static void Main(string[] args)
{
string castNames = "Kenneth Branagh,Patrick Doyle,Chris Hemsworth,Natalie Portman";
string castRoles = "Director,Music,Actor,Actor";
string genresOfTheMovie = "Action,Adventure,Fantasy";
Movie thor = new Movie(0800369, "Thor", "The powerful but arrogant god Thor is cast out of Asgard to live amongst humans in Midgard (Earth), " +
"where he soon becomes one of their finest defenders.", 7.0, 2011, new Cast(castNames.Split(','), castRoles.Split(','), 0800369), new Genre(genresOfTheMovie.Split(',')));
thor.getMovie();
//Movie ironman = new Movie();
//Movie hulk = new Movie();
//Movie avengers = new Movie();
//Movie blackPanther = new Movie();
}
}
}

There are many issues with your code:
Genre:
you set a global genre Dictionary on every initialization of Genre. This means you'll be adding all of the items every time Genre you try to create a Genre.
private static Dictionary<string, string> genre = new Dictionary<string, string>();
//make this static
public static void SetGlobalGenreDictionary()
and then call it
Genre.SetGlobalGenreDictionary();
in your program
For your properties, they are what is causing your StackOverflow issue.
There are a couple of ways to write these, but your version will keep calling itself causing the stack overflow.
//Option 1:
public string[] GenreName1 { get; set; }
//Option 2:
private string[] genreName2;
public string[] GenreName2 {
get
{
return genreName2;
}
set
{
//you have to write a Set method body if you write a get method. Otherwise nothing will happen. If you don't want to set it, don't write a set method at all.
genreName2 = value;
}
}
There are other issues, but this should get you started on your homework problem.

Related

Breadth First Search Algorithm Does Not Work Results in Infinite Loop

I am trying to do a BFS search where I dynamically create the Nodes of the graph as I search the State Space. I followed the book but it does not work the frontier keeps on running and the explored set stays at the start value only. Please help, I have been stuck here for 4 days. Still a beginner programmer.
Problem Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
internal class Problem
{
public State start { get; set; }
public State end { get; set; }
public string[] action = { "UP", "LEFT", "DOWN", "RIGHT" };
public Problem(State x, State y)
{
start = x;
end = y;
}
public State Result(State s , string a)
{
State up;
if (a == "UP" && s.X - 1 >= 0)
{
up = new State(s.X - 1, s.Y);
}
else if (a == "LEFT" && s.Y - 1 >= 0)
{
up = new State(s.X, s.Y-1);
}
else if (a == "DOWN" && s.X + 1 < 5)
{
up = new State(s.X, s.Y+1);
}
else if( a == "RIGHT" && s.Y + 1 < 11)
{
up = new State(s.X + 1, s.Y);
}
return up;
}
public bool GoalTest(Node<State> goal)
{
if (goal.Data.Equals(end))
{
return true;
}
return false;
}
}
}
Search Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
internal class Search
{
public void BFS(Problem p)
{
Queue<Node<State>> frontier = new Queue<Node<State>>();
HashSet<string> explored = new HashSet<string>();
List<Node<State>> nNodes = new List<Node<State>>();
Node<State> root = new Node<State>() {Data = p.start,};
frontier.Enqueue(root);
while(frontier.Count > 0)
{
Node<State> next = frontier.Dequeue();
if(!explored.Add(next.Data.Data)) continue;
next.Children = new List<Node<State>>();
foreach(string action in p.action)
{
next.Children.Add(new Node<State>() { Data = p.Result(next.Data, action), Parent = next });
}
for(int i = 0; i < next.Children.Count; i++)
{
if (p.GoalTest(next.Children[i]) == true)
{
//Solution(next.Children[i]);
break;
}
frontier.Enqueue(next.Children[i]);
}
}
}
public void Solution(Node<State> n)
{
while(n.Parent != null)
{
Console.WriteLine(n.Parent.Data);
}
}
}
}
Node Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
internal class Node<T>
{
public T Data { get; set; }
public Node<T>? Parent { get; set; }
public List<Node<T>> Children { get; set; }
}
}
State Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
internal class State
{
public int X { get; set; }
public int Y { get; set; }
public string Data { get; }
public State(int x, int y)
{
X = x;
Y = y;
Data = $"{X}-{Y}";
}
}
}
Main Program
using Test;
State start = new State(0, 1);
State end = new State(3, 7);
Problem p = new Problem(start, end);
Search s = new Search();
s.BFS(p);
This is actually for my assignment hence I named it test.
I am trying to implement the pseudocode from here: (Page 82)
https://zoo.cs.yale.edu/classes/cs470/materials/aima2010.pdf
Update
It does not stuck now but it does not input anything into the console after the loop runs it is supposed to get the links between the goal node and the start node via the "Parent property".
You are never checking if nodes are already explored, so you will likely enter an infinite loop:
explored.Add(next.Data.Data);
should be
if(!explored.Add(next.Data.Data)) continue;
But there might be other problems with the code. I would highly recommend reading Eric Lipperts article How to debug small programs since problems like this should be fairly easy to find and fix yourself with the help of a debugger. Learning how to use a debugger is an invaluable skill that will make troubleshooting much easier.
I would also recommend removing all the strings from your program. Instead you should create type representing a coordinate, i.e. a Point, or vector2Int. I would recommend making this a readonly struct, and add ToString overload, IEquality<Point> implementation, operators for addition subtraction, equality etc. This type could then be used both for representing the state, and to represent the offsets. Such a type would be reusable for all kinds of different projects.

How to store values of different types in a single Structure

I have a text file in that has a list of strings (Example 6|Chicago|Illinois|I-98;I-90). I am trying to create two Classes. One class (CityReader) reads the text file and other file prints it. I declared a class(CityItem) with 4 variables, int population, string city, string state, List<int> Interstates.
In the CityReader class I created a CityItem Object(CIObj) and was able to read the file and delimit it and returning CIObj. But when I access this object from a different class I am only seeing the last line in the text file. This object is not returning all the values.
I realized though I am reading the file in each loop. I am not storing those values and hence the object is holding only the last object.
CityItem Class-----
using System;
using System.Collections.Generic;
using System.Text;
namespace ReadingAtxtFile
{
public class CityItem
{
public int Population { get; set; }
public string City { get; set; }
public string State { get; set; }
public List<int> Interstates = new List<int>();
}
}
CityReader Class-----
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
namespace ReadingAtxtFile
{
public class CityReader
{
public CityItem ReadCities(string FilePath)
{
CityItem CIObj = new CityItem();
var AllLines = File.ReadAllLines(FilePath, Encoding.UTF8);
try
{
foreach (var item1 in AllLines)
{
string[] EachLine = item1.Split('|');
CIObj.Population = Convert.ToInt32(EachLine[0]);
CIObj.City = EachLine[1];
CIObj.State = EachLine[2];
string[] IStates = EachLine[3].Split(';');
foreach (var item2 in IStates)
{
var IStatesAfterSplit = item2.Split("-");
CIObj.Interstates.Add(Convert.ToInt32(IStatesAfterSplit[1]));
}
}
}
catch (Exception)
{
Console.WriteLine("There is an issue with processing the data");
}
return CIObj;
}
}
}
Input TextFile:
6|Oklahoma City|Oklahoma|I-35;I-44;I-40
6|Boston|Massachusetts|I-90;I-93
8|Columbus|Ohio|I-70;I-71
I am trying to process the text file and print the data as I like. For example. population
Population,
City, State,
Interstates: I-35,I-40,I-45 (Sorted order)
Your ReadCities method needs to return some kind of collection of CityItem objects, not just a single CityItem object. .Net supports various kinds of collections, but a List is probably best for this instance.
Then, after populating your CityItem object, before moving to the next iteration of the loop, add the CityItem object to your List. Something like...
List<CityItem> listOfCityItems = new List<CityItem>();
foreach (var line in AllLines)
{
CityItem ci = new CityITem();
// Populate the properties of ci
listOfCityItems.Add(ci);
}

Passing arguments by referencing parameters stored in a struct object

I'm new to programming and C#; I don't quite understand how to pass arguments with structs and could use some help in getting this code to work..
I'm making a program to test working with structs & methods.
I'm trying to make two methods..
My displayStudent() method is supposed to take the Student type parameters from the newStudent object/instance created by the CreateStudent_Click.
CreateStudent_Click() Method grabs the user input from three TextBoxes(nameOfStudent, studentID, studentsMajor) and concatenates them to be one string(Output) which is displayed on a fourth outputTextBox after the mouse click on Create Student button.
Myy CreateStudent_Click(), is supposed to get the user input and put it into a new object/instance of Student type as well as pass an argument to DisplayStudent(newStudent) as well as call it.
Any help you can provide would be very much appreciated. Thank you.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Student_Structure
{
struct Student
{
public string name;
public string studentID;
public string major;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
private void displayStudent(ref Student student)
{
try
{
student.name = nameTextBox.Text;
student.studentID = studentIDTextBox.Text;
student.major = majorTextBox.Text;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void CreateStudent_Click(object sender, EventArgs e)
{
// Declare a string to hold a line of output.
string output;
// Create an instance of student.
Student newStudent = new Student();
newStudent.name = nameTextBox.Text;
newStudent.studentID = studentIDTextBox.Text;
newStudent.major = majorTextBox.Text;
// Clear the TextBoxes
nameTextBox.Clear();
studentIDTextBox.Clear();
majorTextBox.Clear();
displayStudent(Student.newStudent());
// Clear the TextBox's current contents.
foreach (Student student in newStudent)
{
}
}
}
Firstly (and this is just a rule of thumb) structs should be Immutable. Now there is 1000's of blogs on the internet that debate this and why and its best to read up on this.
However, by default they are mutable. Yet on saying that, there are a lot of mutable structs used in the framework like Point, Size, Rectangle. These structs are fully mutable. This is done (against the guidelines) for the sake of performance, as it avoids the need to create new values for modification operations.
...All that aside, if you are passing a mutable struct in a parameter (unlike a reference type) what you get is a copy. Nothing you do will make any difference unless you pass by ref.
Given a Mutable struct
public struct Student
{
public Student(string name, int studentId, string major)
{
Name = name;
StudentId = studentId;
Major = major;
}
public string Name { get; set; }
public int StudentId { get; set; }
public string Major { get; set; }
public override string ToString() => Name + ", " + StudentId + ", " + Major;
}
You can simply pass by reference
private void MutateStudent(ref Student student)
{
student.Name = "asd";
student.StudentId = 234;
student.Major = "ertyt";
}
or
private Student AbetterMutateStudent(Student student)
{
// this is actually a copy
student.Name = "asd";
student.StudentId = 234;
student.Major = "ertyt";
return student;
}
Example
var student = new Student("SomeName",1,"SomeMajor");
Console.WriteLine(student);
MutateStudent(ref student);
Console.WriteLine(student);
var student2 = AbetterMutateStudent(student);
Console.WriteLine(student2);
Output
SomeName, 1, SomeMajor
ByrRefName, 2, ByrRefMajor
ByCopyName, 3, ByCopyMajor

switching gender pronouns in strings and unums

I'm making a game that involves with the players choice of gender and want to reflect the dialogue of the player's choice with the correct pronouns. I was thinking of using boolean but was advice not to as it seems kind of bad making one of the genders to be true and the other to be false. So trying to use enums on this but my only problem is how to implement it correctly and have it working. Haven't really used enums that much before to be use for strings.
This is what I have so far:
public class UITextBoxScript : MonoBehaviour
{
public Text mytext;
enum Gender
{
None, Male, Female
}
enum States
{
Instructions, Warning, YourGender, Test
}
Gender playerGender = Gender.None;
Gender playersGender = Gender.Male;
Gender playGender = Gender.Female;
int gender = 0; // using 0 or 1 (or 0, 1, 2.. if you might ever have 'unset')
string[] heshe = { "he", "she" };
string[] hisher = { "his", "her" };
string[] himher = { "him", "her" };
Then this is the target area of where it should hit and affect the user's choice:
void state_YourGender()
{
mytext.text = "Okay!" +
"\n" +
"\n" +
"What is your love interest gender?" +
"\n" +
"\n" +
"\n" +
"\n" +
"A) Male" +
"\n" +
"\n" +
"S) Female";
timer -= Time.deltaTime;
if (Input.GetKeyDown(KeyCode.A))
{
myState = States.Test;
gender = 0;
Gender playersGender = Gender.Male;
}
else if (Input.GetKeyDown(KeyCode.S))
{
myState = States.Test;
}
}
void state_Test()
{
string phrase=" _heshe_was really happy";
string newPhrase = phrase.Replace("_HESHE_", heshe[gender]);
timer -= Time.deltaTime;
if (timer <= 0 && Input.GetKeyDown(KeyCode.Space))
{
timer = timerVal;
myState = States.YourGender;
}
}
I have been trying to experiment and find a way to call out the string to return to me but the string itself is not returning at all. I'm also using mytextbox and the area of a small box for the dialogue to show up and it has been working fine; no issues there. Any advice or tips?
Using enums to store exclusive values like gender is a good idea, but there are a few design decisions in your code that are not good ideas. First, you already have four global variables just to store one player's gender roles. That's already too many, and will get worse with every player or NPC you add. Instead, create a class for storing people:
public class Person
{
public string Name { get; private set; }
public Gender Gender { get; private set; }
public Gender LoveInterestGender { get; private set; }
public Person(string name, Gender gender, Gender loveInterestGender)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name));
Name = name;
Gender = gender;
LoveInterestGender = loveInterestGender;
}
}
Beginners are strangely reluctant to create new classes. Don't be; that is the main way you will simplify your code. Now you can create your player through code or a UI:
var player = new Person(name: "Hiro Protagonist", gender: Gender.Male, loveInterestGender: Gender.Female);
It's also a bad idea to try to customize dialog using string replacement; often you want to change the actual dialog, not just replace every “he” with “she” or such. You need to specify rules for dialogs to follow. For example, we could specify a different rule for each dialog depending on the gender of the speaker and listener. How do you do that? With another class, of course. Though, for reasons I won't go into, in this particular case a readonly struct would be better:
public struct DialogSpecifier : IEquatable<DialogSpecifier>
{
public readonly Gender SpeakerGender;
public readonly Gender ListenerGender;
public DialogSpecifier(Gender speakerGender, Gender listenerGender)
{
SpeakerGender = speakerGender;
ListenerGender = listenerGender;
}
public bool Equals(DialogSpecifier other)
{
return SpeakerGender==other.SpeakerGender
&& ListenerGender==other.ListenerGender;
}
}
Okay, so now we have people, and rules for dialogs. How do we make people speak to each other using these rules? We could write a bunch of code for each person for each rule for each gender. Wow, that's a lot of code! How do we simplify code again? Oh yeah, create a class:
public class Dialogue
{
Dictionary<DialogSpecifier, string> specifiedDialog = new Dictionary<DialogSpecifier, string>();
public Dialogue(string noneToNone)
{
specifiedDialog.Add(new DialogSpecifier(Gender.None, Gender.None), noneToNone);
}
public Dialogue Add(DialogSpecifier specifier, string dialogue)
{
specifiedDialog.Add(specifier, dialogue);
return this;
}
public string OpeningGambit(Person speaker, Person listener)
{
string gambit;
if (specifiedDialog.TryGetValue(new DialogSpecifier(speakerGender: speaker.Gender, listenerGender: listener.Gender),
out gambit))
return gambit;
return specifiedDialog[new DialogSpecifier(Gender.None, Gender.None)];
}
}
Okay, so now let's create some people and dialogues:
var introduction = new Dialogue("Hello")
.Add(new DialogSpecifier(Gender.Male, Gender.Male), "Wassup?");
var npc = new Person(name: "Juanita Marquez", gender: Gender.Female, loveInterestGender: Gender.Male);
var gambit = introduction.OpeningGambit(player, npc);
Simple, right? That's because we created classes and didn't try to write code for every possible permutation. This is easily extensible, too; we can Add gambits for different situations, or change specifiedDialog to a Dictionary<DialogSpecifier, List<string>> so we can have a list of gambits instead of a single one for each specifier. We could add more rules to DialogSpecifier, for example to behave differently if the listener is the speaker's LoveInterestGender. Doing that only requires changing one class; you don't have to rewrite all your code every time you add something.

Using a ComboBox as filter

I have made a program that is a kind of a wiki, but in a program. I've added lots of pictureBoxes, and I have 3 filters to sort those pictureBoxes: ROLE, ATTACK TYPE and NAME.
What I'd like to do is, like, if you select the Attack Type RANGED it disables the other pictureBoxes that has a different Attack Type than RANGED.
I've tried comparing each Hero (I've made a different class for it) with a timer, but I didn't know how to do it.
I also tried this
if(comboBox1.Text == "RANGED") { //do stuff }
But I don't know how could I access all of the heroes inside an array I made, and check if they have atkType = RANGED.
My Hero.cs class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace WindowsFormsApplication1
{
public struct Hero
{
public string Name;
public string Role; /* carry, disabler, lane support, initiator, jungler, support, durable, nuker, pusher, escape */
public string atkType; /* melee or ranged */
public string Type; /* strength, agility or intelligence */
public string imgName;
public Hero(string name, string role, string atktype, string type, string imgname)
{
Name = name;
Role = role;
atkType = atktype;
Type = type;
imgName = imgname;
}
public static Hero[] heroes = new Hero[] {
new Hero() {Name = "test", Role = "", atkType = "Melee", Type = "Strength", imgName = "test" }
};
}
}
I've managed to get the filter working, but now, there's only a problem: I can't dispose (images wont unload) the current loaded images and can't load new ones.
What I tried:
if (melee == false && ranged == false)
{
for (int i = 0; i < Hero.heroes.Length; i++)
{
imgs[i].Load("http://cdn.dota2.com/apps/dota2/images/heroes/" + Hero.heroes[i].imgName + "_sb.png");
comboBox3.Items.Add(Hero.heroes[i].Name);
//imgs[i].MouseHover += displayInfo(i);
}
}
if (ranged == true)
{
for (int i = 0; i < Hero.heroes.Length && Hero.heroes[i].atkType.Contains("Ranged"); i++)
{
imgs[i].Image.Dispose();
imgs[i].Load("http://cdn.dota2.com/apps/dota2/images/heroes/" + Hero.heroes[i].imgName + "_sb.png");
}
}
The code could be something like this:
if(cmb.text=="goofy")
//Code
else if(cmb.text=="mars")
//Other code
else
//BLA BLA

Categories

Resources