Choosing a random element from a list of tuples C# - c#

I'm quite new to programming and I am trying to add a random bot move to a small game I've made. My idea was to make a list of tuples of all of the legal moves and then pick a random tuple from that list to then deconstruct and change a value in a 2D-array.
I've looked all over the internet and found a way to make a list of tuples (I think), but couldn't manage to pick a random element from that list.
This is what I tried:
List<Tuple<int, int>> legalMoves; // To make the list of tuples
// Later on in a double for-loop that iterates through all the rows and columns of the 2D-array I check if that certain row and column combination is a legal move and then add it to the list like so:
legalMoves.Add(Tuple.Create(row, col));
//Then in a different method I try to pick a random element from that list (this doesn't work)
Random random = new Random();
int randomIndex = random.Next(legalMoves.Count);
(int, int) randomMove = legalMoves[randomIndex];
It gives the following error on the last line:
Error CS0029 Cannot implicitly convert type 'System.Tuple<int, int>' to '(int, int)'
Is there any way to make this work?
Thanks in advance!

The syntax (int, int) defines a ValueTuple<int,int> not a Tuple<int,int>. Change the list definition to :
List<ValueTuple<int, int>> legalMoves;
and Tuple.Create to ValueTuple.Create

Related

How to use SkipWhile() to skip duplicate elements in two arrays?

I am trying to get a list of numbers (upto 9) that don't contain any numbers already in a 3x3 cell from which is contained within a 81 large 2d array of integers. I'm attempting to make sudoku. There are likely better solutions that have nothing to with skipwhile or something similar, but they all seem to rely on duplicate numbers having the same index in both array which doesn't work.
int[] inCellNumbers = thisCell.Intersect(Numbers).ToArray();
int[] availableNumbers = Numbers.SkipWhile(Numbers.Contains<int>(inCellNumbers) == true);
This is the code that I tried, numbers is an array of integers and I get this error:
'MemoryExtensions.Contains(ReadOnlySpan, int)' requires a receiver of type 'ReadOnlySpan'
I was attempting to skip all numbers that are in 'inCellNumbers' and have them in 'availableNumbers' from 'Numbers'
You can use the Enumerable.Except Method:
int[] availableNumbers = Numbers.Except(inCellNumbers).ToArray();
The Enumerable.SkipWhile Method stops skipping at the first element that does not fulfill the condition. Even if others follow later that do fulfill it.
I'm not sure of the algorithm for checking around a sudoku grid but it sounds like you would want to use some hashsets.
A hashset may only have unique entries. An array or list can be dumped to a hashset using its constructor new HashSet(arrOrList), and you can evaluate immediately to one from LINQ using .ToHashSet().
As for the error, it looks like you are using List<T>.Contains<T>(T item) (notice all of the T here), which is going to check if the List contains the entire parameterized array as a single element/item. Unless Numbers is of type List<int[]> this is going to be a problem, but I'm unsure of what type you give it so this may not be the true issue. I see you are using .Contains<int> but this won't work as inCellNumbers is int[]

Create a list of tuples dynamically in C#

I want to add to a C# list of tuples declared as
var myList = List<(int, int)>();
How can I do this? The method Add doesn't accept 2 arguments. The code computes 2 integers in a for loop. I want to check in each loop whether the generated 2 integers already exist in myList and, if not, add it to myList.
"The method Add doesn't accept 2 arguments"
Correct, but you can pass a Tuple<int, int> as a single argument to the list, since that's the type that the list contains.
"The code computes 2 integers in a for loop. I want to check in each loop whether the generated 2 integers already exist in myList and, if not, add it to myList"
Some code would help here, but I would suggest creating a Tuple<int, int> from the two integers and then checking if that tuple already exists in the list or not (Tuple overrides Equals to compare the values of it's items with the corresponding items in the other Tuple, so there's no extra work to do):
// We have two computed integers
int first = 5;
int second = 8;
// Add them as a Tuple to the list if it doesn't already exist
if (!myList.Contains((first, second))) myList.Add((first, second));

Storing lots of Arrays into a List on every Loop

I have a question about storing lots of arrays into a list.
First, I initialize the array and list:
int[] arr = new int[9];
List<int[]> forkarr = new List<int[]>();
then I run through a lot of for loops and modify the array each time in order to produce all possible tic tac toe variations. While looping through all those variations, if the array is a possible board then I print it, and additionally if the array meets certain criteria for being a 'fork', then I will add it to the list like this:
if (ForkCheck.fork(arr)) { forkarr.Add(arr); Console.WriteLine("It's a Fork!");}
which also prints that message letting you know that particular array is a fork.
Now, when I am printing all of the arrays, the ones that are forks are printed properly and labeled as such.
However, when I go to print out all of the int[] elements of my list forkarr like so:
foreach (int[] arry in forkarr)
{
PrintGame.print(arry);//this is my method that prints the array
Console.WriteLine();
}
for some reason each array becomes an identical:
222
222
222
(I'm using 2 as 'X' and 1 as 'O' and 0 as 'empty' btw)
And it just prints that out over and over for all the forks.
So, something is going wrong when I am adding each modification of the array as a new element in the list I think, but I'm not sure why.
Thanks for any help.
Because you are modifying the same array and adding it to the list. Each time you done with one array array you need to create a new instance like this:
arr = new int[9];
This will create a new reference which will be independent from other arrays. And modifying it's elements wont affect the others.
For more information about value vs reference types you can refer to the question below:
What is the difference between a reference type and value type in c#?

Vba Type-Statement conversion to C#

This can probably be accomplished very easily but I have the following statement in VBA:
Type testType
integerArray(5 To 100) As Double
End Type
How can I accomplish the same in C#?
#Edit 14:16 08-07-2015
In my belief this is not the same as the question mentioned. This is a question how to convert the Type statement with an array inside. The question mentioned is only about an array with it's starting index.
Actually C# does not support those kind of arrays based on any other start-index then zero.
However you may do.
double[] myArray = new double[96];
Alternatvily you may create a dictionary with indexes as keys and the actual value:
var myDict = new Dictionary<int, double>();

choosing items based on random numbers

I am working on a small game where prizes are awarded based on a random number. So when a mission is completed and the reward has to be handed out, I want to randomly generate the prize. Currently I am getting a random number between 1 and 500 and then using a giant nested if-else statement to assign the prize based on the result. It is obvious to me that this is the wrong way to do this, however I am not sure what other way this may be done.
Any suggestions?
You can just use a prize array to hold your prices, use the random value as index into the array to pick a prize.
var prizes = new Prize[500];
//fill prizes
//randomly select index within prize array
If there are gaps or only a few numbers win anything, use a dictionary mapping from an integer to a prize ( or nothing if they key doesn't exist) instead.
There are many things you could do. For example, you could use an array to store the prizes and use the random number as the index of the array. The prize would then be whatever was stored in the array at that index. You could do the same with a List if you wanted more control.
Use a list where each item has a unique "minimum value" and information about the associated prize. Then find the item on the list that has the highest value, but is still below your random number. Or vice-versa.
The minimum value allows you to give different probabilities to prizes without using a giant array that has an entry for all numbers. The probabilities are defined by the distances of the values between different prizes.
In this example I assume that your prizes are strings (but this works with objects too).
Create a list and add all of your prizes to it, in the following way:
//using System.Collections.Generic;
var prices = new List<string>();
//Add all of your prices here
var random = new Random();
var price = prices[random.Next(0,prices.Count)];

Categories