updating variable from inside a loop? - c#

I'm writing a mastermind game and I need to update the value of an array size using a variable inside a while loop which increments on each loop is there any way i can do this?
bool game = false;
do
{
int codeSize;
int colourSize;
int guessNumber = 1;
int userGuess;
int black = 0;
int white = 0;
int count = 1;
Console.WriteLine("Welcome to Mastermind coded by ****");
Console.Write("How many positions > ");
codeSize = Convert.ToInt32(Console.ReadLine());
Console.Write("How many colours > ");
colourSize = Convert.ToInt32(Console.ReadLine());
Random rand = new Random();
int[] code = new int[codeSize];
int[] guess = new int[codeSize];
for (int i = 0; i < codeSize; i++)
{
code[i] = rand.Next(1, colourSize + 1);//filling the secret code array
}
Console.WriteLine("O.k. - I've generated a code -- guess it!");
while (black < codeSize)
{
int[,] history = new int[count, codeSize + 2];
Console.WriteLine("Next guess please.");
for (int n = 0; n < codeSize; n++)
{
Console.Write("Position " + guessNumber + " >");
userGuess = Convert.ToInt32(Console.ReadLine());
guess[n] = userGuess;
history[count - 1, n] = guess[n];
guessNumber++;
}
for (int x = 0; x < codeSize; x++)
{
int caseSwitch = 1;
switch (caseSwitch)
{
case 1:
{
if (guess[x] == code[x])
{
black++;
break;
}
goto case 2;
}
case 2:
{
if (guess[x] == code[x])
{
break;
}
int i = 0;
while (i < codeSize)
{
if ((guess[x] == code[i]) && (guess[i] != code[i]))
{
white++;
break;
}
i++;
}
break;
}
}
}
guessNumber = 1;
if (black == codeSize)
{
white = 0;
}
history[count - 1, codeSize + 1] = white;
history[count - 1, codeSize] = black;
count++;
Debug.WriteLine("-----------\nSecret code\n-----------");
for (int x = 0; x < codeSize; x++)
{
Debug.WriteLine(code[x]);
}
Console.WriteLine("Correct positions : {0}", black);
Console.WriteLine("Correct colours : {0}\n", white);
Console.WriteLine("History");
for (int t = 1; t < codeSize + 1; t++)
{
Console.Write(t + " ");
}
Console.WriteLine("B W");
for (int g = 0; g < codeSize + 3; g++)
{
Console.Write("--");
}
Console.Write("\n");
for (int t = 0; t < count - 1; t++)
{
for (int g = 0; g < codeSize + 2; g++)
{
Console.Write("{0} ", history[t, g]);
}
Console.WriteLine("\n");
}
if (codeSize > black)//reseting values for next turn
{
black = 0;
white = 0;
}
}
int play;
Console.WriteLine("\nYou Win!\n\nPress 1 to play again or any other number to quit");
play = Convert.ToInt32(Console.ReadLine());
if (play == 1)
game = true;
} while (game == true);

Arrays have a fixed size when you declare them and you cannot change the size afterwards without creating a new array. Try using a strongly typed List instead.
List<int> MyList = new List<int>();
// Add the value "1"
MyList.Add(1);
or the following for a table:
List<List<int>> MyTable = new List<List<int>>();
// Add a new row
MyTable.Add(new List<int>());
// Add the value "1" to the 1st row
MyTable[0].Add(1);

I believe you are asking whether you can change the length property of an array from within a loop, extending it as required.
Directly, no. There are helpers and classes which provide for such functionality, allocating more memory as needed, but I doubt this is what you really need. You could try using an array of fixed dimensions (the maximum codeSize your program will tolerate or expect), and then an integer next to it to record the length/position.
Alternatively, if you really need to expand to arbitrary sizes and store all codes, just use a List.
List<int[]> theList = new List<int[]>();
theList.Add(code);
Creates a list of integer arrays (your codes) that you can keep adding onto, and index just like any simple array.

There is a way to resize array size:
Array.Resize<T>
method. Details there: http://msdn.microsoft.com/en-us/library/bb348051(v=vs.110).aspx
But it's usually a pretty bad idea to resize the arrays loop based. You need to select another data structure to save your data or i.e. create an array of bigger size filled i.e. with zeroes.

You also need to add the items to the list as so. The list will dynamically grow based on it's size.
int myInt = 6;
List<int> myList = new List<int>();
myList.Add(myInt);

Related

Comparing arrays without using linq

I am making a lottery game that asks the user for 10 numbers and then check it against random numbers that i have created in an array. I need to compare the two but I am not allowed to use the contains method.
I think I need to use a foreach loop to compare the arrays but really I am at a loss of what to do. I have been piecing it together from the little I know and would like to know if I am on the right track.
Is a foreach loop the correct way to compare the two arrays?
This is my code so far.
using System;
namespace lotto2
{
class Program
{
static void Main(string[] args)
{
//an array named "input" to hold the users' 10 guesses
int[] inputs = new int[10];
//an array named "lotNum" to hold 10 random numbers
int[] lotNums = new int[10];
//a for loop to loop over the inputs array. each loop will ask the user for a number
Console.WriteLine("Enter your 10 lottery numbers one at a time. The numbers must be between 1 and 25.");
for (int i = 0; i < inputs.Length; i++)
{
inputs[i] = Convert.ToInt32(Console.ReadLine());
}
//a random number generator
Random ranNum = new Random();
//loop to call the random generator 10 times and store 10 random numbers in the "lotNum" array
for (int i = 0; i < 10; i++)
{
lotNums[i] = ranNum.Next(1, 26); //chooses random numbers between 1 and 25
}
//writes out the randomly generated lotto numbers
Console.Write("\nThe lottery numbers are: ");
for (int i = 0; i < 10; i++)
{
Console.Write("{0} ", lotNums[i]);
}
//loop for checking users inputs against random generated numbers..
//foreach loop maybe?
foreach (var input in lotNums)
{
}
//print out if there are any matches, which numbers matched
//declared integer for the correct numbers the user guessed
int correct;
//end progam
Console.WriteLine("\n\nPress any key to end the program:");
Console.ReadKey();
}
}
}
Here's a program that correctly does what you want. It even ensures that you don't have duplicate lotto numbers.
void Main()
{
const int count = 10;
const int max = 25;
//an array named "input" to hold the users' 10 guesses
int[] inputs = new int[count];
//a for loop to loop over the inputs array. each loop will ask the user for a number
Console.WriteLine("Enter your {0} lottery numbers one at a time. The numbers must be between 1 and {1}.", count, max);
for (int i = 0; i < inputs.Length; i++)
{
inputs[i] = Convert.ToInt32(Console.ReadLine());
}
//a random number generator
Random ranNum = new Random();
//an array named "allNums" to hold all the random numbers
int[] allNums = new int[max];
for (int i = 0; i < allNums.Length; i++)
{
allNums[i] = i + 1;
}
//shuffle
for (int i = 0; i < allNums.Length; i++)
{
int j = ranNum.Next(0, allNums.Length);
int temporary = allNums[j];
allNums[j] = allNums[i];
allNums[i] = temporary;
}
//an array named "lotNum" to hold 10 random numbers
int[] lotNums = new int[count];
Array.Copy(allNums, lotNums, lotNums.Length);
//writes out the randomly generated lotto numbers
Console.Write("\nThe lottery numbers are: ");
for (int i = 0; i < lotNums.Length; i++)
{
Console.Write("{0} ", lotNums[i]);
}
int correct = 0;
Console.Write("\nThe correct numbers are: ");
for (int i = 0; i < lotNums.Length; i++)
{
for (int j = 0; j < inputs.Length; j++)
{
if (lotNums[i] == inputs[j])
{
Console.Write("{0} ", lotNums[i]);
correct++;
};
}
}
Console.Write("\nYou got {0} correct. ", correct);
Console.WriteLine("\n\nPress any key to end the program:");
Console.ReadLine();
}
You're on the right way.
My implementation would be:
foreach (var input in inputs)
{
for (int i = 0; i < lotNums.Length; i++){
if(input == lotNums[i]){
Console.WriteLine(lotNums[i]);
}
}
}
This will compare every number of the input array with the lottery array.
I'm printing every match, but you can set a variable to True if it finds a match or add every matching number into an array if you need it.
This is what I have tried.I hope it makes sense?
static void LottoMethod(int[] randNums,int[] userNums)
{
Console.WriteLine("Guess 10 numbers");
for(int i = 0; i <= userNums.Length-1; i++)
{
userNums[i] = Int32.Parse( Console.ReadLine());
}
Console.WriteLine("The numbers you entered: ");
foreach(int k in userNums)
{
Console.Write(k+" ");
}
//generate 10 numbers randomly
Random rnds = new Random();
for(int k = 0; k <= randNums.Length - 1; k++)
{
randNums[k] = rnds.Next(1, 26);
}
Console.WriteLine("Random Numbers");
foreach(int i in randNums)
{
Console.Write(i + " ");
}
int correctNums = 0;
//Check if random numbers correspond with entered numbers
try
{
for(int i = 0; i <= randNums.Length-1; i++)
{
for(int j = 0; j <= userNums.Length-1; j++)
{
if (randNums[i] == userNums[j])
{
correctNums++;
}
}
}
Console.WriteLine($"There are {correctNums} numbers ");
}
catch(Exception e) {
throw new Exception(e.ToString());
}
}
You have to calculate intersection of two sequences. You have three options:
Double foreach loop. This is something to avoid as it has time complexity O(m*n). It it not a problem for 10 items, but we should make programs that scale.
Using hash join. You can use HashSet for this and it would be my preferred method. But as it inherently implies using Contains, it is not the option here.
Merging sorted sequences. This would be the way to go here.
The program is rather self explanatory, it produces and intersects two random sequences.
static Random rnd = new Random((int)DateTime.Now.Ticks);
static int[] GetRandomArray(int arrSize, int minNumber, int maxNumber)
{
int[] tmpArr = new int[maxNumber - minNumber + 1];
for (int i = 0; i < tmpArr.Length; ++i)
{
tmpArr[i] = i + minNumber; // fill with 1, 2, 3, 4,...
}
int[] ret = new int[arrSize];
for (int i = 0; i < ret.Length; ++i)
{
int index = rnd.Next(tmpArr.Length - i); //choose random position
ret[i] = tmpArr[index];
tmpArr[index] = tmpArr[tmpArr.Length - 1 - i]; //fill last of the sequence into used position
}
return ret;
}
static IEnumerable<int> GetMatches(int[] a, int[] b)
{
Array.Sort(a);
Array.Sort(b);
for (int i = 0, j = 0; i < a.Length && j < b.Length;)
{
if (a[i] == b[j])
{
yield return a[i];
++i;
++j;
}
else if (a[i] > b[j])
{
++j;
}
else
{
++i;
}
}
}
static void Main(string[] args)
{
var a = GetRandomArray(5, 3, 7);
var b = GetRandomArray(10, 1, 25);
Console.WriteLine("A: " + string.Join(", ", a));
Console.WriteLine("B: " + string.Join(", ", b));
Console.WriteLine("Matches: " + string.Join(", ", GetMatches(a, b)));
Console.ReadKey();
}
The result is something like:
A: 7, 4, 6, 3, 5
B: 17, 1, 8, 14, 11, 22, 3, 20, 4, 25
Matches: 3, 4
You can think about what would happen if one or both of the sequences contain duplicities.

Function not returning array

I have this function to initiate a two dimensional array:
static Array Matrix(int Rows, int Columns)
{
int[,] LotteryArray = new int[Rows,Columns];
for (int i = 0; i < LotteryArray.GetLength(0); i++)
{
for (int j = 0; j < LotteryArray.GetLength(1); j++)
{
LotteryArray[i, j] = RandomNum(1, 46);
Console.Write("{0,3},", LotteryArray[i, j]);
}
Console.WriteLine();
}
return LotteryArray;
}
Then I have this which is supposed to give me a one dimensional array and see how many numbers in the winning array are in the matrix:
int RowNum = 1;
int Prediction = 0;
Console.WriteLine("Your winning numbers are!");
Console.WriteLine("------------------------");
int[] Winner = new int[6];
for (int i = 0; i < Winner.Length; i++) //this loop is to initiate and print the winning numbers
{
Winner[i] = RandomNum(1, 46); //the numbers are supposed to be between 1 and 45, so i tell it to do it until 46 because the upper limit is exclusive
Console.Write("{0,3},", Winner[i]);
}
Console.WriteLine();
Console.WriteLine("------------------------"); //these two lines are for aesthetics
Matrix(Rows, Columns);
foreach (int i in Winner)
{
for (int j = 0; j<LotteryArray; j++)
{
if (Winner[i] == j)
{
Prediction++;
if (j % 6 == 0) { RowNum++; }
}
Console.WriteLine("you got {0} correct prediction in row number {1}",Prediction,RowNum);
RowNum = 1;
}
}
It's telling me LotteryArray doesn't exist in the current context.
LotteryArray is a variable within another method. You cannot access it in the scope you are showing.
You can do get the return from your method into a variable and then use it.
var LotteryArray = Matrix(Rows, Columns);
foreach (int i in Winner)
{
for (int j = 0; j<LotteryArray; j++)
{
if (Winner[i] == j)
{
Prediction++;
if (j % 6 == 0) { RowNum++; }
}
Console.WriteLine("you got {0} correct prediction in row number {1}",Prediction,RowNum);
RowNum = 1;
}
}
LotteryArray is a variable declared in Matrix method, and is not visible outside.

for loop - highscore array

So I'm trying to make this loop that goes through every index of highscore array(scorelist) to check if the current score(playerScore) is higher than the current index. If the if statement gets a "yes", then it should push all scores down(or is that higher?) along the index and put playerScore at where it should be.
{
Console.Write("input name: ");
string playerName = Console.ReadLine();
Console.Write("input score: ");
int playerScore = Convert.ToInt32(Console.ReadLine());
for (int i = 0; i < 10; i++)
{
if (playerScore > scoreList[i])
{
int nextNo = 9;
for (int n = 10; n > 0; n--)
{
scoreList[n] = scoreList[nextNo];
nameList[n] = nameList[nextNo];
nextNo--;
}
scoreList[i] = playerScore;
nameList[i] = playerName;
}
}
}
With this current code, it just places playerScore on the first index(IF it is higher than what was previously stored there), then copies it along the rest of the index. Any suggestions on how to fix this?
It can be done much easier:
int prev = playerScore;
for (int i = 0; i < 10; i++)
{
if (playerScore > scoreList[i])
{
int temp = scoreList[i];
scoreList[i] = prev;
prev = temp;
}
}
I assumed, that you only need top 10 results (and your array already has 10 elements in it).
Change your array to a List<int> and use this code:
var scorelist = new List<int>();
//populate your scorelist;
var playerScore = someintValue;
var firstlower = scorelist.FirstOrDefault(x => x < playerScore);
if (firstlower != null)
scorelist.Insert(playerScore, scoreList.IndexOf(firstlower);
else
scorelist.add(playerScore);
Edit:
If you need to crop the list to 10 items max after inserting, just:
scorelist = scorelist.Take(10).ToList();

Creating different arrays: not displaying correct results

I am currently building a sorting program. I have made three different ways to create an array: Random, In Order and Reverse. I am currently undergoing problems with the In Order and Reverse arrays. Every time an In Order array is created it starts with a 1, I am not sure how come is doing so. Also my Reverse array will display digits out of order not every time but after some clicks. How can I fix these two issues?
namespace sortingMachine
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Class Level Variables --------------------------------------------------------------------------------------
Stopwatch sw = new Stopwatch();
Random r = new Random();
OpenFileDialog open1 = new OpenFileDialog();
long operations = 0;
int size;
int max;
int[] createArray;
int[] sortArray;
int[] copyArray;
//Create Array Methods --------------------------------------------------------------------------------------
public void RandomNumber()
{
size = Convert.ToInt32(textBoxSize.Text);
max = Convert.ToInt32(textBoxMax.Text);
createArray = new int[size];
copyArray = new int[size];
sortArray = new int[size];
for (int i = 0; i < size; i++)
{
createArray[i] = r.Next(1, max);
}
textBoxResults.AppendText("-------------------------------------------------------------------------------" + Environment.NewLine + "Random" + Environment.NewLine + Environment.NewLine);
DisplayArrays();
}
public void InOrder()
{
size = Convert.ToInt32(textBoxSize.Text);
max = Convert.ToInt32(textBoxMax.Text);
createArray = new int[size];
copyArray = new int[size];
sortArray = new int[size];
createArray[0] = 1;
for (int i = 1; i < size; i++)
{
createArray[i] = createArray[i - 1] + r.Next(1, max);
}
for (int i = 1; i < size; i++)
{
if (r.Next(1, 101) < Convert.ToInt32(textBoxPercentage.Text))
{
for (int x = 1; x < size; x++)
{
createArray[x] = r.Next(1, createArray[size - 1]);
}
}
}
textBoxResults.AppendText("-------------------------------------------------------------------------------" + Environment.NewLine + "In Order" + Environment.NewLine + Environment.NewLine);
DisplayArrays();
}
public void ReverseOrder()
{
size = Convert.ToInt32(textBoxSize.Text);
max = Convert.ToInt32(textBoxMax.Text);
createArray = new int[size];
copyArray = new int[size];
sortArray = new int[size];
createArray[size - 1] = 1;
for (int i = size - 1; i > 0; i--)
{
createArray[i - 1] = createArray[i] + r.Next(1, max);
}
for (int i = size - 1; i > 0; i--)
{
if (r.Next(1, 101) < createArray[0])
{
for (int x = size - 1; x > 0; x--)
{
createArray[x] = r.Next(1, createArray[0]);
}
}
}
textBoxResults.AppendText("-------------------------------------------------------------------------------" + Environment.NewLine + "Reverse Order" + Environment.NewLine + Environment.NewLine);
DisplayArrays();
}
private void buttonCreateArray_Click(object sender, EventArgs e)
{
if ((textBoxSortKey.Text != "") && (textBoxCreateKey.Text != ""))
{
if (radioButtonRandom.Checked == true)
{
RandomNumber();
}
if (radioButtonInOrder.Checked == true)
{
InOrder();
}
if (radioButtonReverseOrder.Checked == true)
{
ReverseOrder();
}
}
else
{
MessageBox.Show("Type a key into the Key textbox.");
}
}
}
}
Display Results:
The order array I am not sure why it always start with one:
-------------------------------------------------------------------------------
In Order
1
2
4
6
10
There are times the reverse order array will be like this:
-------------------------------------------------------------------------------
Reverse Order
10
2
7
6
5
Windows Form:
If you look at how you are assigning values to the array you'll see that the first element is assigned zero, but in your loop you start at the second element (i.e. 1) so you never re-assign the first element.
createArray[0] = 1;
for (int i = 1; i < size; i++)
{
createArray[i] = createArray[i - 1] + r.Next(1, max);
}
Try writing the first element assignment like this:
createArray[0] = r.Next(1, max);
As for your reverse function, there's too much weirdness in there to really see what you're trying to do. Try thinking thru it a few more times. Especially be careful with code like this: if (r.Next(1, 101) < createArray[0]) - it has random behaviour and also magic numbers in it.
In the function InOrder you initialize your first index of your array to 1. As for the Reverse Order, in the if statement in between the two fors, each time you are comparing a random number between 1-101 with the first number in your array. What you should be doing instead is compare the numbers in your array with each other.

C# populate array with unique ints No Linq or ArrayLists;

This code is buggy but can't figure out why ... want to populate an array with 7 unique random integers without using arraylists or linq! I know the logic is not okay...
class Program
{
static void Main(string[] args)
{ int current;
int[] numbers = new int[7]; // size of that array
Random rNumber = new Random();
current = rNumber.Next(1, 50);
numbers[0] = current;
Console.WriteLine("current number is {0}", current);
for (int i=1;i<7;i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < numbers.Length; j++)
{
do
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
}
else
{
numbers[j++] = current;
break;
}
}while (current == numbers[j]);
}//inner for
}//outer for
for (int l = 0; l < 7; l++) // DISPLAY NUMBERS
{
Console.WriteLine(numbers[l]);
}
}// main
}//class
want to populate an array with 7 unique integers without using
arraylists or linq!
int[] list = new int[7];
for (int i = 0; i < list.Length; i++)
{
list[i] = i;
}
EDIT
I changed your inner loop, if the random number is already in the array; create a new random and reset j to 0.
for (int i = 1; i < 7; i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < numbers.Length; j++)
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
j = 0; // reset the index iterator
}
}//inner for
numbers[i] = current; // Store the unique random integer
}//outer for
I presume you are looking for random numbers, so the other answer is not what you are looking for.
There are a couple of issues here.
The inner loop is testing for duplicates. However, it is looking from 0 through the end of the array since it is using numbers.length. This should probably be i, to compare with already set values. numbers.length is always 7 regardless of whether or not you set any of the elements.
the assignment is using j, so presuming the first element is not a duplicate, it will be overwritten each time. That should be numbers[i] = current;. No ++ necessary as the for is handling the incrementing.
if you determine that a number is a duplicate, j should be reset to zer to check against the entire list again rather than having the while in the middle.
Without a complete rewrite, the changes will look something like this:
for (int i=1;i<7;i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < i; j++) //----------------- loop through set values
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
j = 0; // -----------------------reset the counter to start over
}
}//inner for
// if we got here there is no duplicate --------------------------------
numbers[i] = current;
}//outer for
(Please note that I have not tested this code, just added the changes)
you keep overwriting the same indexes in the else, and also checking too many indices causing the first to show up as a duplicate at all times which was false...
change it to:
for (int i=1;i<7;i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < i; j++) ///< change to j < i. no need to check the others
{
do
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
}
else
{
numbers[i] = current; ///< not j++ but i to prevent writing at the same locations over and over again
break;
}
}while (current == numbers[j]);
}//inner for
}//outer for
What about this?
int[] list = new int[7];
var rn = new Random(Environment.TickCount);
for (int i = 0; i < 7; i++)
{
var next = rn.Next(1, 50);
while(Contains(list, next))
{
next = rn.Next(1, 50);
}
list[i] = next;
}
private bool Contains(IEnumerable<int> ints, int num)
{
foreach(var i in ints)
{
if(i = num) return true;
}
return false;
}

Categories

Resources