I have looked up about threadpooling and etc and found an example of it. At the moment was i trying to recreate the example i saw for my own project and i keep getting this error when i input any number from the UI.
ManualResetEvent[] doneReadEvents = new ManualResetEvent[Read];
ManualResetEvent[] doneWriteEvents = new ManualResetEvent[Write];
ReadWrite[] ReadArray = new ReadWrite[Read];
ReadWrite[] WriteArray = new ReadWrite[Write];
for (int i = 0; i < Read; i++)
{
doneReadEvents[i] = new ManualResetEvent(false);
ReadWrite Rw = new ReadWrite(Read, doneReadEvents[i]);
ReadArray[i] = Rw;
ThreadPool.QueueUserWorkItem(Rw.ThreadPoolCallBackRead, i);
}
for (int i = 0; i < Write; i++)
{
doneReadEvents[i] = new ManualResetEvent(false);
ReadWrite rW = new ReadWrite(Write, doneWriteEvents[i]);
ReadArray[i] = rW;
ThreadPool.QueueUserWorkItem(rW.ThreadPoolCallBackWrite, i);
}
WaitHandle.WaitAny(doneReadEvents);
WaitHandle.WaitAny(doneWriteEvents);
temp.Items.Add("Complete");
temp.Items.Add("Closing");
Output.DataSource = ReadWrite.MyList;
Work.DataSource = ReadWrite.MyList2;
ReadWrite.ReadData(Read);
}
the first line in the first loop i get an error saying it is out of bound of the array. when that error clears i dont know if there will be any more errors
namespace MultiThreadingReaderWriter
{
class ReadWrite
{
public int _rw;
public ManualResetEvent _doneEvents;
public List<string> myList = new List<string>();
public List<string> myList2 = new List<string>();
public List<string> MyList{ get { return myList; } }
public List<string> MyList2{ get { return myList2; } }
public int RW { get { return _rw; } }
//Constructor
public ReadWrite(int rw, ManualResetEvent doneEvents)
{
_rw = rw;
_doneEvents = doneEvents;
}
public void ThreadPoolCallBackRead(Object threadContext)
{
int threadindex = (int) threadContext;
myList.Add("Thread Read " + threadindex+ " started");
ReadData(_rw);
myList.Add("Thread Read " + threadindex + " done");
_doneReadEvents.Set();
}
public void ThreadPoolCallBackWrite(Object threadContext)
{
int threadindex = (int)threadContext;
myList.Add("Thread Write " + threadindex + " started");
WriteData(_rw);
myList.Add("Thread Write " + threadindex + " done");
_doneWriteEvents.Set();
}
public void ReadData(int reader)
{
myList.Add("Reader " + reader + " has entered Critical Section");
myList.Add("Reader " + reader + " is Reading");
myList.Add("Reader " + reader + " is leaving Critical Section");
}
public void WriteData(int writer)
{
myList.Add("Writer " + writer + " has entered Critical Section");
myList.Add("Writer " + writer + " is writing");
myList.Add("Writer " + writer + " is leaving Critical Section");
}
}
}
this is the class connected to that above form program.
Array indices start from zero and the right way to iterate would be
for (int i = 0; i < Read; i++)
{
}
for (int i = 0; i < Write; i++)
{
}
Related
I am trying to use "Anviz Original SDK"
i added simple looping to connect multiple devices.
it was running okay if i only run it for 1 times, but in the second (sometimes the third) it keep crashing and showing erorr "Access Violation" at the output box of Visual Studio.
I've read some posts here on stackoverflow which suggest that there might be a bad pointer somewhere, but i cannot find where. I think My pointers are not corrupt.
The DLL Import for the function are using this code:
[DllImport("tc-b_new_sdk.dll")]
here is the function to loop and connect to device:
private void pictureBox3_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewDevice.Items)
{
if (item.Selected)
{
//int result = connectDevice(item.SubItems[3].Text, "5010");
int ret = 0;
byte[] Ipstr = new byte[16];
//string_to_byte(this.Add_dev_Ip.Text,Ipstr, (byte)Add_dev_Ip.Text.Length);
Ipstr = System.Text.Encoding.Default.GetBytes(item.SubItems[3].Text);
int Port = Convert.ToInt32("5010");
ret = AnvizNew.CCHex_ClientConnect(anviz_handle, Ipstr, Port);
}
}
}
and here is the Timer Tick function to get the data:
private void timer1_Tick(object sender, EventArgs e)
{
try
{
int ret = 0;
int[] Type = new int[1];
int[] dev_idx = new int[1];
IntPtr pBuff;
int len = 32000;
pBuff = Marshal.AllocHGlobal(len);
while (true)
{
if (anviz_handle == IntPtr.Zero)
{
break;
}
ret = AnvizNew.CChex_Update(anviz_handle, dev_idx, Type, pBuff, len);
//dbg_info("Update~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
if (ret > 0)
{
dbg_info("Msg Type : " + Type[0]);
switch (Type[0])
{
case (int)AnvizNew.MsgType.CCHEX_RET_DEV_LOGIN_TYPE:
{
AnvizNew.CCHEX_RET_DEV_LOGIN_STRU dev_info;
dev_info = (AnvizNew.CCHEX_RET_DEV_LOGIN_STRU)Marshal.PtrToStructure(pBuff, typeof(AnvizNew.CCHEX_RET_DEV_LOGIN_STRU));
string info_buff = "Dev Login --- [MachineId:" + dev_info.MachineId
+ " Version:" + byte_to_string(dev_info.Version)
+ " DevType:" + byte_to_string(dev_info.DevType)
+ " Addr:" + byte_to_string(dev_info.Addr)
+ "]";
//log_add_string(info_buff + " " + dev_info.DevTypeFlag.ToString());
log_add_string(info_buff + " " + Convert.ToString(dev_info.DevTypeFlag, 16));
ListViewItem foundItem = null;
if (foundItem == null)//just test has machineid
{
int i = 0;
for (i = 0; i < listViewDevice.Items.Count; i++)
{
foundItem = this.listViewDevice.Items[i];
if (foundItem.SubItems[1].Text.ToString() == dev_info.MachineId.ToString() && Convert.ToInt32(foundItem.Text.ToString()) != dev_info.DevIdx)
{
foundItem.Text = dev_info.DevIdx.ToString();
break;
}
else
{
}
//foundItem.Text = dev_info.DevIdx.ToString();
foundItem = null;
}
}
DevCount++;
//DevTypeFlag.Add(dev_info.DevIdx, (int)dev_info.DevTypeFlag);
}
break;
case (int)AnvizNew.MsgType.CCHEX_RET_DEV_LOGIN_CHANGE_TYPE:
{
AnvizNew.CCHEX_RET_DEV_LOGIN_STRU dev_info;
dev_info = (AnvizNew.CCHEX_RET_DEV_LOGIN_STRU)Marshal.PtrToStructure(pBuff, typeof(AnvizNew.CCHEX_RET_DEV_LOGIN_STRU));
string info_buff = "Login Change --- [MachineId:" + dev_info.MachineId
+ " Version:" + byte_to_string(dev_info.Version)
+ " DevType:" + byte_to_string(dev_info.DevType)
+ " Addr:" + byte_to_string(dev_info.Addr)
+ "]";
log_add_string(info_buff + " " + Convert.ToString(dev_info.DevTypeFlag, 16));
//log_add_string(info_buff + " " + dev_info.DevTypeFlag.ToString());
//DevTypeFlag[dev_info.DevIdx] = (int)dev_info.DevTypeFlag;
}
break;
case (int)AnvizNew.MsgType.CCHEX_RET_DEV_LOGOUT_TYPE:
{
AnvizNew.CCHEX_RET_DEV_LOGOUT_STRU dev_info;
dev_info = (AnvizNew.CCHEX_RET_DEV_LOGOUT_STRU)Marshal.PtrToStructure(pBuff, typeof(AnvizNew.CCHEX_RET_DEV_LOGOUT_STRU));
string info_buff = "Dev Logout --- [MachineId:" + dev_info.MachineId
+ " Version:" + byte_to_string(dev_info.Version)
+ " DevType:" + byte_to_string(dev_info.DevType)
+ " Live:" + dev_info.Live
+ " Addr:" + byte_to_string(dev_info.Addr)
+ "]";
log_add_string(info_buff);
DevCount--;
ListViewItem foundItem = null;
if (foundItem == null)//just test has machineid
{
int i = 0;
for (i = 0; i < listViewDevice.Items.Count; i++)
{
foundItem = this.listViewDevice.Items[i];
if (foundItem.SubItems[1].Text.ToString() == dev_info.MachineId.ToString() && Convert.ToInt32(foundItem.Text.ToString()) == dev_info.DevIdx)
{
break;
}
foundItem = null;
}
}
//ListViewItem foundItem = this.listViewDevice.FindItemWithText(dev_info.MachineId.ToString(), false, 0);
if (foundItem != null)
{
// DevTypeFlag.Remove(dev_idx[0]);
foundItem.Text = "0";
//this.listViewDevice.Items.Remove(foundItem);
}
}
break;
}
}
else if (0 == ret)
{
//MY_SLEEP(10);
//Marshal.FreeHGlobal(pBuff); // free the memory
break;
}
else if (0 > ret)
{
//buff to small
len = len * 2;
Marshal.FreeHGlobal(pBuff);
pBuff = Marshal.AllocHGlobal(len);
}
else
{
//没有找到消息类型
//Marshal.FreeHGlobal(pBuff); // free the memory
break;
}
//Marshal.FreeHGlobal(pBuff); // free the memory
}
//Marshal.FreeHGlobal(buff_fin);
Marshal.FreeHGlobal(pBuff); // free the memory
}
catch (Exception ex)
{
dbg_info("Error " + ex.Message);
}
}
Really appreciate for any helps.
Thanks.
Hi I need to create a list in .txt but using these codes I am only able to write data and keying anymore will just overwrite the first one
int score = Convert.ToInt32(ScoreLBL.Text);
String name = NameTB.Text;
List<Leaderboard> LB = new List<Leaderboard>();
Leaderboard results;
results = new Leaderboard(name, score);
LB.Add(results);
StreamWriter sw = new StreamWriter(#"C:\Users\zxong\Desktop\EGL138-OBJECT-ORIENTED PROGRAMMING\Project\Leaderboard.txt");
for (int i = 0; i< LB.Count(); i++)
{
sw.WriteLine(LB[i].getName() + "," + LB[i].getScore());
}
Leaderboard class
class Leaderboard
{
private String name;
protected int score;
public Leaderboard(String n, int s)
{
this.name = n;
this.score = s;
}
public String getName()
{
return this.name;
}
public int getScore()
{
return this.score;
}
}
i think this small change should be able to give you the functionality you want:
List<Leaderboard> LB = new List<Leaderboard>();
LB.Add(new Leaderboard("SomeName", 10));
LB.Add(new Leaderboard("AnotherName", 20));
LB.Add(new Leaderboard("ThirdName", 30));
using (StreamWriter sw = new StreamWriter(#"C:\Users\zxong\Desktop\EGL138-OBJECT-ORIENTED PROGRAMMING\Project\Leaderboard.txt", true)) {
for (int i = 0; i < LB.Count; i++) {
//Console.WriteLine(LB[i].getName() + "," + LB[i].getScore());
sw.WriteLine(LB[i].getName() + "," + LB[i].getScore());
}
}
Adding the true flag at the end of the StreamWriter should set the stream writer to work in append mode, which should add new lines rather than overwrite them on the file.
What I want to do is to spread tasks over a number of servers randomly with very little bias if possible. So far what I worked on is able to randomly spread the tasks over a different servers. The problem is that whenever I spread the tasks over the servers, it spreads the 1-3 tasks per server. The load balancing method used is Power of Two Choices. Forgive me if I get the concept wrong.
Power of Two Choices is where two random queues are chosen, where the one with the least tasks, is assigned a task. Correct me if I'm wrong.
The photo below shows my current output.
What I want is this
My main file is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C1._2
{
class Program
{
static void details(Server[] server, int num)
{
int count = 0;
for (int i = 0; i < server.Length; i++)
{
if (server[i].Tasks == num)
{
count++;
}
}
Console.WriteLine("There are " + count + " servers with " + num + " tasks.");
}
static void Main(string[] args)
{
Random rand = new Random();
int n = 256; //number of tasks
int m; //number of servers
m = 64;//Convert.ToInt32(Console.ReadLine())
Console.WriteLine("Number of servers(m): " + m);
int d = 1; //random servers to be chosen
Console.WriteLine("Number of tasks(n): " + n);
Console.WriteLine("Number of randomly selected server(d): " + d);
//Main server setup
Server[] servers = new Server[m];
for (int i = 0; i < m; i++)
{
servers[i] = new Server(i);
}
if (d == 1)
{
for (int i = 0; i < n; i++)
{
int randS = rand.Next(m);
servers[randS].Tasks++;
}
}
//Power of Two choice algorithm is here
if (d == 2)
{
for(int i = 0; i < n; i++)
{
Server s1 = servers[rand.Next(m)];
Server s2 = servers[rand.Next(m)];
if (s1.Tasks < s2.Tasks)
{
for(int j = 0; j < m; j++)
{
if (servers[j].SNo == s1.SNo)
{
servers[j].Tasks++;
}
}
}
else
{
for (int j = 0; j < m; j++)
{
if (servers[j].SNo == s2.SNo)
{
servers[j].Tasks++;
}
}
}
}
}
//Server min max
Server maxServer = new Server();
maxServer = servers[0];
for (int i = 0; i < m; i++)
{
if (maxServer.Tasks < servers[i].Tasks)
{
maxServer = servers[i];
}
}
Console.WriteLine("\nIndex of servers with most tasks: " + "[" + maxServer.SNo + "]");
Console.WriteLine("Highest number of tasks: " + maxServer.Tasks+"\n");
Server minServer = new Server();
minServer = servers[0];
for (int i = 0; i < m; i++)
{
if (minServer.Tasks > servers[i].Tasks)
{
minServer = servers[i];
}
}
Console.WriteLine("\nIndex of servers with least tasks: " + "[" + minServer.SNo + "]");
Console.WriteLine("Lowest number of tasks: " + minServer.Tasks+"\n");
//details
details(servers, 0);
details(servers, 1);
details(servers, 2);
details(servers, 3);
details(servers, 4);
details(servers, 5);
details(servers, 6);
details(servers, 7);
details(servers, 8);
details(servers, 9);
}
}
}
Accompanied Server class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace C1._2
{
class Server
{
private int server_number;
private int task;
public Server()
{
this.server_number = (int)0;
this.task = 0;
}
public Server(int sn)
{
this.server_number = sn;
this.task = 0;
}
public int SNo
{
get
{
return this.server_number;
}
set
{
this.server_number = value;
}
}
public int Tasks
{
get
{
return this.task;
}
set
{
this.task = value;
}
}
}
}
Any advice on how to do so?
When you say "random... where the one with the least tasks" means to me not random. But i think that I understand what you want. So we need to select the list of items that have least tasks and chose one of this randomic.
I rewrited a part of the class Program. Let me know if is this the expected result.
class Program
{
static void Main(string[] args)
{
//Random rand = new Random();
int numberOfTasks = 256; //number of tasks
int numberOfServers; //number of servers
numberOfServers = 64;//Convert.ToInt32(Console.ReadLine())
Console.WriteLine("Number of servers(m): " + numberOfServers);
//int d = 1; //random servers to be chosen
Console.WriteLine("Number of tasks(n): " + numberOfTasks);
//Console.WriteLine("Number of randomly selected server(d): " + d);
//Main server setup
Server[] servers = new Server[numberOfServers];
for (int i = 0; i < numberOfServers; i++)
{
servers[i] = new Server(i);
}
for(int i = 0; i < numberOfTasks; i++){
var minimumTasksValue = servers.Min(x => x.Tasks);
var listOfServersToSpread = servers.Where(x => x.Tasks == minimumTasksValue).ToList();
Random rand = new Random();
var randomServer = rand.Next(0, listOfServersToSpread.Count() - 1);
listOfServersToSpread[randomServer].Tasks++;
}
//Server min max
Server maxServer = new Server();
maxServer = servers[0];
for (int i = 0; i < numberOfServers; i++)
{
if (maxServer.Tasks < servers[i].Tasks)
{
maxServer = servers[i];
}
}
Console.WriteLine("\nIndex of servers with most tasks: " + "[" + maxServer.SNo + "]");
Console.WriteLine("Highest number of tasks: " + maxServer.Tasks + "\n");
Server minServer = new Server();
minServer = servers[0];
for (int i = 0; i < numberOfServers; i++)
{
if (minServer.Tasks > servers[i].Tasks)
{
minServer = servers[i];
}
}
Console.WriteLine("\nIndex of servers with least tasks: " + "[" + minServer.SNo + "]");
Console.WriteLine("Lowest number of tasks: " + minServer.Tasks + "\n");
//details
details(servers);
Console.ReadLine();
}
static void details(Server[] server)
{
var numberOfTasksAvailable = server.Select(x => x.Tasks).Distinct().OrderBy(x => x);
foreach(var numberOfTasks in numberOfTasksAvailable)
{
Console.WriteLine("There are " + server.Count(x => x.Tasks == numberOfTasks) + " servers with " + numberOfTasks + " tasks.");
}
}
}
Updated load balancing algorithm
if (d == 2)
{
for(int i = 0; i < n; i++)
{
int a = rand.Next(m);
int b = rand.Next(m);
servers[a < b ? a : b].Tasks++;
}
}
My problem was over-complicating the code. What it does above is that it randomly chooses two random servers from the total servers available. Compares which server has the least burden/tasks, and assigns a task to it.
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
I have the class WireObjectAnimation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using DannyGeneral;
namespace AnimationEditor
{
class WireObjectAnimation
{
private List<WireObjectCoordinates> wocl = new List<WireObjectCoordinates>();
private WireObject wo1 = null;
string name;
int ndx;
public WireObjectAnimation(string name,WireObject wo)
{
this.name = name;
wo1 = wo;
WireObjectCoordinates woc;
woc = new WireObjectCoordinates(wo.woc);
wocl.Add(woc);
ndx = 0;
}
public void Save(string path , string fileName , PictureBox pb)
{
int framesNumberX = 0;
int framesNumberY = 0;
string fn;
string t = Path.GetFileNameWithoutExtension(this.name);
if (File.Exists(path + "\\" + "DATABASE" + "\\" + fileName + "\\" + t + ".txt"))
{
try
{
string f = Path.Combine(path + "\\" + "DATABASE" + "\\" + t + "\\" + fileName);
File.Delete(f);
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not delete file from disk. Original error: " + ex.Message);
}
fn = path + "\\" + "DATABASE" + "\\" + t + "\\" + fileName;
}
else
{
fn = path + "\\" + "DATABASE" + "\\" + fileName + "\\" + this.name + ".txt";
}
OptionsFile setting_file = new OptionsFile(fn);
setting_file.SetKey("File Name", fn);
setting_file.SetKey("Object Name", fileName);
setting_file.SetKey("Animation Name", this.name);
setting_file.SetKey("picturebox.Width", pb.Width.ToString());
setting_file.SetKey("picturebox.Height", pb.Height.ToString());
string[] xFrames = new string[wocl.Count];
string[] yFrames = new string[wocl.Count];
string X="";
string Y="";
for (int i = 0; i < wocl.Count; i++)
{
X = string.Format("Frame_X_{0} ", i + 1);
Y = string.Format("Frame_Y_{0} ", i + 1);
framesNumberX ++;
framesNumberY ++;
for (int j = 0; j < wocl[i].Point_X.Count; j++)
{
xFrames[i] += string.Format("{0},", wocl[i].Point_X[j]);
yFrames[i] += string.Format("{0},", wocl[i].Point_Y[j]);
}
string tt = xFrames[i].Trim(",".ToCharArray());
string yy = yFrames[i].Trim(",".ToCharArray());
setting_file.SetKey(X, tt);
setting_file.SetKey(Y, yy);
}
int resultX = framesNumberX / 2;
int resultY = framesNumberY / 2;
setting_file.SetKey("Number Of Frames X", resultX.ToString());
setting_file.SetKey("Number Of Frames Y", resultY.ToString());
}
public void Load(string path,string fileName)
{
int numberofframesX = 0;
int numberofframesY = 0;
string framesX = "";
string framesY = "";
string X = "";
string Y = "";
string t = path + "\\" + fileName;
OptionsFile setting_file = new OptionsFile(t);
string XX = setting_file.GetKey("Number Of Frames X");
string YY = setting_file.GetKey("Number Of Frames Y");
numberofframesX = Convert.ToInt32(XX);
numberofframesY = Convert.ToInt32(YY);
for (int i = 1; i < numberofframesX ; i++)
{
X = string.Format("Frame_X_{0} ", i);
framesX = setting_file.GetKey(X);
List<string> floatStrings = new List<string>(framesX.Split(new char[] { ',' }));
List<float> test = floatStrings.Select(tempStr => (float)Convert.ToDouble(tempStr)).ToList();
wo1.woc.Point_X = test;
}
for (int i = 1; i < numberofframesY; i++)
{
Y = string.Format("Frame_Y_{0} ", i);
framesY = setting_file.GetKey(Y);
List<string> floatStrings = new List<string>(framesY.Split(new char[] { ',' }));
List<float> test = floatStrings.Select(tempStr => (float)Convert.ToDouble(tempStr)).ToList();
wo1.woc.Point_Y = test;
}
}
public void SetFrame(int frameNumber, WireObjectCoordinates woc)
{
wocl[frameNumber].Set(woc);
}
public WireObjectCoordinates GetFrame(int frameNumber)
{
if (frameNumber > wocl.Count)
{
throw new Exception("not allowed!");
}
if (frameNumber == wocl.Count)
{
WireObjectCoordinates woc;
woc = new WireObjectCoordinates(wocl[wocl.Count - 1]);
wocl.Add(woc);
return woc;
}
else
{
return wocl[frameNumber];
}
}
}
}
Now when im doing loading the Load function i see the points its loading it good.
But then im trying to move the trackBar bar scroll to the right and then im getting the exception. Now thisl ine: wo1.woc.Point_X = test; the woc have 4 indexs and in each index Point_X and Point_Y are filled with numbers in each index.
In this class i have the functions SetFrame and GetFrame and im using GetFrame in Form1 scroll event of the trackBar:
private void trackBar1_Scroll(object sender, EventArgs e)
{
currentFrameIndex = trackBar1.Value;
textBox1.Text = "Frame Number : " + trackBar1.Value;
wireObject1.woc.Set(wireObjectAnimation1.GetFrame(currentFrameIndex));
LoadPictureAt(trackBar1.Value, sender);
button1.Enabled = false;
button2.Enabled = false;
button3.Enabled = false;
button4.Enabled = false;
button8.Enabled = false;
SaveFormPicutreBoxToBitMapIncludingDrawings();
return;
}
Now when im moving the trackBar once to the right it should paint the next set of numbers from the Point_X and Point_Y instead its going to the WireObjectCoordinates class and throw there the exception:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AnimationEditor
{
class WireObjectCoordinates
{
public List<float> Point_X = new List<float>();
public List<float> Point_Y = new List<float>();
public WireObjectCoordinates()
{
}
public WireObjectCoordinates(WireObjectCoordinates w)
{
Point_X.AddRange(w.Point_X);
Point_Y.AddRange(w.Point_Y);
}
public void Set(WireObjectCoordinates w)
{
for (int i = 0; i < Point_X.Count; i++)
{
Point_X[i] = w.Point_X[i];
Point_Y[i] = w.Point_Y[i];
}
}
}
}
The exception is on the line: Point_X[i] = w.Point_X[i];
Point_X[i] contain now 4 indexs from [0] to [3] each index contain a number like 332.0 333.0 334.0 335.0
And w.Point_X[i] contain now only one index [0] and this index have the number 332.0
i just dont understand why the exception is on this line.
The idea is that when im moving the trackBar to the right it should draw the next coordinates from the wo1.woc.Point_Y and wo1.woc.Point_X but i guess i did something wrong in the Load function ? Im not sure why its throwing the exception and its only when im moving the trackBar to the right once.
How do you expect your for loop to work? The loop variable i goes from 0 to the count of the Point_X list of this instance. But if the other instance w has a Point_X list of a lower count, or if the Point_Y list of this or the Point_Y list of w has, it will fail.
If you realize that Point_X.Count is 4 and w.Point_X.Count is only 1, then when i exceeds 0, the expression w.Point_X[i] will try to read an element of the list that does not exist. That throws the excpetion "Index was out of range".
But maybe you understand that?
throw a try catch around it it technically wont fix the problem but it wont crash anymore and just read over the error
It says that in my array that I have gone over the index. My program is a Number Guessing game played by 5 players (5 indexes). I have used arrays to create the object and player classes.
I have reached a stump where my program crashes within the second or third round of the game. I noticed that during my second round, the index did not loop property: the loop counts the index 1 to 5 in the first loop, then counts 2 to 5 in the second loop, then if I even get to the 3rd round of the loop, all the indexes are shuffled around meaning I can't go from 1 to 5.
As each player gets 3 guesses, use those 3 guesses and your out of the game. I have taken the array of object I created for the player, created a temporary array smaller than the previous and referenced that to achieve the current array.
I looked over my references in the code and found as much code as I could fix, I cannot find the bug that is causing my System.IndexOutOfRangeException. It is being caused by my guessing game class.
Here is my GuessingGame Class:
using System; // only this using statement is needed here.
namespace GuessingGame
{
class GuessingGame
{
#region instance attributes
private const int GUESSES_ALLOWED = 3;
private const int NUMBER_OF_PLAYERS_TO_START = 5;
private const int MIN_VALUE = 1;
private const int MAX_VALUE = 15;
private Player[] players;
private Random randomSource;
#endregion
public GuessingGame()
{
Console.WriteLine("Starting Constructor of GuessingGame");
players = new Player[NUMBER_OF_PLAYERS_TO_START];
randomSource = new Random();
string playerName = "";
for (int index = 0; index < players.Length; index++)
{
Console.Write("What is the name for player #"
+ (index +1) + "?\t");
playerName = Console.ReadLine();
players[index] = new Player(playerName, randomSource);
Console.Write("\n");
}
Console.WriteLine("Ending GuessingGame Constructor");
}
public GuessingGame(string [] playerNames)
{
Console.WriteLine("Starting Constructor of GuessingGame");
players = new Player[playerNames.Length];
randomSource = new Random();
for (int index = 0; index < playerNames.Length; index++)
{
players[index] = new Player(playerNames[index], randomSource);
}
}
public void playGame()
{
int numberOfPlayersWhoHavePlayedThisRound = 0;
int index = 0;
bool[] playedThisRound = null;
string playerGuessEntry = "";
int playerGuessValue = -1;
Player[] tempArray = new Player[players.Length - 1];
bool roundOver = false;
Console.WriteLine(
"Starting playGame - press any key to continue");
//Console.Read()
while (roundOver == false) // Is this the right condition?
{
playedThisRound = new bool[players.Length];
while (playedThisRound[index] == false)
{
do
{
Console.Write(players[index].getName()
+ ", Enter a number between "
+ MIN_VALUE.ToString()
+ " and " + MAX_VALUE.ToString()
+ " inclusive\t");
playerGuessEntry = Console.ReadLine();
Console.Write("\n");
}
while (!int.TryParse(playerGuessEntry,
out playerGuessValue)
|| playerGuessValue < MIN_VALUE
|| playerGuessValue > MAX_VALUE);
if(playerGuessValue < MIN_VALUE || playerGuessValue > MAX_VALUE)
{
Console.Write("Invalid guess- try again");
}
else
{
Console.WriteLine("You entered "
+ playerGuessValue.ToString());
players[index].makeAGuess(playerGuessValue);
playedThisRound[index] = true;
if (index == players.Length)
{
Console.WriteLine("End of Round");
index = 0; //edit?
numberOfPlayersWhoHavePlayedThisRound = 0;
}
}
if (players[index].getGuessesUsed() == 3)
{//creating a temp array
Console.WriteLine("Guesses MAXED");
tempArray = players[index].deletePlayerFromArray(players, index);
players = tempArray; // referencing
bool[] tempBooleanArray = new bool[playedThisRound.Length - 1];//reducing size of played this round array
Console.WriteLine("Playedthisround length: " + playedThisRound.Length + " \nThe Index: " + index.ToString());
tempBooleanArray = players[index].deletePlayerBool(playedThisRound, index);
playedThisRound = tempBooleanArray;
Console.WriteLine("New Player Array Size: " + players.Length);
Console.WriteLine("New Boolean Array Size: " + playedThisRound.Length);
}
if (index == players.Length - 1)
{
index = 0;
numberOfPlayersWhoHavePlayedThisRound = 0;
}
if (players.Length == 1)
{
roundOver = true;
}
index++;
numberOfPlayersWhoHavePlayedThisRound++;
}
Console.WriteLine("WINNER:" + players[index].getName() +
"\nWins: " + players[index].getWins() + "\nArray Size: " + players.Length.ToString());
}//end of while
Console.WriteLine("Ending playGame - "
+ "press any key to continue");
Console.Read();
}
public bool playersAlreadyPlayed(bool[] thePlayer)
{
bool havePlayed = false;
for (int plays = 0; plays < thePlayer.Length; plays++)
{
if (thePlayer[plays] == false)
{
havePlayed = false;
}
else
{
havePlayed = true;
}
}
return havePlayed;
}
static void Main(string[] args)
{
GuessingGame newGame = new GuessingGame();
newGame.playGame();
}
}
}
And Here is the Player Class
using System;
namespace GuessingGame
{
class Player
{
private String name;
private int winningNumber;
private int guessesUsed;
private int wins;
private Random myWinningNumberSource;
public Player(string newName, Random random)
{
name = newName;
guessesUsed = 0;
wins = 0;
myWinningNumberSource = random;
winningNumber = myWinningNumberSource.Next(1, 16);
}
public bool makeAGuess(int guessValue)
{
bool isWinner = false;//edit
if (guessValue == winningNumber)
{
wins++;
Console.WriteLine("Congradulations, You have guessed correct number!\n");
Console.WriteLine("You have a total of " + wins + " wins!");
Console.WriteLine("You have " + (3 - guessesUsed) + " guesses left!\n");
winningNumber = myWinningNumberSource.Next(1, 16);
isWinner = true; //edit
}
else
{
guessesUsed++;
Console.WriteLine("Oh no! You have guessed incorretly!");
Console.WriteLine("You have used " + guessesUsed + " and have " + (3 - guessesUsed) + " guesses left!");
Console.WriteLine("HINT: You should have guessed " + winningNumber);
isWinner = false;
if (guessesUsed > 3)
{
Console.WriteLine("Sorry you have Lost, Game Over");
}
}
return isWinner;
}
public int getGuessesUsed()
{
return guessesUsed;
}
public string getName()
{
return name;
}
public int getWins()
{
return wins;
}
public Player[] getWinner(Player[] nPlayers)
{
int maxScore = 0; //edit
Player[] winningPlayers;
winningPlayers = new Player[5];
for (int i = 0; i < nPlayers.Length; i++)
{
if (nPlayers[i].wins >= maxScore)
{
winningPlayers[i].wins = nPlayers[i].getWins();
winningPlayers[i].name = nPlayers[i].getName();
}
}
return winningPlayers;
}
public bool[] deletePlayerBool(bool[] playedThisRound, int removeIndex)//edit
{
bool[] newArray = new bool[playedThisRound.Length - 1];
int tempIndex = 0;
for (int i = 0; i < playedThisRound.Length; i++)
{
if (i != removeIndex)
{
newArray[tempIndex++] = playedThisRound[i];
}
}
return newArray;
}
public Player[] deletePlayerFromArray(Player[] nPlayers, int removeIndex)
{
Player[] newArray = new Player[nPlayers.Length - 1];
int tempIndex = 0;
for (int i = 0; i < nPlayers.Length; i++)
{
if (i != removeIndex)
{
newArray[tempIndex++] = nPlayers[i];
}
}
return newArray;
}
}
}
i is within the bounds of nPlayer length not 0-4.
public Player[] getWinner(Player[] nPlayers)
{
int maxScore = 0; //edit
Player[] winningPlayers;
winningPlayers = new Player[5];
for (int i = 0; i < nPlayers.Length; i++)
{
if (nPlayers[i].wins >= maxScore)
{
winningPlayers[i].wins = nPlayers[i].getWins();
winningPlayers[i].name = nPlayers[i].getName();
}
}
return winningPlayers;
}
It means that you are trying to access an index bigger than the array. In the line:
while(playedThisRound[index] == false)
You don't check the boundaries before using the index, and your crash is probably there.
It means that you are trying to access an item in an array with an index higher than the limit of the array.