Related
I want to write a card exchange game. I have an Arraylist of Colors in which values start from -1 to 6. Each element of this array implies id colors. There is also an ArrayList Player Properties in which cards with colors are stored. I need to create an ArrayList with eight zeros that will imply id Colors. Next, skip the ArrayList Player Properties through this array and if there is some element in the array, then increase the ArrayList Colors index by +1.
Eg:
ArrayList Colors =new ArrayList(){-1,0,1,2,3,4,5,6};
ArrayList Player Properties = new ArrayList(){0,4,6};
This array should imply that its element is an element of the Colors array
ArrayList buffer = new ArrayList(){0,0,0,0,0,0,0,0};
If an array comes to the input in this form: {0,4,6};
Then the index of this array is added by +1, like this: {0,1,0,0,0,1,0,1};
How do I implement this in code?
I don't have any code examples because I don't know how to implement it, sorry in advance that I didn't provide more code, I really need help, thank you all in advance for your help
You can use the Linq function Contains to check if a value is present in an array. Something like this:
var colors = new int[] { -1, 0, 1, 2, 3, 4, 5, 6 };
var playerProperties = new int[] { 0, 4, 4, 6 };
var result = colors.Select(c => playerProperties.Where(x => x == c).Count());
Console.WriteLine(string.Join(", ", result));
prints 0, 1, 0, 0, 0, 2, 0, 1
What you want is a histogram of the card values that you accumulate.
Since this is C# you better start thinking of a data model for each player. There are two arrays to consider, one with the card values: -1,0,..6 and one with the card counts, how many of each card a player has.
Here is how this would play out:
static class Program
{
static void Main(string[] args)
{
var player1 = new Player("Player1");
Console.WriteLine(player1);
// Player1 : 0,0,0,0,0,0,0,0
player1.Hand(0,4,6);
Console.WriteLine(player1);
// Player1: 0,1,0,0,0,1,0,1
}
}
You can to this point with the following Player class that handles the logic inside the .Hand() method.
public class Player
{
public static readonly int[] CardValues = { -1, 0, 1, 2, 3, 4, 5, 6 };
public Player(string name)
{
CardCounts = new int[CardValues.Length];
Name = name;
}
public int[] CardCounts { get; }
public string Name { get; }
public void Hand(params int[] cards)
{
foreach (var card in cards)
{
int index = Array.IndexOf(CardValues, card);
if (index >= 0)
{
CardCounts[index] += 1;
}
}
}
public override string ToString()
{
return $"{Name} : {string.Join(",", CardCounts)}";
}
}
Note that ArrayList is really old technology, and not type safe. In it place there is List<>, but in this case the length of the array is fixed since there is a finite set of card values, and that does not change, so no need for a collection, as a plain old Array would suffice.
Because your array is a fixed representation:
var Colors = new []{-1,0,1,2,3,4,5,6};
var PlayerProperties = new []{0,4,6};
var buffer = new []{0,0,0,0,0,0,0,0};
You can calculate which indexes in the buffer should be set to 1
foreach(var pp in PlayerProperties)
buffer[pp+1] += 1;
Value 0 always occurs at index 1. Value 4 always occurs at index 5. Value 6 always occurs at index 7. Thus the formula is value+1..
Edit: Changed System.Array.Clear(new[] {1,2,3}, 0, 2); to System.Array.Clear(numbers, 0, 2); but get the output [0, z0, z3] and was expecting [0,0,3]
I'm learning about C# and currently learning about arrays and Clear(). When trying to see what happens when using Clear(), I get this output:
I don't understand why this happens. Wasn't it supposed to be [0,0,3]?
My code looks like this:
Program.cs
namespace Introduction
{
internal class Program
{
/* MAIN FUNCTION */
public static void Main()
{
// RunControlFlow();
RunArrays();
}
/* ARRAYS */
public static void RunArrays()
{
// Var declaration
var array = new Arrays.Array();
array.Manipulation();
}
}
}
Arrays.cs
using System;
namespace Introduction.Arrays
{
public class Array
{
public void Manipulation()
{
var numbers = new[] {1, 2, 3};
System.Array.Clear(numbers, 0, 2);
Console.WriteLine("Manipulation | Clearing from index 0 to 2: [{0}]", string.Join(",z", numbers));
}
}
}
You are not passing the numbers array to the Clear method, you are creating a new array that has the same elements, but it's a completely different reference and has nothing to do with numbers. That is why the values in numbers stays unchanged:
Array.Clear(numbers, 0, 2);
I was trying to translate this python code for a Neural Network
https://gist.github.com/miloharper/c5db6590f26d99ab2670#file-main-py
in C#. I'm using the Math.Net Numerics for the matrixes and here is the code I've made so far in C#
using System;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics;
using MathNet.Numerics.LinearAlgebra.Double;
namespace NeuralNetwork
{
class Program
{
static void Main(string[] args)
{
NeuralNetwork NN = new NeuralNetwork();
Console.WriteLine("Random starting synaptic weights: ");
Console.WriteLine(NN.SynapticWeights);
Matrix<double> TrainingSetInput = DenseMatrix.OfArray(new double[,] { { 0, 0, 1 }, { 1, 1, 1 }, { 1, 0, 1 }, { 0, 1, 1 } });
Matrix<double> TrainingSetOutput = DenseMatrix.OfArray(new double[,] { { 0, 1, 1, 0 } }).Transpose();
NN.Train(TrainingSetInput, TrainingSetOutput, 10000);
Console.WriteLine("New synaptic weights after training: ");
Console.WriteLine(NN.SynapticWeights);
Console.WriteLine("Considering new situation {1, 0, 0} -> ?: ");
Console.WriteLine(NN.Think(DenseMatrix.OfArray(new double[,] { { 1, 0, 0 } })));
Console.ReadLine();
}
}
class NeuralNetwork
{
private Matrix<double> _SynapticWeights;
public NeuralNetwork()
{
_SynapticWeights = 2 * Matrix<double>.Build.Random(3, 1) - 1;
}
private Matrix<double> Sigmoid(Matrix<double> Input)
{
return 1 / (1 + Matrix<double>.Exp(-Input));
}
private Matrix<double> SigmoidDerivative(Matrix<double> Input)
{
return Input * (1 - Input); //NEW Exception here
}
public Matrix<double> Think(Matrix<double> Input)
{
return Sigmoid((Input * _SynapticWeights)); //Exception here (Solved)
}
public void Train(Matrix<double> TrainingInput, Matrix<double> TrainingOutput, int TrainingIterations)
{
for (int Index = 0; Index < TrainingIterations; Index++)
{
Matrix<double> Output = Think(TrainingInput);
Matrix<double> Error = TrainingOutput - Output;
Matrix<double> Adjustment = Matrix<double>.op_DotMultiply(TrainingInput.Transpose(), Error * SigmoidDerivative(Output));
_SynapticWeights += Adjustment;
}
}
public Matrix<double> SynapticWeights { get { return _SynapticWeights; } set { _SynapticWeights = value; } }
}
}
When I execute it, it shows an exception on line 53 (there is a comment at that line in the code). It says:
Matrix dimensions must agree: op1 is 4x3, op2 is 3x1
Did I copy it wrong or is it a problem with the MAth.Net library?
Thanks in advance :D
As far as I can see, the problem not in the library code. You are trying to perform an element-wise matrix multiplication with the use of op_DotMultiply function (line 53). In this case it is obvious from the error message that matrices cannot be multiplied due to difference in their size: the first one is 4x3, the second one is 3x1.
I can suggest to look at the size of these matrices: TrainingSetInput and _SynapticWeights (look at function Train, you are calling Think inside of it with the wrong sized matrices). Check if they are generated correctly. And also think if you really need an element-wise matrix multiplication or a usual multiplication.
If you need more info about matrix multiplications, you can use these links:
Element-wise:
https://en.wikipedia.org/wiki/Hadamard_product_(matrices)
Usual:
https://en.wikipedia.org/wiki/Matrix_multiplication
I've been struggling with this bit of code for a while, I can't seem to find out where I'm going wrong. Basically I want to search through an Array using an Integer and if it matches an element inside that array, it returns a bool variant as true. It's quite self explanatory but can't for the life of me figure it out! Any ideas?
Here is the code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ArrayProject
{
class ArrayProgram
{
public bool ElementAt(int[] intArray, int valueToBeFound)
{
bool intAt = false;
int numberTofind;
Console.WriteLine("Please enter the number you wish to search for within the array: ");
numberTofind = Convert.ToInt32(Console.ReadLine());
foreach (int x in intArray)
{
if (x == numberTofind)
{
intAt = true;
}
else
{
intAt = false;
}
}
if (intAt == true)
{
Console.WriteLine("{0} is in the array!", numberTofind);
}
else
{
Console.WriteLine("{0} is not in the array.", numberTofind);
}
return intAt;
}
public void RunProgram()
{
int[] intArray = { 20, 30, 40, 50, 60, 50, 40, 30, 20, 10 };
int numberTofind = 0;
ElementAt(intArray, numberTofind);
} // end RunProgram()
static void Main(string[] args)
{
ArrayProgram myArrayProgram = new ArrayProgram();
myArrayProgram.RunProgram();
Console.WriteLine("\n\n===============================");
Console.WriteLine("ArrayProgram: Press any key to finish");
Console.ReadKey();
}
}
}
int[] intArray = { 20, 30, 40, 50, 60, 50, 40, 30, 20, 10 };
int numberToFind = 0;
//variant 1 (using System.Linq):
bool bInside1 = intArray.Contains(numberToFind);
//variant2
bool bInside2 = Array.IndexOf(intArray, numberToFind) >= 0;
And if you want to write your own function:
bool IsInside(int[] arrToSearch, int nToSearch)
{
foreach (int n in arrToSearch)
{
if (n == nToSearch)
return true;
}
return false; //not found
}
The problem is that your loop continues checking elements and updating intAt even if it finds the element you're looking for.
If the array was {1, 2, 3, 4} and your code was searching for 1, it would first check index 0. This is a match, so intAt becomes true. Next it will try index 1. This one isn't a match, so it sets intAt to be false. Then it will try indices 2, 3, etc. never finding the match.
You could do this pretty easy with Linq.
using System.Linq;
public static string test(int[] numberArray, int find)
{
bool s = false;
numberArray.ToList().ForEach(x => { if (x == find) s = true; });
return s ? "It contains it." : "Can't find it.";
}
However there is a method for this. You can use .Contains with an array as a person said above me.
If you want to keep your implementation, try this:
class ArrayProgram
{
public bool ElementAt(int[] intArray, int valueToBeFound)
{
foreach (int x in intArray)
if (x == valueToBeFound) // if you found your value in the array
return true; // you return true
return false; // otherwise, by this point the foreach has looped through all the elements and hasn't once entered in the above if (so it hasn't found your value) = you return false
}
public void RunProgram()
{
int[] intArray = { 20, 30, 40, 50, 60, 50, 40, 30, 20, 10,99 };
int numberTofind;
// I noticed that you're not using the numberTofind value either, so:
Console.Write("Please enter the number you wish to search for within the array: ");
numberTofind = Convert.ToInt32(Console.ReadLine());
// and since you made a function that returns true if your value has been found, you might as well use it like this
if(ElementAt(intArray, numberTofind)) // if the function returns true
Console.WriteLine("{0} is in the array!", numberTofind);
else
Console.WriteLine("{0} is not in the array.", numberTofind);
} // end RunProgram()
static void Main(string[] args)
{
ArrayProgram myArrayProgram = new ArrayProgram();
myArrayProgram.RunProgram();
Console.WriteLine("\n\n===============================");
Console.WriteLine("ArrayProgram: Press any key to finish");
Console.ReadKey();
}
}
Okay, so I'll admit up front this one's going to be a bit long. I'm writing a chess engine for C#, with the eventual goal including UCI implementation. I've got it to the point where, given a board, the engine will generate a list of all valid moves; however, my evaluation code seems to be struggling, because when playing a game against itself, the engine will move two pawns on either side, and then just move a piece back and forth on either side. I'm going to outline the crucial parts of the program below in order to best allow you to understand under what conditions my code is called and used, in the hope that it will help you answer my question.
This is just the main method called by my interface, nothing exciting here.
class BreezeEngine
{
// Declares Piece Values
public const int pawn = 1, knight = 4, bishop = 6, rook = 8, queen = 16, king = 60;
public const int toDepth = 4;
public static void BoardGen(string mode)
{
Board chessBoard = new Board(new int[8, 8] {
{ 8, 4, 6,16,60, 6, 4, 8 },
{ 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{-1,-1,-1,-1,-1,-1,-1,-1 },
{-8,-4,-6,-16,-60,-6,-4,-8 }
}, 0, true, true, true);
PlayGame(chessBoard, true);
return;
}
This method is working just fine.
It returns a list of moves with format
x1, y1, x2, y2, weight
The weight this method generates is the value of whatever piece is killed. If you have questions, let me know.
private static List<int[]> CalcFutures(Board chessBoard)
{
// Move generation stuff.
}
This method isn't complete yet (since it doesn't handle castling or en passant), but it's basically just to generate a new board object from any given move.
private static Board MoveToBoard(int[] move, Board board)
{
int[,] newBoard = new int[8, 8];
Array.Copy(board.Pieces(), newBoard, 64);
newBoard[move[3], move[2]] = newBoard[move[1], move[0]];
newBoard[move[1], move[0]] = 0;
if (newBoard[move[3], move[2]] == pawn && move[3] == 7) newBoard[move[3], move[2]] = queen;
if (newBoard[move[3], move[2]] == -pawn && move[3] == 0) newBoard[move[3], move[2]] = -queen;
return new Board(newBoard, board.Depth() + 1, !board.IsTurn(), true, true);
}
This code is probably not needed, but I'm including it on the off chance that a typo in here is causing the bug. This is just a very basic user interface to allow me to play a game against my engine, or have the engine play itself.
private static void PlayGame(Board chessBoard, bool demo)
{
int[] move = new int[5];
if (!(chessBoard.IsTurn() || demo))
{
Console.WriteLine("Type in your move one integer at a time: x1,y1,x2,y2");
move[0] = Convert.ToInt32(Console.ReadLine());
move[1] = Convert.ToInt32(Console.ReadLine());
move[2] = Convert.ToInt32(Console.ReadLine());
move[3] = Convert.ToInt32(Console.ReadLine());
}
else
{
Console.WriteLine("Calculating Move..." + chessBoard.IsTurn());
move = Evaluate(CalcFutures(chessBoard), chessBoard);
}
if (Math.Abs(chessBoard.Pieces()[move[3], move[2]]) == king)
{
if (chessBoard.IsTurn()) Console.Write("White Wins");
else Console.Write("Black Wins");
return;
}
chessBoard = MoveToBoard(move, chessBoard);
chessBoard.SetDepth(0);
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
Console.Write(chessBoard.Pieces()[i, j].ToString().PadLeft(3, ' '));
}
Console.WriteLine();
}
PlayGame(chessBoard, demo);
}
}
Now, I'm going on a brief tangent before presenting the evaluation algorithm itself. This is the board object you've seen referenced many other times throughout the code. It contains an array for the chess board, as well as other variables necessary for defining the game's current state.
class Board
{
bool isTurn;
bool castling;
bool enemyCastling;
int[,] pieces = new int[8, 8];
int weight = 0;
int depth;
public Board(int[,] inBoard, int inDepth, bool inIsTurn, bool inCastling, bool inEnemyCastling)
{
Array.Copy(inBoard, pieces, 64);
isTurn = inIsTurn;
castling = inCastling;
enemyCastling = inEnemyCastling;
depth = inDepth;
}
public int Weight()
{
int sum = 0;
foreach (int i in pieces)
sum += i;
weight = sum;
return weight;
}
public int[,] Pieces() { return pieces; }
public bool IsTurn() { return isTurn; }
public void ToggleTurn() { isTurn = !isTurn; return; }
public int Depth() { return depth; }
public void SetDepth(int inDepth)
{
depth = inDepth;
}
}
Now that I've outlined the rest of my program, here is the evaluation method itself. The code takes in a list of moves, and if it is to the furthest depth that is supposed to be searched, it simply returns the one with the greatest absolute value. If it's not to the bottom, it simply generates a list of futures, for each move in the list of futures it receives, and calls itself again. The returned value is then added to the original move's weight, and compared to the best move it has found so far. However, I've been having issues with this approach, and I'm guessing it's either because I've misunderstood how negamax is supposed to work, or I've made a typo somewhere along the way. Any idea what's going on?
private static int[] Evaluate(List<int[]> futures, Board chessBoard)
{
int[] bestMove = new int[5];
bestMove[0] = 30;
if (chessBoard.Depth() >= toDepth)
{
foreach (int[] move in futures)
{
if (Math.Abs(move[4]) > Math.Abs(bestMove[4]))
{
Array.Copy(move, bestMove, 5);
}
}
}
else
{
foreach (int[] move in futures)
{
Board newBoard = MoveToBoard(move, chessBoard);
int[] testMove = Evaluate(CalcFutures(newBoard), newBoard);
move[4] += testMove[4];
if (bestMove[0] == 30) bestMove = move;
if (chessBoard.IsTurn())
{
if (move[4] > bestMove[4])
{
Array.Copy(move, bestMove, 5);
}
}
else
{
if (move[4] < bestMove[4])
{
Array.Copy(move, bestMove, 5);
}
}
}
}
return bestMove;
}
You're doing the evaluation wrong. You have to make sure that either side is picking its own best future. Honestly, minimax is easy to implement given your data structure for moves. Here's the fixed evaluation function.
public static int[] Evaluate(List<int[]> futures, Board chessBoard)
{
int[] bestMove = new int[5];
Random rndMove = new Random();
Array.Copy(futures[rndMove.Next(futures.Count)], bestMove, 5);
if (chessBoard.Depth() == toDepth)
{
if (chessBoard.IsTurn())
{
// Maximum
//bestMove[4] = -1000000;
foreach (int[] move in futures)
{
if (move[4] > bestMove[4])
{
Array.Copy(move, bestMove, 5);
}
}
}
else
{
// Minimum
//bestMove[4] = 1000000;
foreach (int[] move in futures)
{
if (move[4] < bestMove[4])
{
Array.Copy(move, bestMove, 5);
}
}
}
}
else
{
if (chessBoard.IsTurn())
{
// Maximum
//bestMove[4] = -1000000;
foreach (int[] move in futures)
{
if (Math.Abs(chessBoard.Pieces()[move[3], move[2]]) == king) return move;
Board newBoard = MoveToBoard(move, chessBoard);
move[4] += Evaluate(CalcFutures(newBoard), newBoard)[4];
if (move[4] > bestMove[4])
{
Array.Copy(move, bestMove, 5);
}
}
}
else
{
// Minimum
//bestMove[4] = 1000000;
foreach (int[] move in futures)
{
if (Math.Abs(chessBoard.Pieces()[move[3], move[2]]) == king) return move;
Board newBoard = MoveToBoard(move, chessBoard);
move[4] += Evaluate(CalcFutures(newBoard), newBoard)[4];
if (move[4] < bestMove[4])
{
Array.Copy(move, bestMove, 5);
}
}
}
}
//Console.WriteLine(bestMove[4]);
return bestMove;
}