This question already has answers here:
Retrieving a random word from a string array [duplicate]
(2 answers)
Closed 2 years ago.
Good evening.
I am trying to create a hangman game in C#. It works fine when I use just one secret word (In this example, the word HASHTAG is used).
But I need to get it to work using an array of words as per those featured in the multi-line comments.
Can anyone please offer assistance?
My full code follows...
class HangManGame
{
static void Main()
{
Console.Title = ("Hangman Game");
string secretword = "HASHTAG";
/*string[] secretword = {
"MARIO", "SONIC", "THELEGENDOFZELDA", "DONKEYKONG", "LUIGI",
"PEACH", "LINK", "LARACROFT", "BOWSER", "KRATOS",
"PLAYSTATION", "NINTENDO", "TETRIS", "GRANDTHEFTAUTO",
"FINALFANTASY", "THELASTOFUS", "GHOSTOFTSUSHIMA", "HORIZONZERODAWN",
"HALO", "FORZA", "CRASHBANDICOOT", "WORLDOFWARCRAFT", "CALLOFDUTY",
"FORTNITE", "ANIMALCROSSING", "DOOM", "METALGEARSOLID", "MINECRAFT",
"RESIDENTEVIL", "PACMAN", "SPACEINVADERS", "ASTEROIDS",
"STREETFIGHTER", "MORTALKOMBAT", "SUPERMARIOKART", "POKEMON",
"BIOSHOCK", "TOMBRAIDER"
}; */
List<string> letterGuessed = new List<string>();
int live = 5;
Console.WriteLine("Welcome To Hangman!");
Console.WriteLine("Enter a letter to guess for a {0} Letter Word ", secretword.Length);
Console.WriteLine("You Have {0} Lives remaining \n", live);
Isletter(secretword, letterGuessed);
while (live > 0)
{
string input = Console.ReadLine();
if (letterGuessed.Contains(input))
{
Console.WriteLine("You Entered Letter [{0}] already", input);
Console.WriteLine("Try a Different Letter \n");
GetAlphabet(input);
continue;
}
letterGuessed.Add(input);
if (IsWord(secretword, letterGuessed))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(secretword);
Console.WriteLine("Congratulations!");
break;
}
else if (secretword.Contains(input))
{
Console.WriteLine("Good Entry \n");
string letters = Isletter(secretword, letterGuessed);
Console.Write(letters);
Console.WriteLine("\n");
}
else
{
Console.WriteLine("That Letter Is Not In My Word");
live -= 1;
Console.WriteLine("You Have {0} Lives Remaining", live);
}
Console.WriteLine();
if (live == 0)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Game Over \nMy Secret Word is [ {0} ]", secretword);
break;
}
}
Console.ReadKey();
}
static bool IsWord(string secretword, List<string> letterGuessed)
{
bool word = false;
for (int i = 0; i < secretword.Length; i++)
{
string c = Convert.ToString(secretword[i]);
if (letterGuessed.Contains(c))
{
word = true;
}
else
{
return word = false;
}
}
return word;
}
static string Isletter(string secretword, List<string> letterGuessed)
{
string correctletters = "";
for (int i = 0; i < secretword.Length; i++)
{
string c = Convert.ToString(secretword[i]);
if (letterGuessed.Contains(c))
{
correctletters += c;
}
else
{
correctletters += "_ ";
}
}
return correctletters;
}
static void GetAlphabet(string letters)
{
List<string> alphabet = new List<string>();
for (int i = 1; i <= 26; i++)
{
char alpha = Convert.ToChar(i + 96);
alphabet.Add(Convert.ToString(alpha));
}
int num = 49;
Console.WriteLine("Letters Left are :");
for (int i = 0; i < num; i++)
{
if (letters.Contains(letters))
{
alphabet.Remove(letters);
num -= 1;
}
Console.Write("[" + alphabet[i] + "] ");
}
Console.WriteLine();
Console.WriteLine("\n");
}
}
}
Implementation of 'Honeyboy Wilson' comment
Random random = new Random();
string secretword = secretwords[random.Next(0, secretwords.Length)];
Switch the declaration order and use the Random class to pick a value from the Array?
string[] secretWords = {
"MARIO", "SONIC", "THELEGENDOFZELDA", "DONKEYKONG", "LUIGI",
"PEACH", "LINK", "LARACROFT", "BOWSER", "KRATOS",
"PLAYSTATION", "NINTENDO", "TETRIS", "GRANDTHEFTAUTO",
"FINALFANTASY", "THELASTOFUS", "GHOSTOFTSUSHIMA", "HORIZONZERODAWN",
"HALO", "FORZA", "CRASHBANDICOOT", "WORLDOFWARCRAFT", "CALLOFDUTY",
"FORTNITE", "ANIMALCROSSING", "DOOM", "METALGEARSOLID", "MINECRAFT",
"RESIDENTEVIL", "PACMAN", "SPACEINVADERS", "ASTEROIDS",
"STREETFIGHTER", "MORTALKOMBAT", "SUPERMARIOKART", "POKEMON",
"BIOSHOCK", "TOMBRAIDER"
};
Random R = new Random();
string secretword = secretWords[R.Next(secretWords.Length)];
Related
This question already has an answer here:
first Console.ReadLine() returns immediately
(1 answer)
Closed 2 years ago.
Here's the code:
using System;
using manjan_in_csharp.Classes;
namespace manjan_in_csharp
{
class Program
{
static void Main()
{
Console.WriteLine("What Do You Want ? \nPress");
Console.WriteLine("'s' to use sort");
var wish =(char)Console.Read(); //explicitly converting to char (char)
// Console.WriteLine(wish.GetType());
switch (wish)
{
case 's':
Console.WriteLine("Enter the size of unsort list");
Sort sort = new Sort();
var size = int.Parse(Console.ReadLine());
sort.CallingSort(size);
break;
default:
Console.WriteLine("Invalid Operation");
break;
}
}
}
}
Now, I only enter s when the line appears "Press s to use sort" and I get this error:
I have no idea what's causing the problem. I mean, I enter s and then it doesn't let me do anything and the program crashes and I get that error.
Btw, here's the Sort class
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
namespace manjan_in_csharp.Classes
{
public class Sort
{
public void CallingSort(int size)
{
var datetimenow = DateTime.Now;
Console.WriteLine("|| Sorting Progra ||\t\t\t DATE/TIME: " + datetimenow.ToString("dd-mm-yyyy hh-mm"));
Console.WriteLine("Now Which Sort Method you want to apply");
Console.WriteLine("'b' for BubbleSort");
var method = (char)Console.Read();
switch (method)
{
case 'b':
Bubblesort(ListInitilizer(size));
break;
default:
Console.WriteLine("There is no sort related to that");
break;
}
}
public List<int> ListInitilizer(int size)
{
List<int> unsortlist = new List<int>();
Random random = new Random();
for (int i = 0; i < size; i++)
{
unsortlist.Insert(i, random.Next(0, size));
}
Console.WriteLine("Now the unsort list is :");
for (int i = 0; i < size; i++)
{
Console.Write(unsortlist[i] + " ");
}
Console.WriteLine();
return unsortlist;
}
public void Bubblesort(List<int> unsortlist)
{
var start = DateTime.Now;
for (int i = 0; i < unsortlist.Count; i++)
{
for (int j = i; j < unsortlist.Count; j++)
{
if (unsortlist[j] < unsortlist[i])
{
int temp = unsortlist[i];
unsortlist[i] = unsortlist[j];
unsortlist[j] = temp;
}
}
}
Console.WriteLine("Applying Bubblesort");
Console.WriteLine("Items in Sorted List : "+unsortlist.Count);
for (int i = 0; i < unsortlist.Count; i++)
{
Console.Write(unsortlist[i] + " ");
}
var end = DateTime.Now;
Console.WriteLine("\nTotal Duration is : " + (end - start) + " Seconds");
}
}
}
The problem is with the combination of these two lines of code:
var wish =(char)Console.Read();
...
var size = int.Parse(Console.ReadLine());
The Console.Read() takes only single character from the input stream so for your input 's' followed by carriage-return. The carriage-return is discarded which will then be passed to next read i.e. Console.ReadLine().
You can either use ReadLine() for the first input as well or use ReadKey(). Modify your Main() as such
static void Main()
{
Console.WriteLine("What Do You Want ? \nPress");
Console.WriteLine("'s' to use sort");
var wish = Console.ReadKey().Key; //explicitly converting to char (char)
// Console.WriteLine(wish.GetType());
switch (wish)
{
case ConsoleKey.S:
Console.WriteLine("Enter the size of unsort list");
Sort sort = new Sort();
var size = int.Parse(Console.ReadLine());
sort.CallingSort(size);
break;
default:
Console.WriteLine("Invalid Operation");
break;
}
}
I want to create simple console wingman game.My error is that if i try get pos of 2 same character in word i get only one and the other is skipped.
For example Tomatoe.
Console output:
Tomatoe
_ o m a t _ _
I know i didnt use live didnt have time for that i do it layter.
class Program {
static string[] word = { "Pineapple", "Apple" , "Tomatoe" , "Pizza"};
static int wordIndex = 0;
static char[] randomWord;
static bool guessing = true;
public static void Main(string[] args)
{
int lives = 3;
Console.OutputEncoding = Encoding.UTF8;
Console.InputEncoding = Encoding.UTF8;
Random r = new Random();
wordIndex = r.Next(word.Length);
randomWord = word[wordIndex].ToLower().ToCharArray();
char[] randomWordcensored = new char[randomWord.Length];
for (int i = 0; i < randomWord.Length; i++)
{
randomWordcensored[i] = '_';
}
Console.WriteLine("Hello");
foreach (var item in randomWordcensored)
{
Console.Write(item + " ");
}
Console.WriteLine();
Console.WriteLine("Please Enter character:");
while (guessing = true)
{
int g = 0;
char userinput;
bool security = char.TryParse(Console.ReadLine() ,out userinput);
if (security == true) {
if (randomWord.Contains(userinput))
{ //help needed
g = (word[wordIndex].ToString().IndexOf(userinput) == -1 ? 0 : word[wordIndex].ToString().IndexOf(userinput));
randomWordcensored[g] = userinput;
Console.WriteLine("Good :) " + g);
foreach (var item in randomWordcensored)
{
Console.Write(item + " ");
}
}
else
{
lives--;
Console.WriteLine("Wrong!\n-Lives:" + lives);
}
}
else
{
Console.WriteLine("Enter only one charracter!");
}
}
}
}
You'll want to handle user input that might be different casing and such. Because of that it's easiest to just visit every character in the random word just once.
Here's a REPL that I made to solve this:
using System;
using System.Collections.Generic;
class MainClass {
public static void Main (string[] args) {
var word = "Tomato";
var input = "t";
var letter = input.ToLower()[0];
var indices = new List<int>();
for(var i = 0; i < word.Length; i++)
if (word.ToLower()[i] == letter)
indices.Add(i);
Console.WriteLine($"Secret word: {word}");
Console.WriteLine($"User guess: {input}");
Console.WriteLine($"Found at {String.Join(", ", indices)}");
}
}
and its output:
Mono C# compiler version 4.0.4.0
Secret word: Tomato
User guess: t
Found at 0, 4
I have a small program that changes values of char arrays. But first you need to tell the program in which array you want to change a value; and write a new value and its position into that same array position.
But when I enter the array number, the program skips the code lines allowing the entry of the new value and its position. Then the program throws a FormatException at the end.
Here's the code:
static void addLetters(char[] messageOne, char[] messageTwo)
{
char Mnumber;
char letter;
string pos;
int position;
Console.Write("- Message #: ");
Mnumber = (char)Console.Read();
if (Mnumber == '1')
{
Console.Write("Letter: ");
letter = (char)Console.Read();
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
messageOne[position - 1] = letter;
}
if (Mnumber == '2')
{
Console.Write("Letter: ");
letter = (char)Console.Read();
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
messageTwo[position - 1] = letter;
}
}
static void Main(string[] args)
{
char[] array1 = new char[50];
char[] array2 = new char[50];
for (int i = 0; i < 50; i++)
{
array1[i] = '*';
array2[i] = '*';
}
addLetters(array1, array2);
}
}
P.S. Could you please tell me how I can make this code more 'elegant'?
When reading a single character it's reccommended to use Console.ReadKey().KeyChar. I've modified your code to handle exceptions as well:
static void addLetters(char[] messageOne, char[] messageTwo)
{
char Mnumber;
char letter;
string pos;
int position;
try
{
do
{
Console.Write("- Message #: ");
Mnumber = Console.ReadKey().KeyChar;
Console.WriteLine();
}
while (Mnumber != '1' && Mnumber != '2');
Console.Write("\nLetter: ");
letter = Console.ReadKey().KeyChar;
Console.Write("\nPosition: ");
pos = Console.ReadLine();
position = Int32.Parse(pos);
if (Mnumber == '1')
messageOne[position - 1] = letter;
else
messageTwo[position - 1] = letter;
}
catch (FormatException)
{
Console.WriteLine("Invalid input format, position must be an integer");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Position out of array bounds");
}
finally
{
Console.Read();
}
}
Try a single function for both messages, and TryParse() your string to integer conversions
static char ReadChar(string prompt)
{
// Screen Prompt
Console.Write(prompt);
// Read a Character
return Console.ReadKey(false).KeyChar;
}
static int ReadNumber(string prompt)
{
// Screen Prompt
Console.Write(prompt);
int result=-1;
// Reads a number and onverts it into an integer
int.TryParse(Console.ReadLine(), out result);
return result;
}
// Caution, this modifies the contents of `messages`
static void addLetters(params char[][] messages)
{
// Read message index (first=1, second=2, etc)
int Mnumber=ReadNumber("- Message #: ");
// Read letter
char letter=ReadChar("Letter: ");
// Read placement position
int position=ReadNumber("\nPosition: ");
// Get the right message
char[] current_message=messages[Mnumber-1];
// Assigns a letter to the message
current_message[position]=letter;
}
static void Main(string[] args)
{
int n=50; //Store the size instead of hard coding it all over your code
char[] array1=new char[n];
char[] array2=new char[n];
for (int i=0; i<n; i++)
{
array1[i]='*';
array2[i]='*';
}
addLetters(array1, array2);
}
In my hangman game, I am attempting to prompt the user to enter the number of "lives" (or guesses) the player should be given. After I type a number at the prompt, the following error message is displayed:
Cannot implicitly convert type 'int' to 'string'
The following line causes the error:
lives = Console.ReadLine();
The lives field is an integer. How can I correctly assign a user-entered value to an integer field?
Here is my complete code:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class Hangman
{
//guesses
public static int lives = 5;
//Words for the game
static string[] wordBank = { "study", "cat", "dress", "shoes", "lipstick" };
// Create new ArrayList and initialize with words from array wordBank
static ArrayList wordList = new ArrayList(wordBank);
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Title = "C# Hangman";
Console.WriteLine("Hang man!");
//Gamemenu
string response = "";
do
{
Console.Write("Enter Command (1. Add Words, 2. List Words , 3. Play , 4. Exit) Pick 1-4: ");
response = Console.ReadLine();
switch (response)
{
case "1": AddWord(); break;
case "2": ListWords(); break;
case "3": Play(); break;
case "4": break;
}
} while (response != "4");
}
//add words to list
static void AddWord()
{
Console.Write("Enter the word to add: ");
String temp = Console.ReadLine();
wordList.Add(temp);
Console.WriteLine("{0} was added to the dictionary!", temp);
}
//Display words
static void ListWords()
{
foreach (Object obj in wordList)
Console.WriteLine("{0}", obj);
Console.WriteLine();
}
//How many guesses
static void AskLives()
{
try
{
Console.WriteLine("please enter number of lives?");
//This line gives me the error
lives = Console.ReadLine();
}
catch
{
// if user does not enter a number ask it again
AskLives();
}
}
//Gameplay
static void Play()
{
Random random = new Random((int)DateTime.Now.Ticks);
string wordToGuess = wordList[random.Next(0, wordList.Count)].ToString();
string wordToGuessUppercase = wordToGuess.ToUpper();
StringBuilder displayToPlayer = new StringBuilder(wordToGuess.Length);
for (int i = 0; i < wordToGuess.Length; i++)
displayToPlayer.Append('-');
List<char> correctGuesses = new List<char>();
List<char> incorrectGuesses = new List<char>();
bool won = false;
int lettersRevealed = 0;
string input;
char guess;
AskLives();
while (!won && lives > 0)
{
Console.WriteLine("Current word: " + displayToPlayer);
Console.Write("Guess a letter: ");
input = Console.ReadLine().ToUpper();
guess = input[0];
if (correctGuesses.Contains(guess))
{
Console.WriteLine("You've already tried '{0}', and it was correct!", guess);
continue;
}
else if (incorrectGuesses.Contains(guess))
{
Console.WriteLine("You've already tried '{0}', and it was wrong!", guess);
continue;
}
if (wordToGuessUppercase.Contains(guess))
{
correctGuesses.Add(guess);
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuessUppercase[i] == guess)
{
displayToPlayer[i] = wordToGuess[i];
lettersRevealed++;
}
}
if (lettersRevealed == wordToGuess.Length)
won = true;
}
else
{
incorrectGuesses.Add(guess);
Console.WriteLine("Nope, there's no '{0}' in it!", guess);
lives--;
}
Console.WriteLine(displayToPlayer.ToString());
}
if (won)
Console.WriteLine("You won!");
else
Console.WriteLine("You lost! It was '{0}'", wordToGuess);
Console.Write("Press ENTER to exit...");
Console.ReadLine();
}
}
}
Your lives field is an integer, but Console.ReadLine returns a string.
You can use Int32.Parse(Console.ReadLine()) to parse the input into an integer. Note that an exception will be thrown if the text entered by the user cannot be interpreted as an integer.
Your catch block will work here and re-prompt. It would be more appropriate to use the Int32.TryParse method:
int tmpLives;
if (Int32.TryParse(Console.ReadLine(), out tmpLives))
{
lives = tmpLives;
}
else
{
AskLives();
}
You want to do something along the lines of:
string livesString = Console.ReadLine();
lives = Convert.ToInt32(livesString);
I'm guessing Console.ReadLine() gives you a string. This will not play ball with your integer lives. You could try this:
lives = Int.Parse(Console.ReadLine())
How can I replace more than one occurrence of an input letter using indexOf? I can currently find all index occurrences if they end in -1. I'm also getting an unhanded exception when converting to char.
static Random rnd = new Random();
static void Main(string[] args)
{
string wrong = "";
ArrayList list = new ArrayList();
list.Add("Dune");
list.Add("The Lord of the Rings");
list.Add("The Iliad");
list.Add("Hamlet");
int r = rnd.Next(list.Count);
Console.WriteLine((string)list[r]);
string s = (string)list[r];
string patten = "[a-zA-Z0-9]";
Regex rgx = new Regex(patten);
string sDash = rgx.Replace(s, "-");
do
{
string a = " ";
Console.Write("Guess a letter: ");
a = Console.ReadLine();
while (a.Length != 1)
{
Console.WriteLine("Please enter only one letter:");
a = Console.ReadLine();
}
char myChar = a[0];
int input = s.IndexOf(a);
while (input != -1)
{
Console.WriteLine(input);
input = s.IndexOf(myChar, input + 1);
}
if (input != -1)
{
StringBuilder builder = new StringBuilder(sDash);
builder[input] = myChar;
sDash = builder.ToString();
Console.WriteLine(sDash + String.Compare(sDash, s, true));
}
else {
StringBuilder builder = new StringBuilder(wrong);
builder.Append(a);
string wrongAnswers = builder.ToString();
Console.WriteLine("Wrong, try again. \n {0}", wrongAnswers);
}
} while (String.Compare(sDash, s) == -1);
}
This is how I would do :
static Random rnd = new Random();
static void Main(string[] args)
{
string wrong = "";
List<String> list = new List<String>();
list.Add("Dune");
list.Add("The Lord of the Rings");
list.Add("The Iliad");
list.Add("Hamlet");
int r = rnd.Next(list.Count);
Console.WriteLine((string)list[r]);
string s = (string)list[r];
string patten = "[a-zA-Z0-9]";
Regex rgx = new Regex(patten);
string sDash = rgx.Replace(s, "-");
StringBuilder wrongAnswers = new StringBuilder();
do
{
string a = " ";
Console.Write("Guess a letter: ");
a = Console.ReadLine();
while (a.Length != 1)
{
Console.WriteLine("Please enter only one letter:");
a = Console.ReadLine();
}
char myChar = a.ToLower()[0];
int input = s.ToLower().IndexOf(myChar);
bool foundSomething = false;
StringBuilder builder = new StringBuilder(sDash);
while(input != -1)
{
foundSomething = true;
builder[input] = myChar;
try
{
input = s.ToLower().IndexOf(myChar, input + 1);
}
catch (ArgumentOutOfRangeException)
{
input = -1;
}
}
sDash = builder.ToString();
if (foundSomething)
{
Console.WriteLine(sDash + " " + sDash.ToLower().Equals(s.ToLower()));
}
else
{
wrongAnswers.Append(myChar);
Console.WriteLine("Wrong, try again. \n {0}", wrongAnswers);
}
} while (!sDash.ToLower().Equals(s.ToLower()));
}
By the way, there are many optimization that can be done here, but the principle is here..