C# Min Max Connect R game Grid Filling issue - c#

I'm having an issue with my Connect R program. I can have it play playervsplayer just fine but, there is something wrong wit my MinMax that I don't understand. I pass in my 2D array into the algorithm in order to traverse it and have the PlaceT algorithm in my MinMax to add into a temporary 2D array for when I recursively call the MinMax. For some reason it actually adds it to my main 2Darray so by the time the function ends its filled up when I only wanted one item to be added. I included both the PlaceT function as well as the MinMax. I also did include a picture for reference
The idea is to traverse through the 2D array from the bottom and if there is a blank space than add to a temp 2D array than recall the Max recursively, and it does this till the traversal ends. then it takes all the added moves and sees which one has the most score than returns that to the main MinMax which is supposed to be used to place the tile where its supposed to go. Let me know if you want to see any of the other code outside of those algorithms.
static void PlaceT(int ogC, int ogR, int c, int r, string[,] board, string id)
{
if (id == "R")
{
if(r - 1 >= 0)
{
if (board[r - 1, c] == "R" || board[r - 1, c] == "B")
{
PlaceT(ogC, ogR, c, r - 1, board, id);
}
else
{
board[r - 1, c] = "R";
}
}
}
else if (id == "B")
{
if(r - 1 >= 0)
{
if (board[r - 1, c] == "B" || board[r - 1, c] == "R")
{
PlaceT(ogC, ogR, c, r - 1, board, id);
}
else
{
board[r - 1, c] = "B";
}
}
}
}
static void MinMax(string [,] board, int row, int col, string ID, int count, string otherID, bool isComp)
{
string[,] tempB = board;
AIMove bestmove = new AIMove();
bestmove.x = MaxMove(tempB, row, col, ID, count, otherID, isComp).x;
PlaceT(col, row, bestmove.x, row, board, ID);
return;
}
static AIMove MaxMove(string[,] board, int row, int col, string ID, int count, string otherID, bool isComp)
{
AIMove move = new AIMove();
string[,] grid = new string[row,col];
grid = board;
if (isFull(grid))
{
move.score = 0;
return move;
}
else if(rInRow(grid, count, row, col, ID) == 10)
{
move.score = 10;
return move;
}
else if(rInRow(grid, count, row, col, otherID) == 10)
{
move.score = -10;
return move;
}
List<AIMove> moves = new List<AIMove>();
for (int y = row - 1; y >= 0; y--)
{
for (int x = col - 1; x >= 0; x--)
{
if (grid[y, x] != "R" && grid[y, x] != "B")
{
move.x = x;
move.y = y;
if(isComp)
{
PlaceT(col, row, move.x, row, grid, ID);
isComp = !isComp;
move.score = MaxMove(grid, row, col, ID, count, otherID, isComp).score;
}
else
{
PlaceT(col, row, move.x, row, grid, otherID);
isComp = !isComp;
move.score = MaxMove(grid, row, col, ID, count, otherID, isComp).score;
}
moves.Add(move);
}
}
}
grid = board;
int _best = 0;
if(isComp)
{
int _bestScore = -100;
for (int i = 0; i < moves.Count; i++)
{
if (moves[i].score > _best)
{
_best = i;
_bestScore = moves[i].score;
}
}
}
else
{
int _bestScore = 100;
for (int i = 0; i < moves.Count; i++)
{
if (moves[i].score < _best)
{
_best = i;
_bestScore = moves[i].score;
}
}
}
return moves[_best];
}
Image of Program running

Related

C# return string in Sine-Wave format

I'm trying to create a function which will return string in Triangle Sine-Wave format:
but currently, my format is only in Wave format:
Code below:
public static void printWave(string str)
{
int height = 3;
// Get length of the string
int len = str.Length;
// Create a 2d character array
char[,] matrixArray = new char[height, len];
char[] charArray = str.ToCharArray();
// for counting the
// rows of the ZigZag
int row = 0;
bool down = true;
for (int i = 0; i < len; i++)
{
// put characters
// in the matrix
matrixArray[row, i] = charArray[i];
// You have reached the bottom
if (row == height - 1)
down = false;
else if (row == 0)
down = true;
if (down)
row++;
else
row--;
}
// Print the Zig-Zag String
for (int i = 0; i < height; i++)
{
for (int j = 0; j < len; j++)
{
Console.Write(matrixArray[i, j] + " ");
}
Console.Write("\n");
}
}
Can you please help me modify my code to it will return triangle sin wave format?
We can use 3 separate StringBuilders to append to depending on our boolean top and a simple even value comparison. A quick TL;DR is that anything at an even index goes in the middle row, and then we flip between appending to the top or bottom row:
public static void printWave(string str)
{
//for use to determine top or bottom StringBuilder
bool top = true;
//will be used to generate each row of the output
StringBuilder topString = new StringBuilder();
StringBuilder middleString = new StringBuilder();
StringBuilder bottomString = new StringBuilder();
//iterate through paramter string
for (int i = 0; i < str.Length; i++)
{
//if char is at an even index, it goes in the middle StringBuilder, blank spaces in top and bottom builders
if (i%2 == 0)
{
topString.Append(" ");
middleString.Append(str[i]);
bottomString.Append(" ");
}
//if not even index, determine top or bottom row
else
{
//simply check our boolean and then flip it after use
if (top)
{
topString.Append(str[i]);
middleString.Append(" ");
bottomString.Append(" ");
top = false;
}
else
{
topString.Append(" ");
middleString.Append(" ");
bottomString.Append(str[i]);
top = true;
}
}
}
//write each row of strings on new lines
Console.WriteLine(topString.ToString());
Console.WriteLine(middleString.ToString());
Console.WriteLine(bottomString.ToString());
}
For a variable height:
public static void printWave(string str)
{
//height we want the wave to reach
int height = 5;
//determine "middle" row
int startingRow = height / 2;
int currentRow = startingRow; //this one is for modifying inside loop
bool up = true;
//2D array to hold the rows
char[,] arr = new char[height, str.Length];
for (int i = 0; i < str.Length; i++)
{
for (int j = 0; j < height; j++)
{
if (j == currentRow)
{
arr[j, i] = str[i];
}
else
arr[j, i] = ' ';
}
//could probably break this into more digestible pieces if time to think about it
if (up)
{
if (currentRow == 0)
{
up = false;
currentRow++;
}
else
{
currentRow--;
}
}
else
{
if (currentRow == height - 1)
{
up = true;
currentRow--;
}
else
{
currentRow++;
}
}
}
for (int k = 0; k < height; k++)
{
for (int l = 0; l < str.Length; l++)
{
Console.Write(arr[k, l]);
}
Console.WriteLine();
}
}
Examples of height = 5 and height = 6 output:
And finally, height = 7
This version works, but it's hard-coded to just the 3 rows like the question shows. If larger waves are needed, or especially if the size of the wave depends on the input string, then this may be hard to adjust to the requirements.
public static void PrintWave(string str)
{
printWithRowLogic(str, (i) => (i - 1) % 4 == 0);
Console.WriteLine();
printWithRowLogic(str, (i) => i % 2 == 0);
Console.WriteLine();
printWithRowLogic(str, (i) => (i - 3) % 4 == 0);
}
private static void printWithRowLogic(string str, Func<int, bool> checkLogic)
{
for (int i = 0; i < str.Length; i++)
Console.Write(checkLogic(i) ? str[i] : ' ');
}

Need advice on optimizing warehouse layout

I'm currently working for a distribution center with ~500 shelves with items for sale and ready to be shipped out to customers. I have decided to create a ranking for each aisle, where the best selling products will be stored at the front and the worst selling products will be stored at the back. I assumed that this would automatically improve efficience in my warehouse. However, after implementing this (see here). After using BFS to simulate a warehouse worker's route it's turned out that this new layout is actually taking more steps for a worker to complete than a regular non-optimized layout..
This is my code for BFS, however I think my problem lies in the way I decide where high demand items go, not in my BFS.
List<String> findPathBFS(magazijnObject[,] grid, bool[,] vis,
string start, string goal)
{
List<string> path = new List<string>();
// Stores indices of the matrix cells
Queue<pair> q = new Queue<pair>();
int row = 0; int col = 0;
// Mark the starting cell as visited
// and push it into the queue
for (int x = 0; x < grid.GetLength(0); x++)
for (int y = 0; y < grid.GetLength(1); y++)
{
if (grid[x, y].Locatie == start)
{
row = x; col = y;
x = grid.GetLength(0); y = grid.GetLength(1);
break;
}
}
q.Enqueue(new pair(row, col, null));
vis[row, col] = true;
// Iterate while the queue
// is not empty
while (q.Count != 0)
{
pair cell = q.Peek();
int x = cell.first;
int y = cell.second;
if (grid[x, y].Locatie == goal)
{
//Console.WriteLine(cell.parent.first + " " + cell.parent.second);
findPath(cell, path);
return path;
}
q.Dequeue();
// Go to the adjacent cells
for (int i = 0; i < 4; i++)
{
int adjx = x + dRow[i];
int adjy = y + dCol[i];
if (isValid(vis, adjx, adjy, grid))
{
if (grid[adjx, adjy].Loopbaar || grid[adjx, adjy].Locatie == goal)
#Locatie = Location of item in aisle, Loopbaar = whether or not a worker can walk here.
{
q.Enqueue(new pair(adjx, adjy, cell));
vis[adjx, adjy] = true;
}
}
}
}
return path;
}
And this is my pair Class which defines a cell and it's parent
class pair
{
public int first, second;
public pair parent;
public pair(int first, int second, pair parent)
{
this.first = first;
this.second = second;
this.parent = parent;
}
public String toString()
{
return (first + " " + second);
}
}
static int[] dRow = { -1, 0, 1, 0 };
static int[] dCol = { 0, 1, 0, -1 };
static bool isValid(bool[,] vis,
int row, int col, magazijnObject[,] test)
{
// If cell lies out of bounds
if (row < 0 || col < 0 ||
row >= test.GetLength(0) || col >= test.GetLength(1))
return false;
// If cell is already visited
if (vis[row, col])
return false;
// Otherwise
return true;
}
private static void findPath(pair node, List<String> path)
{
if (node != null)
{
findPath(node.parent, path);
path.Add(node.toString());
}
}
I'm curious to see whether you have any ideas on how to improve this layout in a way. As this obviously is not an improvement.
Kind regards,
D.

2D array 3x9 matrix get the index of the next two elements of the current index and check if it is equal to 0

I am a total newbie to programming and i have been following some tutorials on array related to housie ticket generator.The point where I am stuck is that, I have to check each rows and each rows of the 3x9 matrix should not have more the two empty cells or it cannot have more then two cells filled next to each other.I am putting random numbers on the arrays and trying to validate the rules but,the program crashes. Can someone please give me an idea.?
This is what i've tried.
for(int columnIndex=0;columnIndex<=6;columnIndex++)
{
if(game[i,columnIndex+2]!=0)
{
return -1;
}
}
And this is the whole code
using System;
namespace HelloWorld
{
class Program
{
public static void Main (String[] args)
{
for(int times=0;times<2;times++)
{
startGame();
Console.WriteLine("******************************************************************");
}
}
private static void startGame()
{
int[,] game = new int[3, 9];
int occupancyLimit = 15;
while (occupancyLimit > 0)
{
int i = getRandomNumber(3);
int j = getRandomNumber(9);
//Console.Write(i);
//Console.Write(j);
// Console.Write(game[i,j]+" ");
int data = validateAndReturnNumber(i, j, game);
if (data>0)
{
game[i, j] = data;
occupancyLimit--;
//Console.WriteLine(game[i,j]);
}
}
for (int i = 0; i < game.GetLength(0); i++)
{
for (int j = 0; j < game.GetLength(1); j++)
{
Console.Write(game[i,j] + "\t");
}
Console.WriteLine();
}
}
private static int validateAndReturnNumber(int i, int j, int[,] game)
{
//do not override existing elements in array
if (game[i,j] != 0)
{
return -1;
}
//column cannot have more then two elements
int columncounter = 0;
for(int c=0;c<3;c++)
{
if(game[c,j]!=0)
{
columncounter++;
}
}
if(columncounter>=2)
{
return -1;
}
/*
//rows cannot have more then two cells filled in and
//rows cannot have more then two empty cells
for(int columnIndex=0;columnIndex<=6;columnIndex++)
{
if(game[i,columnIndex+2]!=0)
{
return -1;
}
}
*/
// rows cannot have more then 5 elements
int rowcounter = 0;
for(int r=0;r<9;r++)
{
if(game[i,r]!=0)
{
rowcounter++;
}
}
//Applying, rows cannot have more then 5 elements
if(rowcounter>=5)
{
return -1;
}
//return getRandomNumberForColumn(j);
int data = 0;
Boolean isValueSet = false;
do
{
data = getRandomNumberForColumn(j);
isValueSet = isValueExistsInCol(game, i, j, data);
} while (isValueSet);
return data;
}
private static bool isValueExistsInCol(int[,] game, int i, int j, int data)
{
Boolean status = false;
for(int k=0;k<3;k++)
{
if(game[k,j]==data)
{
status = true;
break;
}
}
return status;
}
private static int getRandomNumberForColumn(int high)
{
if(high==0)
{
high = 10;
}
else
{
high=(high + 1) * 10;
}
int low = high - 9;
Random random = new Random();
return random.Next(high-low)+low;
}
private static int getRandomNumber(int max)
{
Random random = new Random();
int num=random.Next(max);
return (num);
}
}
}
Why your for loop does not work:
for (int columnIndex = 0; columnIndex <= 6; columnIndex++)
{
if (game[i, columnIndex + 2] != 0)
{
return -1;
}
}
This loop does not take j into account. It is testing for previous numbers added, as soon as one previous number fails this test, it will fail indefinitely. This creates an infinite loop. This loop also fails if a number is placed in any position past 1, while it needs to fill 5 positions to succeed. This is mathematically impossible.
This:
'should not have more the two empty cells or it cannot have more then two cells' is also mathematically impossible. a row of 9 cannot have less than 2 full and less than 2 empty at the same time.
I think you are after 2 empty or full consecutively in a row. For that testing for two empty in a row cannot be achieved as it starts empty, and you are testing it before you fill it. Fortunately this is a redundant test that will always be true based on all of the other test cases.
No more than 2 full in a row is possible, but can also lead to impossible scenarios. I have added a check that resets the scenario if it has not found the solution after 1000 guesses.
using System;
namespace HelloWorld
{
class Program
{
public static void Main(String[] args)
{
for (int times = 0; times < 2; times++)
{
startGame();
// Console.WriteLine("******************************************************************");
}
}
private static void startGame()
{
int iCount = 0;
int[,] game = new int[3, 9];
int occupancyLimit = 15;
while (occupancyLimit > 0)
{
int i = getRandomNumber(3);
int j = getRandomNumber(9);
//Console.Write(i);
//Console.Write(j);
// Console.Write(game[i,j]+" ");
int data = validateAndReturnNumber(i, j, game);
if (data > 0)
{
game[i, j] = data;
occupancyLimit--;
//Console.WriteLine(game[i,j]);
}
else
{
iCount++;
//Console.WriteLine(iCount);
//printGame(game);
// If X many fails, retry
if(iCount > 1000)
{
iCount = 0;
game = new int[3, 9];
occupancyLimit = 15;
}
}
// If you want to check for zeros you would need to do it here. And use while(true) above
/*
if( //Check for zeros)
{
break; // Ends While loop
}
else
{
// Reset and try again
iCount = 0;
game = new int[3, 9];
occupancyLimit = 15;
}
*/
}
printGame(game);
}
private static void printGame(int[,] game)
{
for (int i = 0; i < game.GetLength(0); i++)
{
for (int j = 0; j < game.GetLength(1); j++)
{
Console.Write(game[i, j] + "\t");
}
Console.WriteLine();
}
Console.WriteLine("******************************************************************");
}
private static int validateAndReturnNumber(int i, int j, int[,] game)
{
//do not override existing elements in array
if (game[i, j] != 0)
{
return -1;
}
//column cannot have more then two elements
int columncounter = 0;
for (int c = 0; c < 3; c++)
{
if (game[c, j] != 0)
{
columncounter++;
}
}
if (columncounter >= 2)
{
return -1;
}
if(
(j != 0 && j != 1 && game[i, j - 2] != 0 && game[i, j - 1] != 0) || // 12X
(j != 0 && j != 8 && game[i, j - 1] != 0 && game[i, j + 1] != 0) || // 1X3
(j != 7 && j != 8 && game[i, j + 1] != 0 && game[i, j + 2] != 0) // X23
)
{
return -1;
}
//for (int columnIndex = 0; columnIndex <= 6; columnIndex++)
//{
// if (game[i, columnIndex + 2] != 0)
// {
// return -1;
// }
//}
// rows cannot have more then 5 elements
int rowcounter = 0;
for (int r = 0; r < 9; r++)
{
if (game[i, r] != 0)
{
rowcounter++;
}
}
//Applying, rows cannot have more then 5 elements
if (rowcounter >= 5)
{
return -1;
}
//return getRandomNumberForColumn(j);
int data = 0;
Boolean isValueSet = false;
do
{
data = getRandomNumberForColumn(j);
isValueSet = isValueExistsInCol(game, i, j, data);
} while (isValueSet);
return data;
}
private static bool isValueExistsInCol(int[,] game, int i, int j, int data)
{
Boolean status = false;
for (int k = 0; k < 3; k++)
{
if (game[k, j] == data)
{
status = true;
break;
}
}
return status;
}
private static int getRandomNumberForColumn(int high)
{
if (high == 0)
{
high = 10;
}
else
{
high = (high + 1) * 10;
}
int low = high - 9;
Random random = new Random();
return random.Next(high - low) + low;
}
private static int getRandomNumber(int max)
{
Random random = new Random();
int num = random.Next(max);
return (num);
}
}
}
Cheers!

Trouble creating algorithm that modifies elements of a 2d array

I am having trouble editing the values of a 2d char array.
char[,] chrRaster = new char[4, 5];
After adding values to the array and printing it to the console, I get:
// Input example:
*****
**.**
*****
****.
I am trying to make an algorithm that replaces every '*' that is beside, under or above a '.' by a '.' and then printing this to the console.
// Output after algorithm example:
**.**
*...*
**.*.
***..
I have tried converting the 2d char array to a 2d string array and then using IndexOf('*') to replace every '*' that is beside, under or above a '.', and I also tried calculating this using a number of if and for loops without any luck.
static void Main(string[] args)
{
// Variablen
int intTestgeval = 0; // Number of times you want program to repeat
int intN = 0; // Number of rows
int intM = 0; // Number of coloms
char chrGrond; // Used to store '*' or '.'
char[,] chrRaster; // 2d char array used to store all values
// Code
try
{
intTestgeval = Int32.Parse(Console.ReadLine()); // Number of times program will repeat
if(intTestgeval > 150) // Program can not repeat more then 150 times
{
throw new Exception();
}
}
catch (Exception)
{
Environment.Exit(0);
}
intN = Controle(intN); // Number of rows ophalen
intM = Controle(intM); // Number of Coloms ophalen
chrRaster = new char[intN, intM]; // Initializing array with user input
for (int intR = 0; intR < intTestgeval; intR++) // Print 2d array to console
{
for(int intY = 0; intY < intN; intY++)
{
for(int intZ = 0; intZ < intM; intZ++)
{
chrGrond = Convert.ToChar(Console.ReadKey().KeyChar);
chrRaster[intY, intZ] = chrGrond;
}
Console.WriteLine();
}
instorten[intR] = Instorten(chrRaster, intN, intM); // Ignore this part, that's another part of my assignment not related to my question.
}
}
static int Controle( int intX )
{
try
{
intX = Int32.Parse(Console.ReadLine());
if (intX > 150 || intX < 1) // Length of row and colom can not exceed 20 and can not go lower then 1
{
throw new Exception();
}
return intX;
}
catch // Program will off if value does not meet requirements
{
Environment.Exit(0);
return intX;
}
}
// It is this part of the program I need help with. This is what I tried but can't get any further
static int Instorten(char[,] chrRaster, int intN, int intM)
{
for (int intY = 0; intY < intN; intY++)
{
for (int intZ = 0; intZ < intM; intZ++)
{
if(chrRaster[intY, intZ] == '.' && chrRaster[intY, intZ + 1] == '*' || chrRaster[intY, intZ] == '*' && chrRaster[intY, intZ + 1] == '.')
{
}
}
Console.WriteLine();
}
int intm = 0;
return intm;
}
}
One way to do this would be to make a copy of the array and then iterate over it, examining each item. If the item is a '.', then update the neighbors of this item in the original array.
To determine the neighbors, we simply add one to the row to get the neighbor below, subtract one from the row to get the neighbor above, and similarly we can get the right and left neighbors by adding/subtracting from the column value. Of course we need to ensure that we're inside the bounds of the array before doing anything.
We could write a method with this logic that might look like:
private static void ExposeDotNeighbors(char[,] input)
{
if (input == null) return;
// Make a copy of the input array that we can iterate over
// so that we don't analyze items that we've already changed
var copy = (char[,]) input.Clone();
for (var row = 0; row <= copy.GetUpperBound(0); row++)
{
for (var col = 0; col <= copy.GetUpperBound(1); col++)
{
if (copy[row, col] == '.')
{
// Update neighbors in original array
// Above = [row - 1, col], Below = [row + 1, col],
// Left = [row, col - 1], Right = [row, col + 1]
// Before updating, make sure we're inside the array bounds
if (row > 0) input[row - 1, col] = '.';
if (row < input.GetUpperBound(0)) input[row + 1, col] = '.';
if (col > 0) input[row, col - 1] = '.';
if (col < input.GetUpperBound(1)) input[row, col + 1] = '.';
}
}
}
}
We can also write some helper methods that will give us the initial array and to print an array to the console (also one that will write a header to the console):
private static char[,] GetInitialArray()
{
var initialArray = new char[4, 5];
for (var row = 0; row <= initialArray.GetUpperBound(0); row++)
{
for (var col = 0; col <= initialArray.GetUpperBound(1); col++)
{
if ((row == 1 && col == 2) || (row == 3 && col == 4))
{
initialArray[row, col] = '.';
}
else
{
initialArray[row, col] = '*';
}
}
}
return initialArray;
}
private static void PrintArrayToConsole(char[,] input)
{
if (input == null) return;
for (var row = 0; row <= input.GetUpperBound(0); row++)
{
for (var col = 0; col <= input.GetUpperBound(1); col++)
{
Console.Write(input[row, col]);
}
Console.WriteLine();
}
}
private static void WriteHeader(string headerText)
{
if (string.IsNullOrEmpty(headerText))
{
Console.Write(new string('═', Console.WindowWidth));
return;
}
Console.WriteLine('╔' + new string('═', headerText.Length + 2) + '╗');
Console.WriteLine($"║ {headerText} ║");
Console.WriteLine('╚' + new string('═', headerText.Length + 2) + '╝');
}
With these helper methods, we can then write code like:
private static void Main()
{
var chrRaster = GetInitialArray();
WriteHeader("Before");
PrintArrayToConsole(chrRaster);
ExposeDotNeighbors(chrRaster);
WriteHeader("After");
PrintArrayToConsole(chrRaster);
GetKeyFromUser("\nDone! Press any key to exit...");
}
And out output would look like:
I noticed that you also appear to be getting the values from the user, and using try/catch blocks to validate the input. A better approach might be to write a helper method that takes in a string that represents the "prompt" to the user, and a validation method that can be used to validate the input. With this, we can keep asking the user for input until they enter something valid.
Below are methods that get an integer and a character from the user, and allow the caller to pass in a function that can be used for validation. These methods will not return until the user enters valid input:
private static char GetCharFromUser(string prompt, Func<char, bool> validator = null)
{
char result;
var cursorTop = Console.CursorTop;
do
{
ClearSpecificLineAndWrite(cursorTop, prompt);
result = Console.ReadKey().KeyChar;
} while (!(validator?.Invoke(result) ?? true));
Console.WriteLine();
return result;
}
private static int GetIntFromUser(string prompt, Func<int, bool> validator = null)
{
int result;
var cursorTop = Console.CursorTop;
do
{
ClearSpecificLineAndWrite(cursorTop, prompt);
} while (!int.TryParse(Console.ReadLine(), out result) ||
!(validator?.Invoke(result) ?? true));
return result;
}
private static void ClearSpecificLineAndWrite(int cursorTop, string message)
{
Console.SetCursorPosition(0, cursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, cursorTop);
Console.Write(message);
}
We can then re-write our GetInitialArray method to use these methods to get the dimensions and values from the user:
private static char[,] GetInitialArray()
{
const int maxCols = 20;
const int maxRows = 20;
var numCols = GetIntFromUser(
$"How many columns do you want (1 - {maxCols}): ",
i => i > 0 && i <= maxCols);
var numRows = GetIntFromUser(
$"How many rows do you want (1 - {maxRows}): ",
i => i > 0 && i <= maxRows);
var initialArray = new char[numRows, numCols];
for (var row = 0; row <= initialArray.GetUpperBound(0); row++)
{
for (var col = 0; col <= initialArray.GetUpperBound(1); col++)
{
initialArray[row, col] = GetCharFromUser(
$"Enter value for [{row}, {col}] ('.' or '*'): ",
c => c == '.' || c == '*');
}
}
return initialArray;
}
And now our output might look like this:
If you try it, notice that you cannot enter an illegal value. The program just waits for you to read the instructions and enter a valid number or character. :)
Here is the algorithm that does what you want. I have tried to explain my code in the comments. The output will match what you're looking for.
static void Main(string[] args)
{
char STAR = '*';
char DOT = '.';
var input = new char[,]
{
{ STAR,STAR,STAR,STAR,STAR},
{ STAR,STAR,DOT,STAR,STAR},
{ STAR,STAR,STAR,STAR,STAR},
{ STAR,STAR,STAR,STAR,DOT}
};
var output = new char[4, 5];
// Copy each from input to output, checking if it touches a '.'
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 5; y ++)
{
if (input[x, y] == STAR)
{
var isDot = false;
// Check left
if (x > 0)
isDot = input[x - 1, y] == DOT;
// Check right
if (x < 3)
isDot = isDot || (input[x + 1, y] == DOT);
// Check above
if (y > 0)
isDot = isDot || (input[x, y - 1] == DOT);
// Check below
if (y < 4)
isDot = isDot || (input[x, y + 1]) == DOT;
output[x, y] = isDot ? DOT : STAR;
}
else
{
output[x, y] = input[x, y];
}
}
}
// Print output
for (int x = 0; x < 4; x ++)
{
for (int y = 0; y < 5; y ++)
{
Console.Write(output[x, y]);
}
Console.WriteLine();
}
Console.Read();
}
You can go like this :
using System;
public class chars
{
public static void Main(string[] args)
{
char[,] charArray = new char[,] {{'*','*','*','*','*'},
{'*','*','.','*','*'},
{'*','*','*','*','*'},
{'*','*','*','*','.'}};
int[,] holdIndex = new int[4, 5];
for(int i = 0; i<4; i++) // get allindexes containing '.'
{
for(int j = 0; j<5; j++)
{
if(charArray[i,j] == '.')
holdIndex[i,j] = 1;
else
holdIndex[i,j] = 0;
}
}
for(int i = 0; i<4; i++)
{
for(int j = 0; j<5; j++)
{
if(holdIndex[i,j] == 1)
{
if(i!=0)
charArray[i-1,j] = '.'; //up
if(j!=0)
charArray[i,j-1] = '.'; // left
if(j!=4)
charArray[i,j+1] = '.'; //right
if(i!=3)
charArray[i+1,j] = '.'; //down
}
}
}
for(int i = 0; i<4; i++)
{
for(int j = 0; j<5; j++)
{
Console.Write(charArray[i,j]);
}
Console.WriteLine();
}
Console.Read();
}
}

Seeded random plotting 2d grid

This has been bugging me for a few hours so I was wondering if anyone could help me out as I might be thinking about this the wrong way.
I want to be able to get a boolean value from a set of x and y coordinates on an grid with an infinite width and height. There are also other constraints, along the x axis there needs to be at least n places between two true values, I would also need to know the number of true values in the area from 0,0 to x,y.
The width and height of the area given to getTrueCoordinatesInArea is equal to x and y as its the area is created from 0,0 to x,y
If that makes sense..
So for example:
value = coordinateContainsTrue( x, y );//return true or false.
total = getTrueCoordinatesInArea( x , y );//Returns the total true values inside the area.
Edit: This would work off a seed.
I don't understand exacly what you need but I thought it sounded like a good and fun exercise. I hoped it's what you wanted. =) It's not coded exactly how I wanted. Would rather have used a bool[,] array but don't know how to make that one dynamic and didn't want to code my own class for this, but maybe I should have.
However, this solution should work.
private List<List<bool>> grid = new List<List<bool>>();
private int N = 4;
Random randomNumberGenerator = new Random();
private bool getRandomBoolean()
{
return this.randomNumberGenerator.Next(0, 2) == 1;
}
private void testProgram()
{
var containsTrue = coordinateContainsTrue(0, 10);
var total = getTrueCoordinatesInArea(14, 2);
var isTrue = coordinateIsTrue(15, 11);
}
private bool coordinateIsTrue(int x, int y)
{
expandGridOfNeeded(x, y);
return grid[x][y];
}
private bool coordinateContainsTrue(int x, int y)
{
expandGridOfNeeded(x, y);
for (int xTemp = 0; xTemp < x; xTemp++) // Loop columns
{
for (int yTemp = 0; yTemp < y; yTemp++) // Loop rows
{
if (grid[xTemp][yTemp])
return true; // Return true if any true was found
}
}
return false;
}
private int getTrueCoordinatesInArea(int x, int y)
{
expandGridOfNeeded(x, y);
var total = 0;
for (int xTemp = 0; xTemp < x; xTemp++) // Loop columns
{
for (int yTemp = 0; yTemp < y; yTemp++) // Loop rows
{
if (grid[xTemp][yTemp])
total++; // Increase count if true was found
}
}
return total;
}
private void expandGridOfNeeded(int x, int y)
{
if (x < 0 || y < 0)
return;
// Add needed columns
while (grid.Count <= x)
{
var column = new List<bool>();
// Only add rows if the others have rows
if (grid.Count > 0)
{
while (column.Count < grid[0].Count)
{
// Check if legal to add a true value, if it is then add random else add false
bool forceFalseValue = false;
for (int i = grid.Count - 1; i > grid.Count + N && forceFalseValue == false; i--)
{
forceFalseValue = grid[i][column.Count - 1];
}
column.Add(forceFalseValue ? false : getRandomBoolean());
}
}
grid.Add(column);
}
// Add needed rows
while (grid[0].Count <= y)
{
var counter = N;
foreach (var column in grid)
{
// Check if legal to add a true value, if it is then add random else add false
if (counter < N)
{
column.Add(false);
counter++;
}
else
{
var randomValue = getRandomBoolean();
if (randomValue)
counter = 0;
else
counter++;
column.Add(randomValue);
}
}
}
}

Categories

Resources