Trying to replace the two spaces after the matched pattern in c# - c#

I am currently making a text based game. I am drawing a map using ASCII. I want to place an "#" sign in the room where the player is located. the four square boxes are the rooms. Here is the code:
string map = #"
+--------+
| |
|| ||
| |
+---||---+
||
+-||-+
|| ||
+-||-+
||
+-||-+
|| ||
+-||-+
||
+-||-+
|| ||
+- -+";
//this doesn't work lol
map = map.Replace("||","#");
It is for an assignment.

To answer your direct question, assuming that there is a part of your map string that has two spaces after two vertical bars and you want to replace the second space with an # symbol, you could do this:
map.Replace("|| ", "|| #");
Which of course would replace every instance of the search string, scattering # symbols throughout your map, and I strongly doubt that you want this to happen.
In fact I don't think it's a good idea to change the map string at all. Instead you would be better served by keeping the map data separate from the player position data and handling the output differently.
For example, if you are allowed to use the Console object's positioning commands you can do something like this:
int playerX;
int playerY;
string map;
public void Draw()
{
Console.Clear();
Console.Write(map);
// save cursor position
int l = Console.CursorLeft;
int t = Console.CursorTop;
// display player marker
Console.SetCursorPosition(playerX, playerY);
Console.Write("#");
// restore cursor position
Console.SetCursorPosition(l, t);
}
You can use cursor positioning to do all sorts of fun things, just like we used to in the good old days of ANSI art. Ah, nostalgia.
If you can't use - or for some reason can't rely on - cursor positioning you will need to get a bit more creative. One method is to break the map down into lines and figure out which one needs to have the player mark added right before you do the output:
public void Draw()
{
string[] lines = map.Replace("\r", "").Split('\n');
for(int y = 0; y < lines.Length; y++)
{
string curr = lines[y];
if (y == playerY)
curr = curr.Substring(0, playerX) + "#" + curr.Substring(playerX + 1);
Console.WriteLine(curr);
}
}
Of course this will blow up as soon as the player movement goes outside of the area covered by the map string, or hits the right-most character of the line.
Another option would be to create an array of map cells with information in each cell about what is there. The map string is used as input for generating the map array, which is used for all operations after that. The draw loop for that would then test against the player position to determine whether it will draw the player's marker or whatever character the map cell is represented by. You can also use this array for testing whether a move is valid (empty map cell), adding things like cell content (treasure!), etc.
The code for which is well outside the scope of this answer.

Related

How to write in multiple positions in a console application at the same time? C#

I want lines as many as the width of the console to simultaneously write downwards one char to the height of the console. I've done most of it, but it goes from top to bottom to right etc...
If you need help picturing what I mean, think of the matrix code rain.
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < w)
{
int j = 0;
while (j < h)
{
Thread.Sleep(1);
Console.SetCursorPosition(i, j);
Console.Write(".");
j++;
}
i++;
}
What I would do is construct a List<string> lines; that would contain the lines you want to write to the console window, where each line is as wide as the console width. Then just print the list out to the console window in reverse order, so the first line (at lines[0]) will always be the last one printed, and will always be at the bottom of the console window.
Sample Implementation -- someone mentioned this might be homework. I did not think so, but if it is, then please try your own implementation of the above idea first.
We can add new items to the list in the same loop that we use to print out its items. Before we add a line, however, we first check to see if there are already as many lines in the list as there are in the console window (Console.WindowHeight). If there are, then we just remove the line at lines[0] before we add a new one. In this way, the List<string> lines is "scrolling" along with the console window.
The scrolling speed is controlled by a Thread.Sleep, but this code could easily be added to a Timer instead, so that other work could happen in the background (like if this was intended to be a "screensaver", and you wanted to wait for user input to "wake up"). But no matter how we decide to implement the speed, I decided to create an enum with values that represent the number of milliseconds a Thread.Sleep implementation would use:
class Program
{
enum MatrixCodeSpeed
{
Fastest = 0,
Faster = 33,
Fast = 67,
Normal = 100,
Slow = 333,
Slower = 667,
Slowest = 1000
}
I would also create a helper method that creates a "random" line for you. It could take in an integer that specifies the "density", which means how many characters you'd want in the line. density represents a percentage, so if 10 is specified, then we pick a random number between 0 and 99, and if it's less than 10 then we add a random matrix character to the string (otherwise we add a space character).
Also, in order to replicate the matrix a little closer, I've also chosen 4 different characters to print, each one slightly darker than the previous. This adds to the three dimensional effect, where the faded blocks look further away than the solid ones:
private static Random rnd = new Random();
// Add whatever 'matrix' characters you want to this array. If you prefer to have one
// character chosen more often than the others, you can write code to favor a specific
// index, or just add more instances of that character to the array below:
private static char[] matrixChars = new[] { '░', '▒', '▓', '█' };
static string GetMatrixLine(int density)
{
var line = new StringBuilder();
for (int i = 0; i < Console.WindowWidth; i++)
{
// Choose a random number from 0-99 and see if it's greater than density
line.Append(rnd.Next(100) > density
? ' ' // If it is, add a space to reduce line density
: matrixChars[rnd.Next(matrixChars.Length)]); // Pick a random character
}
return line.ToString();
}
Next, we have the main method, which populates a list with random lines (using a density of 10%), then prints them out one at a time, in reverse order, in an endless loop (removing the first line if we need to):
static void Main()
{
var lines = new List<string>();
var density = 10; // (10% of each line will be a matrix character)
var speed = MatrixCodeSpeed.Normal;
// Hide the cursor - set this to 'true' again before accepting user input
Console.CursorVisible = false;
Console.ForegroundColor = ConsoleColor.DarkGreen;
while (true)
{
// Once the lines count is greater than the window height,
// remove the first item, so that the list "scrolls" also
if (lines.Count >= Console.WindowHeight)
{
lines.Remove(lines[0]);
}
// Add a new random line to the list, which will be the new topmost line.
lines.Add(GetMatrixLine(density));
Console.SetCursorPosition(0, 0);
// Print the lines out to the console in reverse order so the
// first line is always last, or on the bottom of the window
for (int i = lines.Count - 1; i >= 0; i--)
{
Console.Write(lines[i]);
}
Thread.Sleep(TimeSpan.FromMilliseconds((int)speed));
}
}
}
Here's a gif of it in action, up to the point where the screen is full (then the gif repeats, but the code version continues to scroll normally):
The task smells like an assignment, so I'm guiding you instead feeding the implementation. It is not ethical to feed you with an answer if it is a homework.
You are looking for a better fit of algorithm. The stated algorithm fill the console from top to bottom, as it iterate to fill through the Y-axis first (the nested loop) and followed by the X-axis (the outer loop).
What is needed is to iterate x-axis and y-axis alternatively so that it looks like it fills from the top left corner to the bottom right corner.
// 1 step to (0,0)
*
// 3 steps to (1,1)
**
**
// 5 steps for reaching (2,2)
***
***
***
// 7 steps for reaching (3,3)
****
****
****
// 9 steps for reaching (4,4) and 11 steps for (5,5)...
// I do think everyone could get this pattern
This draft would also be the final outcome of what it looks like.
Instead of filling them all at the same time, what you need is actually get the thread sleep after it reach the next square point.
(Computers are so fast that it probably do all its work to feed your screen within a second and the black console window is gone without any notice.)
At the time you posted the question, I'm also solving it from the very beginning. I thought of filling X and Y axis alternatively is the solution, but stopping at each time that the square expands is far more important to get the effect.
It is not a threading problem tag either at my point of view.
Let's sum up the above pattern:
Assume i and j are x and y coordinates respectively.
Each iteration takes you from (i, j) and n*2+1 steps to reach
(i+1,j+1)
Note that we are zero-based in this example.
We are about to construct the loop:
The n*2+1 step number is useful. It means you need to fill x-axis for
n times and y-axis for n times, and finally get the diagonal grid
(n+1,n+1) done.
In each inner loop, we first render the X frontier along y-axis and
then render the Y frontier along x-axis.
Let say the cycle start with the checkpoint (n,n), where n=3, and we
slept for a while, so we are in n=4 now.
To achieve this, we'd better first navigate to (n+1,0) then fill up
to (n+1,n)
Afterwards we navigate to (0,n+1) and fill to (n+1,n+1)
Then we are in m=n+1 now (sounds like a mathematical proving :(
The loop would be
//calculate how many checkpoints (n)
int checkpoints = 1080;
//n should indicate the actual turn we are instead of naming the total turns like sucks
//The main, the outermost For-loop
for (int n=0;n<checkpoints;n++)
{
// The nested step
for (int y=0;y<n;y++)
{
// Just fill in (n+1, y) grid
Console.SetCursorPosition(n+1, y);
Console.Write(".");
}
for (int x=0;x<n+1;x++)
{
// Just fill in (x, n+1) grid
Console.SetCursorPosition(x, n+1);
Console.Write(".");
}
// Upon completion of each main cycle we have a sleep, yah
Thread.Sleep(100);
}
Well, I expect the program to crash when the console size is smaller than 1080x1080.
This algorithm could only get you a square to fill, and a typical monitor with resolution 1920x1080 just fails as it is 16:9. This is intentional, if you're doing homework you need to configure it before shipping it to your teacher. (I've got no chance to do an assignment as I self learned programming :(
(The site continuously urging me to format my code, this has been half an hour and I just didn't do things wrong. So I decided to post it bit by bit to debug that. Finally I've got the job done...)
If you just want to write one line at a time you can use this:
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < h)
{
Console.WriteLine(new string('.', w-1));
Thread.Sleep(20);
i++;
}
Just a bit of modification allow the code to simulate the matrix code rain.
int w = Console.WindowWidth;
int h = Console.WindowHeight;
int i = 0;
while (i < h)
{
int j = 0;
string s = "";
Thread.Sleep(10);
while (j < w)
{
Console.SetCursorPosition(j, i);
s += ".";
j++;
}
Console.Write(s);
i++;
}
basically what i did here is just some restructuring of the logic and putting in the proper delays at the right position. Hope it helps.

How to make small changes for console output without repeating all unchanged values

I am trying to create a text game in C# with console interface
The basic process goes like this:
Take user input.
Manipulate the map (2d array) based on the user input.
Print out the map.
Repeat.
The game works fine, but my problem is that it flickers whenever you try to move the character because it has to go through an entire nested for loop to print out the map each time.
Can I change still different parts of the console output to avoid flickers?
My current actual code for display map at every step:
Console.Clear();
for (int y = 0; y < 15; y++)
{
for (int x = 0; x < 58; x++)
{
// map is an array with current state for each cell on the map
Console.Write(map[y, x]);
}
Console.WriteLine();
}
You should not reprint all the map for each cycle. The better way is to use Console.SetCursorPosition method and rewrite just modified symbols:
foreach(var changedSymbol in changes)
{
Console.SetCursorPosition(changedSymbol.Row, changedSymbol.Column)
Console.Write(changedSymbol.Value);
}

Programmatically check textboxes for completeness

I am looking for a way to figure out if textboxes are filled in in a specific way.
I have the following textboxes:
X1 Y1 Z1
X2 Y2 Z2
X3 Y3 Z3
Users are expected to input into them continuously. For example, if only X1,Y1 have texts, it's valid. While if X1,Z1 have texts while Y1 hasn't, it's invalid.
The reason for this is because:
string G1
if(!string.IsNullOrWhiteSpace(X1.Text) && string.IsNullOrWhiteSpace(Y1.Text))
{
G1 = "<" + X1.Text + ">";
}
else if(!string.IsNullOrWhiteSpace(X1.Text) && !string.IsNullOrWhiteSpace(Y1.Text))
{
G1 = "<" + X1.Text + ">, ";
}
If they skip around then what is printed in the end will not be what is expected.
If you can think of an easier way to do all of this, please share. I am sure that my way of attacking this problem is quite simplistic and inefficient.
The answer I found is to use an array of the text boxes, then to iterate over that to determine the text of the filled out boxes. Then add the text from those boxes to a list.
Finally I used joined all of the items of that list, in a way that made the final output correct.
Code I used in the end:
string[] cells = new string[] { X1.Text, Y1.Text, Z1.Text, X2.Text, Y2.Text, Z2.Text, X3.Text, Y3.Text, Z3.Text };
List<string> final_cells = new List<string>();
//Process array to determine which cells are full, adds full cells to list
for (int i = 0; i < cells.Length; i++)
{
if(cells[i].Length == 0)
{
//If cell is empty, continue to the next one
continue;
}
else
{
// If cell is full add its contents to the final_cells list
final_cells.Add(cells[i]);
}
}
//Join the list to one string
string content = string.Join(">, <", final_cells);
Also I am sorry that I did not better explain the original situation.
The purpose of the final application is to output text in a specific format for a minecraft plugin to read. The 3x3 of text boxes is meant to mimic the crafting grid from the game.
The type of recipe this part of the application is supposed to add does not need to use 9 items/blocks, and is not shaped (so it doesn't technically matter where the user inputs each item name). Because of this, the empty boxes have to be completely ignored, and the program needs to know if there is something coming next, so I could not simply say that the recipe ended at the first empty box.
An output of <item1> <item2> is not valid, the correct format is <item1>, <item2>. However the input can also be a single item... so this <only_item> is a valid format.
I hope it is clear both what the function of this is, but also why this was important for my application.

System of the Unicode Box Drawing table

I'm implementing a function in C# where providing from which side goes what kind of line, it will return one character from the Box Drawing table (0x2500-0x257F) from Unicode. However I've failed (yet) to find a system in the position of these characters in the table, that would make a significantly simpler function, then assigning all possible input to an output in one enormous if-then-else block.
I've noted that there are 9 different line styles (thin, double, thick, double-dashed, triple-dashed, quad-triple-dashed, thick double-dashed, ...) in that table, and with the four direction, with the "no line" information makes 10 different states, which would make up to 9999 different combination not including the "none of the side has a line" case, which in my case would be a space character.
The easiest way I've found to implement this, is to make one freakin' huge array containing all 10000 possible outcome, (where the first digit notes North, the second East, then South and West) but I believe that this is actually the second worst case scenario I've found, and there is a much more elegant solution. (BTW This would be hilarious if you're not planning on implement it this way. That is how I feel about this anyways.)
This question is probably not suitable here, but considering the size of this task, I even take that risk:
Is there a system how the Box Drawing table arranges the characters, and/or is there a simpler algorithm that does the exact same I would like to do?
The simplest/shortes solution I see, needs an array/list of 128 elements.
You declare a struct/class like this:
// I use consts instead of enum to shorten the code below
const int thin = 1;
const int double = 2;
const int thick = 3;
... // other line styles
struct BoxDrawingChar{
int UpLine, DownLine, LeftLine, RightLine;
BoxDrawingChar(int UpLine, int DownLine, int LeftLine, int RightLine)
{ ... }
};
Then you describe appearance of each character:
BoxDrawingChar[] BoxDrawingCharList =
{
new BoxDrawingChar(0, 0, thin, thin), // 0x2500
new BoxDrawingChar(0, 0, thick, thick), // 0x2501
...
new BoxDrawingChar(...), // 0x257F
}
Then your function will be quite simple:
int GetCharCode(int UpLine, int DownLine, int LeftLine, int RightLine)
{
for(int i = 0; i < BoxDrawingCharList.Length; ++i){
BoxDrawingChar ch = BoxDrawingCharList[i];
if (ch.UpLine == UpLine && ch.DownLine == DownLine && ...)
return i + 0x2500;
}
return 0;
}
Of course you can add diagonal lines, rounded angles etc and refactor the code in many ways. I gave only a general idea.

How do i get a character in a given coordinate in the C# console?

I'm trying to make a roguelike in C#, and i got to make a little map, and a loop that checks if w/s/a/d is pressed to move the player; but i have a problem detecting walls; let's say i want to know if there is a wall to the right before moving there, i get the player position, i check what is on the right of that position, and if it's a '#', i don't let the player move because it's supposed to be a wall.
But here's the problem, in the console, how do i check if the coordinate, for instance "(15,2)" contains a '#' char?
Is there an easier way to check if a given coordinate contains that character?
And how? Because i tried, but i can't GET the char in a certain coord of the console.
Something like:
static bool wallcheck_x(int xpos) {
xpos++;
//Now, it should GET the char allocated in xpos++;
if (/*char that's in xpos++ */ == '#')
{
return true; //it's a wall
}
return false; //it's not a wall
}
You shouldn't be doing it that way. You should have something that maps to what is displayed in the console, I assume that's how you even see the map to begin with. When a player moves, you should check it based on your map, not what is displayed in the console.
So for example...
how do i check if the coordinate, for instance "(15,2)" contains a '#' char?
Don't check what's in the console at (15,2), but check your map that displays what's in the console for a # instead. It's much easier that way.
But, let's say i did the map in a multidimensional array... then how do i print the array in the console?
Use Google, man. Here's what I pulled from this question:
int rowLength = arr.GetLength(0);
int colLength = arr.GetLength(1);
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Console.Write(string.Format("{0} ", arr[i, j]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
What this does is traverses the array by row, printing each character in the row. When it reaches the end of a row, it prints a new line and begins printing the new row. Your array would probably be a 2-dimensional character array which represents the map. Likewise, you can keep track of a player's position with something like:
int playerXPos;
int playerYPos;
You would need to update those as your character moves. So, credit to gleng for this snippet, you can check if the player has hit a wall:
if (arr[playerXPos, playerYPos] == '#')
{
// player has collided with a wall
}
else
{
// player has NOT collided with a wall
}
Though it would be more scalable to have an actual Player data structure, this seems like it would suit you just fine.
Without having access to any of your code (you should really post it for help like this), i'm assuming you would do something like:
if (map[player.X, player.Y] == '#')
{
// player has collided with a wall
}
else
{
// player has NOT collided with a wall
}
This code assumes that map is a multidimensional array that contains your map.

Categories