Inserting disks in a container having different diameters at each level [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need to make a program , in which the number of layers for a container and their diameters are taken input from the user. Then the user inserts a disk of certain diameter into the program. Then the disks moves through all possible layers , the process can be repeated until the container is filled or user stops adding more disks to it. Finally the program is supposed to give total number of disks contained in the container and their layer numbers. Iam badly stuck and my mind is blank now. Kindly help!
[updated code] The problem remains that the container is never fills , program keeps on inserting disks. I cant think of a logical way to let it know when container is full.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.Write("Number of Layers ? ");
int layers = int.Parse(Console.ReadLine());
int[] container = new int[layers];
int disk_number = 0;
for (int i = 0; i < layers; i++)
{
Console.Write("\nLayer num {0} : ",1+i);
container[i] = int.Parse(Console.ReadLine());
}
Console.Write("\nPress 1 to Insert disk? ");
int insert = int.Parse(Console.ReadLine());
while (insert == 1)
{
Console.Write("\nDiameter of Disk? ");
int disk_diameter = int.Parse(Console.ReadLine());
if (disk_diameter <= container[0])
{
for (int i = 0; i < layers;) {
if (disk_diameter <= container[i])
{
i++;
}
else { if (i == layers - 1) break; layers = i+1; }
}
disk_number++;
Console.Write("\nPress 1 to Insert more disk(s)? ");
insert = int.Parse(Console.ReadLine());
if (insert != 1) { Console.Write("\nNumber of disks contained in container are : {0}", disk_number); }
}
else
{
Console.Write("\nDisc blocked the surface opening of the container , no further input could be processed! \nNumber of disks contained in container are : {0}",disk_number);
break;
}
}
Console.ReadLine();
}
//static int inserting_disk(int a);
}
}

You haven't explained me what you want exactly, but here goes a much improved (on different fronts) version of your code which, hopefully, you will take as a good learning exercise. The overall structure is pretty bad, but I have intended to emulate the one in your original code such that you can understand perfectly what is going on. The "input flow" is still pretty poor and thus might stop working easily (if the right inputs are not introduced) but, at least, I have replaced your Parse with TryParse accounting for different-type inputs (e.g., a string instead of an integer).
Test the code, see what it does. Get used to the new variables (I have renamed/redefined some of them because were too confusing in its original version) and build a code delivering exactly what you are after (and, ideally, properly written).
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.Write("Number of Layers ? ");
int input0 = 0;
bool right0 = int.TryParse(Console.ReadLine(), out input0);
if (right0 && input0 > 0)
{
int tot_layers = input0;
int[] maxDiamLayer = new int[tot_layers + 1]; //better maintain the indexing as displayed to the user: starting from 1
bool[] layerDone = new bool[tot_layers + 1]; //This boolean array will make sure that you don't use the same layer more than once
int disk_number = 0;
for (int i = 1; i <= tot_layers; i++)
{
Console.Write("\nIntroduce the maximum diameter for the layer num {0} : ", i);
maxDiamLayer[i] = int.Parse(Console.ReadLine());
}
Console.Write("\nPress 1 to Insert disk? ");
input0 = 0;
right0 = int.TryParse(Console.ReadLine(), out input0);
while (right0 && input0 == 1)
{
Console.Write("\nDiameter of Disk? ");
int input = 0;
bool right = int.TryParse(Console.ReadLine(), out input);
if (!right || input <= 0)
{
Console.Write("\nWrong Diameter. ");
continue;
}
int disk_diameter = input;
bool oneInserted = false;
for (int i = 1; i <= tot_layers; i++)
{
if (disk_diameter <= maxDiamLayer[i] && !layerDone[i])
{
layerDone[i] = true;
oneInserted = true;
disk_number++;
Console.Write("\nNumber of disks contained in container are : {0}", disk_number);
Console.Write("\nPress 1 to Insert more disk(s)? ");
int input2 = 0;
bool right2 = int.TryParse(Console.ReadLine(), out input2);
if (!right2 || input2 != 1 || disk_number >= tot_layers) break;
Console.Write("\nDiameter of Disk? ");
input = 0;
right = int.TryParse(Console.ReadLine(), out input);
if (!right || input <= 0)
{
Console.Write("\nWrong Diameter. ");
break;
}
disk_diameter = input;
}
}
if (disk_number >= tot_layers)
{
Console.Write("\nAll the layers are filled");
break;
}
else
{
Console.Write("\nWrong diameter. Try again.");
}
if (!oneInserted)
{
Console.Write("\nThe disk couldn't be inserted");
Console.Write("\nPress 1 to continue ");
int input3 = 0;
bool right3 = int.TryParse(Console.ReadLine(), out input3);
if (!right3 || input3 != 1) break;
}
}
}
Console.ReadLine();
}
}
}

Related

How to find a way of output the number of attempts for each question of the quiz?

I am making the quiz application on C# in Console version. I have almost done all things, but I don't know how to show the number of attempts for each question, after when the quiz is finished. If you know something, let me know.
I can not add more lines of the code, as the website doesn't allow to do it
if (keys[index] == answer) // Answer is correct
{
Console.WriteLine();
Console.WriteLine("Congratulations. That's correct!");
Console.WriteLine();
totalScore += markPerQuestion;
index++;
Console.WriteLine("The total score is: {0}", totalScore);
Console.WriteLine("Used attempt(s): {0}", attempt);
attempt = 1;
count = attempt;
markPerQuestion = 20;
}
else // Answer is incorrect
{
attempt++;
count++;
if (attempt <= 3)
{
markPerQuestion /= 2;
}
else if (attempt > 3 && attempt < 5) // The fourth attempt gives zero points
{
markPerQuestion = 0;
totalScore += markPerQuestion;
}
else if(attempt >= 5) // Move to the next question
{
Console.WriteLine("Sorry, you used all attempts for that question. Moving to the next question");
index++;
markPerQuestion = 20;
attempt = 1;
count = attempt;
continue;
}
Console.WriteLine("Oops, try again");
}
if ((index > keys.Length - 1 && index > questions.Length - 1)) // Questions and answer keys are finished
{
for (int i = 0; i < questions.Length; i++)
{
Console.WriteLine("Question {0} was answered after {1} attempt(s)", (i + 1), count);
}
break;
}
Consider this solution:
Create a public class that will allow you to store the results.
public class QuizMark
{
public int Attempts;
public int Mark;
}
For the Console app create a method to control the Quiz. Call the method Quiz() from the Main method.
private const int MAX_ATTEMPTS = 5;
private static void Quiz()
{
var quizResults = new List<QuizMark>();
var questionAnswers = new List<int>() { 1, 3, 5, 2, 3, 6 };
foreach(var a in questionAnswers)
{
var v = QuizQuestion(a);
quizResults.Add(v);
}
int i = 0;
quizResults.ForEach(e => Console.WriteLine($"Question: {++i} Attempts: {e.Attempts} Mark: {e.Mark}"));
var total = quizResults.Sum(s => s.Mark);
Console.WriteLine($"Total Points: {total}");
}
Notice the List collection that stores an object of the class QuizMark. This is where the results of each question are stored: attempts and points.
The List questionAnswers simply contains the expected answer to each of the questions.
Now create the method that is going to control how each question in the quiz will be handled:
private static QuizMark QuizQuestion(int answer)
{
var quizMark = new QuizMark();
int guess = 0; //Store ReadLine in this variable
int mark = 20;
for (int attempt = 1; attempt < MAX_ATTEMPTS + 1; attempt++)
{
guess++; //remove when adding Console.ReadLine
if (guess.Equals(answer))
{
quizMark.Attempts = attempt;
quizMark.Mark = mark;
break;
}
else
{
mark = attempt <= 3 ? mark/2 : 0;
quizMark.Attempts = attempt;
quizMark.Mark = mark;
}
}
return quizMark;
}
You will need to replace the incrementor guess++ with the actual guess the user makes. This code is designed to go though automatically just as a demonstration.
IMPORTANT NOTE:
You will want to do some error handling any time you allow users to enter data. They might enter non-integer values. Probably using a loop around a Console.ReadLine where you check the value of the input with a Int32.TryParse().

using methods for program?

So I did this hangman game, and it works perfectly fine, the only problem is that I want to use methods to organize everything.
And yes, it is a school project. I tried my best but whenever I try to put a part of the program in a method it's as if I removed a variable and it underlines it in red.
I removed them for now so it's more clear. also, the file I used contained 19 8 letters max words, one on each line.
Can someone tell me how I can incorporate methods without ruining the whole thing? also English isn't my first language plz excuse any mistakes, the code was in french and I translated it for this question. thank you very much. I appreciate your time and effort :)
using System;
using System.IO;
namespace TP3
{
class Program
{
public const String Dico = "dico.txt";
public static void Welcome()
{
//Mot de bienvenue
Console.WriteLine("Welcome to hangman !");
}
public static void Goodbye()
{
Console.WriteLine("thx for playing, goodbye!");
}
public static void Program()
{
int SolvedWords= 0;
string WordToGuess= "";
int NumberOfLetters ;
int x = 0;
int WordTried = 0;
Console.WriteLine("");
Console.WriteLine("Do you wanna guess a word ? oui or non.");
Console.WriteLine("you have 8 chances per word.");
string Answer= Console.ReadLine();
Answer= Answer.ToLower();
while (Answer== "oui" && WordTried <19)
{
const int Lives= 8;
int LostLives= 0;
int LivesLeft= 8;
int LettersGuesed= 0;
x += 1;
WordTried += 1;
if (WordTried <= 20 && WordTried >1)
{
Console.WriteLine("Do you wanna guess a word ? oui or non.");
Answer= Console.ReadLine();
Answer= Answer.ToLower();
}
//Read a word in the file
int compteur = 0;
string ligne;
// Read file and show on the line
System.IO.StreamReader file = new System.IO.StreamReader(#"dico.txt");
while ((line = file.ReadLine()) != null)
{
compteur++;
if (compteur == x)
{
WordToGuess= line;
}
}
file.Close();
char[] table;
table = new char[WordToGuess.Length];
for (int i = 0; i < table.Length; i++)
{
table[i] = WordToGuess [i];
}
//change each letter into a *
Console.WriteLine("here’s the word to guess : ");
string HiddenWord = "********";
char[] table2;
table2 = new char[WordToGuess.Length];
for (int i = 0; i < table2.Length; i++)
{
table2[i] = HiddenWord[i];
}
for (int i = 0; i < table2.Length; i++)
{
Console.Write(table2[i]);
}
Console.WriteLine("");
//guess the word
while (LettersGuesed< WordToGuess.Length && LivesLeft> 0)
{
Console.WriteLine("");
/* Console.WriteLine("Devinez une seule Letterdu mot. Ne pas écrire une Letter plus d'une fois de suite. Si c'est le cas, recommencez le jeu.");*/
string Letter= Console.ReadLine();
Letter= Letter.ToLower();
NumberOfLetters = Letter.Length;
char[] table3;
table3= new char[NumberOfLetters ];
for (int i = 0; i < table2.Length; i++)
{
if (table[i].Equals(Letter[0]))
{
Table2[i] = Letter[0];
LettersGuesed+= 1;
}
}
for (int i = 0; i < table2.Length; i++)
{
Console.Write(table2[i]);
}
if (WordToGuess.IndexOf(Lettre) < 0)
{
Console.WriteLine("");
Console.WriteLine("wrong letter.");
LostLives+= 1;
LivesLeft= Lives- LostLives;
Console.WriteLine("you have " + LivesLeft+ " lives left.");
}
if (WordToGuess.IndexOf(Lettre) >= 0)
{
Console.WriteLine(" ");
Console.WriteLine("right !");
Console.WriteLine("you have " + LivesLeft+ " lives left.");
}
if (LettersGuesed== WordToGuess.Length && LivesLeft> 0)
{
SolvedWords+= 1;
Console.WriteLine(" ");
Console.WriteLine("you found the word !");
Console.WriteLine("you found " + SolvedWords+ " on" + WordTried + " words so far.");
}
if (LivesLeft== 0)
{
Console.WriteLine("you couldnt guess the word.");
Console.WriteLine("the word was :");
for (int i = 0; i < table.Length; i++)
{
Console.Write(table[i]);
}
Console.WriteLine(" ");
Console.WriteLine("you found " + SolvedWords+ " on" + WordTried + " words so far.");
}
if (WordTried == 19)
{
Console.WriteLine("no more words to guess.");
}
}
}
}
static void Main(string[] args)
{
Welcome();
Programme();
Goodbye();
}
}
}
Im not going to make every method for your project, I'll help kickstart on how to think about it. Look at your current code for reading the file of words. You can move that into a method -
public string[] ReadWordsFromFile()
{
string file = "path to your file here";
return File.ReadAllLines(file);
}
Or pass the file path as parameter -
public string[] ReadWordsFromFile(string filePath)
{
return File.ReadAllLines(filePath);
}
Next you can have a method to get random words -
public string GetRandomWord(string[] wordsArray)
{
Random random = new Random();
int randomIndex = random.Next(0, wordsArray.Length);
return wordsArray[randomIndex];
}
Note - words can be repeated if you do it this way, if you don't want that - then add logic to remove that item from the list once its used in the game. If you remove it within this method, its not actually going to remove it from the game, as you'll still be passing the entire array when getting a new word. Ill leave the implementation of that logic to you, if you want it.
In the "game controller" code -
you can use the above methods like this -
string file = "your path to txt file";
string[] allWords = ReadWordsFromFile(file);
string WordToGuess = GetRandomWord(allWords);
May be your next goal should be something like this -
public void GameControler()
{
// get all words here and other logic before game starts
while (Attempts > 0)
{
string WordToGuess = GetRandomWord(wordsArray);
// get letterGuessed from user
bool letterExists = CheckIfLetterExists(WordToGuess, letterGuessed);
if (!letterExists)
{
Attempts--;
ExecuteWrongGuessMethod(x, y);
}
else
{
ExecuteRightGuessMethod(w);
}
}
}
public bool CheckIfLetterExists(string word, string letter)
{
if (word.Contains(letter)) return true;
else return false;
}
public void ExecuteWrongGuessMethod(string passWhatYouNeedTo, int somethingElse)
{
// what to do when the guess is wrong e.g. Console.Writeline("wrong guess");
}
public void ExecuteRightGuessMethod(string word)
{
// logic when guess is right. e.g. Show the letter guessed within the word on the console etc.
}
All of this isn't the best way to do it. BUT I personally feel this is logically next step a beginner takes after what you've implemented. Seeing a fully well-developed program might be too much without understanding atleast some basic concepts of OOP.
After learning how to create Methods and use them, then comes classes and objects. Which should be implemented in this game, but this is all for now. I recommend you do a short C# course on coursera etc or even youtube. And slowly move towards a better understanding of SOLID principles. And by SOLID I mean an acronym for the 5 principles and not the actual word. All the best.

Random number guessing game not working C# [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am trying to get this random number guessing game working. The program runs, but it doesn't give the "you won" message when you enter the correct number, and the hint feature does not give the feed back it is supposed to. Any help appreciated.
using System;
namespace randomNumberGame
{
class Program
{
static void Main(string[] args)
{
Random r = new Random();
var val = r.Next(1, 100);
var guess = 0;
bool correct = false;
var attemptsLeft = 5;
Console.WriteLine("I'm thinking of a number between 1 and 100.");
while (!correct && attemptsLeft >= 1)
{
Console.Write("You have " + attemptsLeft + " lives left. Please enter your Guess: ");
string input = Console.ReadLine();
var message = "";
var difference = val - guess;
if (!int.TryParse(input, out guess))
{
Console.WriteLine("That's not a number.");
continue;
}
if (difference == 0)
{
Console.WriteLine("You have won");
correct = true;
}
else
{
if (Math.Abs(difference) >= 50)
{
message = Math.Sign(difference) == -1 ? "Very High" : "Very Low";
}
else if (Math.Abs(difference) < 50 && Math.Abs(difference) >= 20)
{
message = Math.Sign(difference) == -1 ? "High" : "Low";
}
else if (Math.Abs(difference) < 20 && Math.Abs(difference) >= 10)
{
message = Math.Sign(difference) == -1 ? "Moderatley High" : "Moderately Low";
}
else if (Math.Abs(difference) < 10)
{
message = Math.Sign(difference) == -1 ? "Somewhat High" : "Somewhat Low";
}
else Console.WriteLine("???");
}
attemptsLeft--;
}
}
}
}
"it doesn't give the you won message when you enter the correct number"
Actually, it does! But then the program exits so quickly that you never see it. To solve this, add a line that waits for the user to press a key at the end of your Main method, so you can see the final result:
// Add this as the last line of the main method:
Console.ReadKey();
"the hint feature does not give the feed back it is supposed too"
This is because you never output the hint message! At the end of your while loop, add a line to do so:
// Add this as the last line of the while loop:
Console.WriteLine(message);
These things can be found easily if you simply set a breakpoint in your code (in Vistal Studio, click the left margin next to one of the lines and a red dot will appear (or press F9)). Then you can step through the code using F10 and you can watch the values of local variables change and see what is happening step-by-step.
Another way to help avoid problems (and to narrow down where they occur) is to take out chunks of code that does something specific and put it in a method. This will make it easier to debug in the long run.
For example, we can write methods that take in a string to display to the user as a prompt for input, and return a strongly-typed value based on their entry. We can also have these methods take in an optional validation method that can be used to validate that the input they entered falls within a valid range (like a number from 1 to 100, or a name that's not longer than 25 characters):
public static string GetStringFromUser(string prompt,
Func<string, bool> validator = null)
{
string result;
var cursorTop = Console.CursorTop;
do
{
ClearSpecificLineAndWrite(cursorTop, prompt);
result = Console.ReadLine();
} while (!(validator?.Invoke(result) ?? true));
return result;
}
public 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 also write a helper method to get our "difference string", which could take in the guess, the number, and the min and max values, then calculate a percentage of how close they were and then return the appropriate string:
public static string GetDifferenceString(int guess, int number,
int minVal, int maxVal)
{
var percentAway =
Math.Abs(guess - number) / (double)(maxVal - minVal) * 100;
var direction = guess - number > 0 ? "High" : "Low";
if (percentAway < 10) return $"Very close, but {direction}";
if (percentAway < 20) return $"Just a little {direction}";
if (percentAway < 30) return $"Somewhat {direction}";
if (percentAway < 40) return $"Moderately {direction}";
if (percentAway < 50) return $"{direction}";
return $"Very {direction}";
}
This simplifies our main code by removing the loops and checking results from there, and lets us focus on our main tasks:
static void Main(string[] args)
{
var randomNumber = new Random().Next(1, 101);
var maxAttempts = 5;
var guess = 0;
Console.WriteLine("I'm thinking of a number between 1 and 100.");
for (int attempt = 0; attempt < maxAttempts; attempt++)
{
Console.WriteLine($"You have {maxAttempts - attempt} " +
$"out of {maxAttempts} attempts remaining.");
guess = GetIntFromUser("Please enter your guess (1 - 100): ",
i => i > 0 && i < 101);
if (guess == randomNumber)
{
Console.WriteLine($"You have won in {attempt + 1} tries!");
break;
}
Console.WriteLine(GetDifferenceString(guess, randomNumber, 1, 100));
}
if (guess != randomNumber)
{
Console.WriteLine("Sorry, you lose! The number was: " +
$"{randomNumber}");
}
GetKeyFromUser("\nDone! Press any key to exit...");
}

For Loop Will Not Execute C# [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am making a program that will a number of dice a number of times. I have made a method called 'RollDice'. the method works until the for loop. It returns to the main method after I type 'roll' in the console and i don't know why it won't execute the script in side the for loop. I have marked place where the code stops working. any help would be much appreciated, thanks!
using System;
using System.Collections.Generic;
namespace Dice Roller
{
class Program
{
public static void Main(string[] args)
{
int nos = 6;
int nod = 1;
int nor = 1;
string OP;
int x = 1;
while (x == 1)
{
Console.WriteLine("Random Dice Macine");
Console.WriteLine("Type 'edit' To Edit Dice Settings");
Console.WriteLine("Type 'clear' To Clear The Screan");
Console.WriteLine("Type 'exit' To Close The Aplication");
Console.WriteLine("Type 'roll' to Roll The Dice");
Console.Write("-> ");
OP = Console.ReadLine();
if (OP == "exit")
{
Environment.Exit(0);
}
else if (OP == "edit")
{
Console.Clear();
Console.WriteLine("Number Of Sides On The Dice");
Console.Write("->");
nos = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Number Of Dice");
Console.Write("->");
nod = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Number Of Roles");
Console.Write("->");
nor = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Setup Compleat! Press Space To Continue.");
Console.ReadKey();
Console.Clear();
}
else if (OP == "clear")
{
Console.Clear();
}
else if (OP == "roll")
{
RollDice(nor, nos, nod);
}
}
}
public static void RollDice(int nor, int nos, int nod)
{ //Code Works Here
Random gen = new Random();
List<int> numbers = new List<int>();
for (int n = 1; n < nod; n++)
{
for (int i = 1; i < nor; i++)
{ //But Not Here
numbers.Add(gen.Next(1, nos));
}
foreach (int element in numbers)
{
Console.Write(element + ", ");
}
numbers.Clear();
}
}
}
}
In for-loops the counter should start from 0 and not from 1. In your case nor and nod are equal to 1. That is why the loops are never executed.
Only thing I can see is that if nod or nor is 1 when the program reaches the for loops, the condition to end the loop is already met. Use '<=' instead in the ebd condition.
On line
for (int n = 1; n < nod; n++)
nod is 1, and n < nod check is termination for loop.
Either set i = 0 or set check n <= nod.

Streamreader and Readline

Today I'm having trouble with something basic and just having a complete lapse trying to remember how to do this. What I'm trying to do is simply use a number from a file as the int variable for my whole program. Using C#.
StreamReader read = new StreamReader("../../data.dat");
string input=(Console.ReadLine());
int num = Convert.ToInt32(input);
System.Console.WriteLine("Range of Numbers: 1 - " + num);
for (int i = 1; i <= num; i++)
{
if (DivBySeven(i) == true && DivByEleven(i) == true)
{
int j = i;
while (j > 0)
{
System.Console.Write("# ");
j--;
}
}
else if (DivBySeven(i) == true)
{
System.Console.Write("* ");
}
else if (DivByEleven(i) == true)
{
System.Console.Write(". ");
}
else
{
System.Console.Write(i +" ");
}
}
Console.ReadKey();
Sorry for the lack of comments. Quick overview: I am taking the number from the file and using it to output to the console 1-the file number, and taking multiples of 11 and 7, also just 7 and just 11 and doing a couple different things with them.
You have
string input=(Console.ReadLine()); // read from the keyboard
int num = Convert.ToInt32(input);
which is user keyboard input.
To read from the file you need
string input=(read.ReadLine()); // read from the stream reader
int num = Convert.ToInt32(input);

Categories