I have been trying to do a task I recieved a few days earlier. Basically the task is a console application in C# :
Prompt the user for input of 2 coordinates in untill the word "stop" is entered. Once the word "stop" is hit, print a "*"(star char) at each of the input coordinates. The field where the coordinates are printed is 20x20. I have tried doing this, but to no avail. If somebody could help me out and show me how to store the input x,y into a 2d array, that'd be great :)
How the application should work : http://imgur.com/a/SnC1k
The [0,5] [18,18]etc are the entered coordinates which are later on printed down below. The "#" chars dont need to be printed , they are here only to help with the understanding of the task.
How I tried to do it but DIDN'T work :
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
bool stopped = false;
int x=0;
int y=0;
while (stopped)
{
string[,] coordinates = Console.ReadLine();
string response = Console.ReadLine();
response = response.ToLower();
if (response == "STOP")
stopped = true;
else
{
string[] xy = coordinates.Split(',');
x = int.Parse(xy[0]);
y = int.Parse(xy[1]);
Console.SetCursorPosition(x, y);
Console.Write("*");
}
}
}
}
}
The code I did just doesn't do it. It shows multiple errors that I do not know how to fix and the only thing I was able to do is get it to print a char immediately when I enter the first coordinates, instead of printing a char at every entered coordinate, AFTER the word STOP is hit.
Create a 20x20 2d array. Prompt the user for the x and y. Once you have each store a 1 in your array[x,y] once the user hits stop loop through the array and print '#' if null or 0 and print '*' if its a 1.
Edit, something along these lines I didn't check if this works or compiles but should get you on the right track.
int[,] grid = new int[20,20];
while (!stopped)
{
string[,] coordinates = Console.ReadLine();
string response = Console.ReadLine();
response = response.ToUpper();
if (response == "STOP")
stopped = true;
else
{
string[] xy = coordinates.Split(',');
x = int.Parse(xy[0]);
y = int.Parse(xy[1]);
grid[x,y] = 1;
}
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
if (grid[i, j] > 0)
Console.Write("*");
else
Console.Write("#");
}
Console.WriteLine("");
}
}
As you only need to display a matrix-style output you don't need to use Console.SetCursorPosition(x, y);
Also you should read the user input somehow and set the proper value for the given position instead of store the coordinates.
Try this and let me know how this works for you. You can see it also on this fiddle. Enter the coordinates as two space-separated numbers and enter stop to print.
using System;
public class Program
{
public static void Main(string[] args)
{
int x=0;
int y=0;
char[,] coordinates = new char[20,20];
while (true)
{
//user must enter 2 3 for example.
string[] response = Console.ReadLine().Split(new[]{" "}, StringSplitOptions.RemoveEmptyEntries);
if (response[0].ToLower() == "stop")
break;
x = int.Parse(response[0]);
y = int.Parse(response[1]);
coordinates[x,y] = '*';
}
//Print the output
for(var i = 0; i < 20; i++)
{
for( var j = 0; j < 20; j++)
if (coordinates[i,j] == (char)0)
Console.Write('#');
else
Console.Write(coordinates[i,j]);
Console.WriteLine();
}
}
}
Hope this helps!
I suggest decomposing the task, cramming entire rountine into a single Main as bad practice; you should:
- ask user to enter coordinates
- print out the map
Let's extract the methods:
private static List<Tuple<int, int>> s_Points = new List<Tuple<int, int>>();
private static void UserInput() {
while (true) {
string input = Console.ReadLine().Trim(); // be nice, let " stop " be accepted
if (string.Equals(input, "stop", StringComparison.OrdinalIgnoreCase))
return;
// let be nice to user: allow he/she to enter a point as 1,2 or 3 4 or 5 ; 7 etc.
string[] xy = input.Split(new char[] { ',', ' ', ';', '\t' },
StringSplitOptions.RemoveEmptyEntries);
int x = 0, y = 0;
if (xy.Length == 2 && int.TryParse(xy[0], out x) && int.TryParse(xy[1], out y))
s_Points.Add(new Tuple<int, int>(x, y));
else
Console.WriteLine($"{input} is not a valid 2D point.");
}
}
Printing out
private static void PrintMap(int size = 20) {
// initial empty map; I prefer using Linq for that,
// you can well rewrite it with good old for loops
char[][] map = Enumerable.Range(0, size)
.Select(i => Enumerable.Range(0, size)
.Select(j => '#')
.ToArray())
.ToArray();
// fill map with points;
// please, notice that we must not print points like (-1;3) or (4;100)
foreach (var point in s_Points)
if (point.Item1 >= 0 && point.Item1 < map.Length &&
point.Item2 >= 0 && point.Item2 < map[point.Item1].Length)
map[point.Item1][point.Item2] = '*';
// The string we want to output;
// once again, I prefer Linq solution, but for loop are nice as well
string report = string.Join(Environment.NewLine, map
.Select(line => string.Concat(line)));
Console.Write(report);
}
Finally, all you have to do it to call the methods:
static void Main(string[] args) {
UserInput();
PrintMap();
Console.ReadKey();
}
Related
I am trying to write a code in C# that counts how many numbers are there in a sentence. So if the number is made up of more than a digit it should be counted as one number.
For example: 2021 is one number not 4 numbers
This problem is caused by the method 'Char.IsDigit'
I wrote a code but the only problem in my algorithms is that if a word starts with a number it will be counted as a number.
For example: 1big will be counted as a number, but it shouldn't.
So how can I solve this problem?
My code might be a trivial code, so if there are better solutions I would be happy if you show me.
using System;
namespace Textanalyse
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("I count how many numbers are there in a text.");
string text = "Hallo to the 1 that broke all my 12345 bones in my 2 legs, 2 hands and 20 fingers without touching my skull that has an IQ100 brain but 1big bone";
Console.WriteLine($"There are {countTheNumbers(text)} in the sentence above");
Console.ReadKey();
}
public static int countTheNumbers(string s)
{
int sum = 0;
string[] everyWord = s.Split(" ");
bool x;
for (int i = 0; i < everyWord.Length; i++)
{
Console.WriteLine($"The {i + 1}. String is \"{everyWord[i]}\" and it contains ({everyWord[i].Length}) digits.");
for (int j = 0; j < everyWord[i].Length; j++)
{
x = char.IsDigit(everyWord[i], j);
Console.WriteLine(x);
if (x == false)
break;
else
{
sum = sum + 1;
Console.WriteLine($"\"{everyWord[i]}\" is a number");
break;
}
}
}
return sum;
}
}
}
This is a working solution for you case with comments explaining what each line does so you can understand and learn. there are many more that you can do to it to make it better and fool proof but for your current test case it's enough
string text = "Hallo to the 1 that broke all my 12345 bones in my 2 legs, 2 hands and 20 fingers without touching my skull that has an IQ100 brain but 1big bone";
// split the text by spaces so we end up with a collection of words
int count = text.Split(new[] { ' ' })
// test all words in the collection
.Where(word =>
// check if all element of the word matches a condition
// a string in composed of char so it will iterate on each char
word.All(letter =>
// return true if the character is a digit
char.IsDigit(letter)))
// return the count of all words we just filtered and kept if they were all made of digits
.Count();
Well, if we define "number" as sequence of digits '0'..'9' with word borders we can use regular expressions, e.g. having
string text =
"Hallo to the 1 that broke all my 12345 bones in my 2 legs, 2 hands and 20 fingers without touching my skull that has an IQ100 brain but 1big bone";
We can put
using System.Text.RegularExpressions;
...
int count = Regex.Matches(text, #"\b[0-9]+\b").Count;
Here
\b - word border
[0-9]+ - one or more digits in '0'..'9' range
\b - word border
Let's have a look at these numbers:
var result = Regex
.Matches(text, #"\b[0-9]+\b")
.Cast<Match>()
.Select(m => m.Value);
string report = string.Join(Environment.NewLine, result);
Console.Write(report);
Outcome:
1
12345
2
2
20
So thank u everyone for everything I really learned a lot from you
I found another idea that would work with my prof. thanks
using System;
namespace Textanalyse
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("I count how many numbers are there in a string.\nPlease enter a text: ");
string satz = Console.ReadLine();
Console.WriteLine($"There are {ZaehleZahlen(satz)} numbers in this sentence! ");
Console.ReadKey();
}
public static int ZaehleZahlen(string s)
{
int sum = 0;
string[] jedesWort = s.Split(" ");
for (int i = 0; i < jedesWort.Length; i++)
{
for (int j = 0; j < jedesWort[i].Length; j++)
{
bool x;
x = char.IsDigit(jedesWort[i], j);
if (x == false)
break;
else if (x == true)
{
if (j != jedesWort[i].Length-1) continue;
else
{
sum = sum + 1;
Console.WriteLine($"\"{jedesWort[i]}\" is a number");
}
}
}
}
return sum;
}
I am trying to write a small program to calculate the addition of two vectors from the user and storing it in the array.
I want to get two X and Y's (like this {x,y})from the user and then add them both together.
I tried to use a 2D array like so
int[,] array = new int[0, 1] {};
but I want the user to enter the values of it.
I don't know enough about c# so if anyone knows how can I solve this problem would apparitions your help
If you want to get a vector from user, you can try asking user to provide its components separated by some delimiter(s), e.g.
private static int[] ReadVector(string title) {
while (true) { // keep asking user until valid input is provided
if (!string.IsNullOrEmpty(title))
Console.WriteLine(title);
string[] items = Console
.ReadLine()
.Split(new char[] { ' ', '\t', ';', ',' },
StringSplitOptions.RemoveEmptyEntries);
if (items.Length <= 0) {
Console.WriteLine("You should provide at least one component");
continue;
}
bool failed = false;
int[] result = new int[items.Length];
for (int i = 0; i < items.Length; ++i) {
if (int.TryParse(items[i], out int value))
result[i] = value;
else {
Console.WriteLine($"Syntax error in {i + 1} term");
failed = true;
break;
}
}
if (!failed)
return result;
}
}
Then you can use this routine like this:
// We don't want any 2D matrices here, just 2 vectors to sum
int[] A = ReadVector("Please, enter vector A");
int[] B = ReadVector("Please, enter vector B");
if (A.Length != B.Length)
Console.WriteLine("Vectors A and B have diffrent size");
else {
// A pinch of Linq to compute C = A + B
int[] C = A.Zip(B, (a, b) => a + b).ToArray();
Console.WriteLine($"[{string.Join(", ", A)}] + ");
Console.WriteLine($"[{string.Join(", ", B)}] = ");
Console.WriteLine($"[{string.Join(", ", C)}]");
}
Edit: Sure you can sum vectors with a help of good old for loop instead of Linq:
int[] C = new int[A.Length];
for (int i = 0; i < A.Length; ++i)
C[i] = A[i] + B[i];
I am making a tic tac toe game and I am making it to be unbeatable
but first I have to let the computer know the rules.
I'm stuck in a step that is => when it's the computer's turn and we have just started the game so no win case so it's up to the computer to generate a random number that will be the computer's choice ( the block where he mark X or O )
so I need it to generate a number from 1 to 9 but by excluding the already used blocks ( numbers ).
I tried doing that by making a list and adding a number every time the human player used a block but I can't find a way to use those numbers from the list as exclusion for the random choice of the computer.
Here is what I tried and thnx in advance:
//random
List<int> cas = new List<int>();
if (c1 == true)
{
cas.Add(1);
}
if (c2 == true)
{
cas.Add(2);
}
if (c3 == true)
{
cas.Add(3);
}
if (c4 == true)
{
cas.Add(4);
}
if (c5 == true)
{
cas.Add(5);
}
if (c6 == true)
{
cas.Add(6);
}
if (c7 == true)
{
cas.Add(7);
}
if (c8 == true)
{
cas.Add(8);
}
if (c9 == true)
{
cas.Add(9);
}
for (int i = 0; i < cas.Count; i++)
{
random_except_list(cas[]);
}
public static int random_except_list(int[] x)
{
Random r = new Random();
int result = r.Next(1, 9 - );
for (int i = 0; i < x.Length; i++)
{
if (result < x[i])
return result;
result++;
}
return result;
}
Lets have possible places to use:
List<int> possible = Enumerable.Range(1,9).ToList(); // create a list and add 1-9
and used places:
List<int> used = new List<int>();
Random rnd = new Random();
Now everytime we generate a random number in the range of possible list count as index and remove it from there and move it to used:
int index = rnd.Next(0, possible.Count);
used.Add(possible[index]);
possible.RemoveAt(index);
for user its just enough to check if it exists in the used so the acceptable number should be:
!used.Any(x=> x== NumberUserHaveChosen)
So the first time the random number can be 0-8 (as possible.Count==9) and take from it at random index.
the second time the random number can be 0-7 (as possible.Count==8) and take from it at random index.
and so on... while the possible.Count != 0
in this case there is no need to generate random numbers several times that finally it won't exist in our used List.
Several years ago I was working on a Sudoku algorithm, and what I was trying to achieve was to generate a valid solved sudoku table in minimum time possible, i get to the conclusion that I should replace the algorithm that each time I generate a number I have to check some lists to make sure the number was not generated before, as count of numbers were increasing these comparisons would become more and more. for example when only the number 4 is remaining, I should generate random numbers till I get 4. so I used this approach and the result was amazing.
I think you should do something like this:
public static int random_except_list(List<int> x)
{
Random r = new Random();
int result = 0;
while (true)
{
result = r.Next(1, 10);
if (!x.Contains(result))
return result;
}
}
Just trying to use what you have written (more or less), but changing the method to take a List<int> which is what you are building, I would write the method using LINQ like this (except I would create a static Random variable and keep it between calls):
public static int random_except_list(List<int> x) => Enumerable.Range(1, 9).Where(n => !x.Contains(n)).ToList()[new Random().Next(0, 9 - x.Count)];
However, you can implement the same idea in a more explicit way using procedural code:
public static int random_except_list_explicit(List<int> x) {
// First, generate a list of possible answers by skipping the except positions in x
var possibles = new List<int>();
for (int i = 1; i <= 9; i++)
if (!x.Contains(i))
possibles.Add(i);
// now pick a random member of the possible answers and return it
return possibles[new Random().Next(0, possibles.Count)];
}
I believe it is better to work with positions left. So user or computer select from all open positions:
using System;
using System.Collections.Generic;
class app
{
public static int random_except_list(List<int> openPositions)
{
Random r = new Random();
int index = r.Next(openPositions.Count - 1);
int result = openPositions[index];
openPositions.RemoveAt(index);
return result;
}
static void Main()
{
List<int> openPositions = new List<int>();
for (int i = 1; i < 10; i++)
{
openPositions.Add(i);
}
bool turn = false;
while (openPositions.Count > 0)
{
foreach (int value in openPositions)
{
Console.Write(value + " ");
}
Console.WriteLine();
if (!turn)
{
while (true)
{
Console.WriteLine("Choose your Position");
ConsoleKeyInfo key = Console.ReadKey();
int num = (int)key.KeyChar - 48;
if (openPositions.Contains(num))
{
openPositions.Remove(num);
Console.WriteLine();
break;
}
else Console.Write(" is not Valid: ");
}
}
else
{
int compPos = random_except_list(openPositions);
Console.WriteLine("Computer choose: " + compPos);
}
turn = !turn;
}
Console.WriteLine("No positions left");
Console.ReadKey();
}
}
I am trying to get input from user 5 times and add those values to marks array;
Then, it will calculate the average and print positive or negative accordingly. However, I can not take input from the user it just prints "Enter 5 elements". After getting input from user how can I add them to marks array? Any tips would be helpful.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
double average =0;
int [] marks = new int[] { };
for (int a = 0; a < 5; a++){
Console.WriteLine("Enter 5 elements:");
string line = Console.ReadLine();
Console.WriteLine(line);
}
for (int i = 0; i < marks.Length; i++){
average = marks.Average();
}
if(average>0){
Console.WriteLine("Positive");
}else{
Console.WriteLine("Negative");
}
}
}
I would use a while loop combined with int.TryParse to check if the user input is a number. Also it doesn't make any sense to put average = marks.Average(); inside a for loop, because LINQ Average calculates the average of a collection (in your case the marks array).
static void Main()
{
int[] marks = new int[5];
int a = 0;
Console.WriteLine("Enter 5 elements:");
while (a < 5)
{
if (int.TryParse(Console.ReadLine(), out marks[a]))
a++;
else
Console.WriteLine("You didn't enter a number! Please enter again!");
}
double average = marks.Average();
if (average > 0)
Console.WriteLine("Positive");
else
Console.WriteLine("Negative");
}
DEMO HERE
Edited my answer to illustrate solving your problem without a for loop.
class Program
{
const int numberOfMarks = 5;
static void Main()
{
List<int> marks = new List<int>();
Enumerable.Range(1, numberOfMarks)
.ForEach((i) => {
Console.Write($"Enter element {i}:");
marks.Add(int.TryParse(Console.ReadLine(), out var valueRead) ? valueRead : 0);
Console.WriteLine($" {valueRead}");
});
Console.WriteLine(marks.Average() >= 0 ? "Positive" : "Negative");
}
}
This will help you, just copy and paste it.
There are some explanation with comments.
class Program
{
static void Main()
{
const int numberOfMarks = 5;
int[] marks = new int[numberOfMarks];
Console.WriteLine("Enter 5 elements:");
for (int a = 0; a < numberOfMarks; a++)
{
// If entered character not a number, give a chance to try again till number not entered
while(!int.TryParse(Console.ReadLine(), out marks[a]))
{
Console.WriteLine("Entered not a character");
}
Console.WriteLine("You entered : " + marks[a]);
}
// Have to call Average only once.
var avg = marks.Average();
Console.WriteLine(avg > 0 ? "Positive average" : "Negative average");
Console.ReadLine();
}
}
Follow Stackoverflow Answer
since integer array is being used, and as input from the console is a string value, you need to convert it using Parse() Method. For e.g.
string words = "83";
int number = int.Parse(words);
Edit: using string variable in parsing.
I want to print the string in reverse format in for loop:
Input: I'm Learning c#
Output: c# Learning I'm
No Split functions and reverse functions should be used, it has to do only with forloop.
for (int i = m.Length - 1; i >= 0; i--)
{
b[j]=a[i];
j++;
if(a[i]==' '|| a[i]==0)
{
for (int x = b.Length - 1; x >= 0; x--)
{
c[k] = b[x];
Console.Write(c[k]);
k++;
}
}
} Console.ReadKey();
You have to create an array of the words in the sentence:
var words = input.Split(' ');
Then you just loop through the above array from the end to the start:
for(int i=words.Length-1; i>=0; i--)
{
Console.Write(words[i]+" ");
}
With LINQ and string methods you can simplify it:
var reversedWords = input.Split().Reverse(); // Split without parameters will use space, tab and new-line characters as delimiter
string output = string.Join(" ", reversedWords); // build reversed words, space is delimiter
Use Stack<Queue<char>>
Hey if you want to show off your knowledge of data structures, use a queue and a stack! This makes for a very concise answer as well.
You want the sentence to be LIFO with respect to words but FIFO with respect to letters within words, so you need a stack (which are LIFO) of queues (which are FIFO). You can take advantage of the fact that a string, a queue<char>, and a stack<char> all expose IEnumerable<char> as well, so it's easy to convert back and forth; once you have all the characters ordered in your data structure, you can extract the whole thing as a character array using SelectMany(), which you can pass to a string constructor for the final answer.
This solution uses no Split() or Reverse() functions, as required.
public static string ReverseSentence(string input)
{
var word = new Queue<char>();
var sentence = new Stack<IEnumerable<char>>( new [] { word } );
foreach ( char c in input )
{
if (c == ' ')
{
sentence.Push( " " );
sentence.Push( word = new Queue<char>() );
}
else
{
word.Enqueue(c);
}
}
return new string( sentence.SelectMany( w => w ).ToArray() );
}
Usage:
public void Test()
{
var input = "I'm Learning c#";
var output = ReverseSentence(input);
Console.WriteLine(output);
}
Output:
c# Learning I'm
DotNetFiddle
Without split and reverse, I modify your logic little bit to achieve what you need
namespace MyNamespace
{
public class Program
{
public static void Main(string[] args)
{
var m="this is mystring";
var b = new char [m.Length];
var j=0;
//Your code goes here
for (int i = m.Length - 1; i >= 0; i--)
{
b[j]=m[i];
j++;
if(m[i]==' ' || i==0)
{
if(i==0)
{
b[j]=' ';
}
for (int x = b.Length - 1; x >= 0; x--)
{
Console.Write(b[x]);
}
b=new char[m.Length];
j=0;
}
}
Console.ReadKey();
Console.WriteLine("Hello, world!");
}
}
}
Input: "this is mystring"
Output: "mystring is this"
Here is a simple console application for your question
Without using Reverse and Split methods (just for loop)
class Program
{
static void Main()
{
string input = "I'm learning C#";
string[] result = new string[3];
int arrayIndex = 0;
string tempStr = "";
// Split string
for (int i = 0; i < input.Length; i++)
{
tempStr += input[i].ToString();
if (input[i] != ' ')
{
result[arrayIndex] = tempStr;
}
else
{
tempStr = "";
arrayIndex++;
}
}
// Display Result
for (int i = result.Length - 1; i >= 0; i--)
{
System.Console.Write(result[i] + ' ');
}
System.Console.WriteLine();
}
}
Press Ctrl + F5 to run the program
Output: C# learning I'm