Advertisement
ada1711

Untitled

Sep 13th, 2024
14
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.97 KB | None | 0 0
  1. Certainly! Here is the full translation from Polish to English:
  2.  
  3. ---
  4.  
  5. ### Guessing Game
  6.  
  7. **Lesson Objective:**
  8. The goal of this lesson is to reinforce knowledge through the practical example of a guessing game.
  9.  
  10. ---
  11.  
  12. ### Agenda:
  13. 1. Preliminary questions and concept review.
  14. 2. Using AI to generate drawings from characters.
  15. 3. Creating the Guessing Game (Hangman, Gallows).
  16. 4. Summary.
  17.  
  18. ---
  19.  
  20. ### Preliminary Questions and Review:
  21. - What are arrays?
  22. - How do methods work?
  23. - What is the difference between the `char` and `string` types?
  24.  
  25. ---
  26.  
  27. ### Task 1: Conversations with AI (max 20 minutes of class time)
  28. Encourage artificial intelligence to draw a series of simple ASCII drawings for you. The drawings should represent an animation of a loss in the Hangman game, consisting of 7 frames/stages. It can be a figure on a gallows or a breaking raft, an exploding bomb, a tree or flower losing leaves, or a melting snowman.
  29.  
  30. **Hint:** Use popular AI chats like Microsoft Copilot, Google Gemini, or OpenAI’s ChatGPT for this task.
  31.  
  32. **Interesting drawing suggestions:**
  33. - Melting snowman
  34. - Christmas tree losing needles
  35. - Flower losing petals
  36. - Figure on a breaking raft
  37.  
  38. **Pre-made set of 7 Hangman drawings for the trainer (and for less advanced students if needed):**
  39. [Link to Hangman drawings](https://drive.google.com/file/d/1IFNUR2Kvjb6ERPPWDrS0unaipe5drHUh/view?usp=drive_link)
  40.  
  41. ---
  42.  
  43. ### Task 2: Hangman Project
  44. Create a Hangman game by expanding the previously prepared template. Your project should include the implementation of the `Main` method below unchanged, and also define the methods used in it to create a playable game mechanic.
  45.  
  46. Student link:
  47. [OnlineGDB link for students](https://onlinegdb.com/JHkCKnb7_)
  48.  
  49. ```csharp
  50. // Main method of the program, executed at startup
  51. static void Main()
  52. {
  53. string[] hangmanDrawings = CreateHangmanDrawings();
  54. string[] wordArray = CreateWordList();
  55. string selectedWord = DrawRandomWord(wordArray);
  56. (string wordToDisplay, int nonLetterCount) = HideWord(selectedWord);
  57. GuessWord(selectedWord, wordToDisplay, nonLetterCount, hangmanDrawings);
  58. }
  59. ```
  60.  
  61. ---
  62.  
  63. ### Step 1: Declaring Methods
  64. We begin by creating a project and pasting the implementation of the `Main` method above. We will immediately receive errors indicating that the invoked methods do not exist. We need to analyze and declare them according to the return types and parameters.
  65.  
  66. We spend time walking through their usage cases together with the students. They should recognize the types of data to be used. We write one method manually, while for the remaining methods we use the IDE suggestions (`Lightbulb -> Generate Method...`).
  67.  
  68. **Using Visual Studio’s help**
  69.  
  70. Declare the methods `CreateHangmanDrawings()`, `CreateWordList()`, `DrawRandomWord()`, `HideWord()`, and `GuessWord()`, taking into account the parameters they should accept and return. In their definitions, we add an empty `return` so that the program can compile without errors when executed. Pay attention to the `HideWord()` method, as it can return more than one item thanks to the use of parentheses.
  71.  
  72. ```csharp
  73. // Main method of the program, executed at startup
  74. static void Main()
  75. {
  76. string[] hangmanDrawings = CreateHangmanDrawings();
  77. string[] wordArray = CreateWordList();
  78. string selectedWord = DrawRandomWord(wordArray);
  79. (string wordToDisplay, int nonLetterCount) = HideWord(selectedWord);
  80. GuessWord(selectedWord, wordToDisplay, nonLetterCount, hangmanDrawings);
  81. }
  82.  
  83. // Method to create an array of words that can be guessed
  84. static string[] CreateWordList()
  85. {
  86. return new string[] {};
  87. }
  88.  
  89. // Method to create hangman drawings for different stages of the game
  90. static string[] CreateHangmanDrawings()
  91. {
  92. return new string[] {};
  93. }
  94.  
  95. // Method to randomly select a word from the list of words
  96. static string DrawRandomWord(string[] wordArray)
  97. {
  98. return "";
  99. }
  100.  
  101. // Method to hide letters in the word using '_' and count non-letter characters
  102. static (string hiddenWord, int nonLetterCount) HideWord(string selectedWord)
  103. {
  104. return ("", 0);
  105. }
  106.  
  107. // Method implementing the main game logic where the user guesses letters of the word
  108. static void GuessWord(string selectedWord, string wordToDisplay, int nonLetterCount, string[] hangmanDrawings)
  109. {
  110. }
  111. ```
  112.  
  113. ---
  114.  
  115. ### Step 2: Implementing the Hangman Drawings and Word List
  116. We test to ensure the program compiles. We won’t see anything in the console just yet.
  117. We implement the methods `CreateHangmanDrawings()` and `CreateWordList()`. Both are similar since they only return arrays with text defined by us. For the drawings, we paste 7 different stages of the Hangman drawing, generated earlier by AI (each stage as a separate string in the array). Make sure they start from the left edge of the editor. For the words, input any number of your own words that players will guess.
  118.  
  119. ```csharp
  120. // Method creating an array of words that can be guessed
  121. static string[] CreateWordList()
  122. {
  123. return new string[] { "programmer", "camp", "environment", "programming language", "giant" };
  124. }
  125.  
  126. // Method creating hangman drawings for different stages of the game + an initial empty one
  127. static string[] CreateHangmanDrawings()
  128. {
  129. return new string[] {
  130. "",
  131. @"
  132. +---+
  133. | |
  134. |
  135. |
  136. |
  137. |
  138. =========",
  139. @"
  140. +---+
  141. | |
  142. O |
  143. |
  144. |
  145. |
  146. =========",
  147. @"
  148. +---+
  149. | |
  150. O |
  151. | |
  152. |
  153. |
  154. =========",
  155. @"
  156. +---+
  157. | |
  158. O |
  159. /| |
  160. |
  161. |
  162. =========",
  163. @"
  164. +---+
  165. | |
  166. O |
  167. /|\ |
  168. |
  169. |
  170. =========",
  171. @"
  172. +---+
  173. | |
  174. O |
  175. /|\ |
  176. / |
  177. |
  178. =========",
  179. @"
  180. +---+
  181. | |
  182. O |
  183. /|\ |
  184. / \ |
  185. |
  186. ========="
  187. };
  188. }
  189. ```
  190.  
  191. ---
  192.  
  193. ### Step 3: Drawing the Word to Guess
  194. We implement the `DrawRandomWord()` method, which returns a randomly selected word from the previously defined list of words.
  195.  
  196. ```csharp
  197. static string DrawRandomWord(string[] wordArray)
  198. {
  199. Random randomMachine = new Random();
  200. int drawnWordIndex = randomMachine.Next(0, wordArray.Length);
  201. return wordArray[drawnWordIndex];
  202. }
  203. ```
  204.  
  205. We test with breakpoints to check the drawn words.
  206.  
  207. ---
  208.  
  209. ### Step 4: Hiding the Word from the Player
  210. We implement the `HideWord()` method. It should convert the previously drawn word into a string of underscores that will be displayed later in the game. In the case of a word consisting of more than one word, the algorithm should account for spaces. Additionally, for the correct functioning of the core game mechanics, we need to count how many characters in the word are not letters.
  211.  
  212. We implement the algorithm in such a way that it loops through each character in the drawn word and appropriately converts or adds it to the counter. Checking if a character is a letter is done using the built-in `IsLetter()` method available for `char` types.
  213.  
  214. ```csharp
  215. // Method to hide letters in the word using '_' and count non-letter characters
  216. static (string hiddenWord, int nonLetterCount) HideWord(string selectedWord)
  217. {
  218. int nonLetterCount = 0; // Counter for non-letter characters (e.g. spaces, commas)
  219. string wordToDisplay = "";
  220.  
  221. for (int i = 0; i < selectedWord.Length; i++)
  222. {
  223. char character = selectedWord[i];
  224. if (char.IsLetter(character)) // Check if the character is a letter and replace it with '_'
  225. {
  226. wordToDisplay += '_';
  227. }
  228. else
  229. {
  230. wordToDisplay += character; // Keep the character unchanged if it's not a letter and increase the counter
  231. nonLetterCount++;
  232. }
  233. }
  234.  
  235. return (wordToDisplay, nonLetterCount); // Return the hidden word and number of non-letter characters
  236. }
  237. ```
  238.  
  239. ---
  240.  
  241. ### Step 5: Core Game Mechanics
  242. We implement the final and most important method, `GuessWord()`. It accepts all the variables we created earlier, so before proceeding, make sure the code works by testing with breakpoints to ensure that no invalid data is passed.
  243.  
  244. The gameplay is based on the main game loop, which repeatedly prompts the user for letters. The loop continues until all letters are revealed. If the player runs out of guesses and loses, the method will terminate prematurely with a loss message.
  245.  
  246. ```csharp
  247. // Method implementing the main game logic where the user guesses letters of the word
  248. static void GuessWord(string selectedWord, string wordToDisplay, int nonLetterCount, string[] hangmanDrawings)
  249. {
  250. // Create a counter for user mistakes, a counter for revealed letters, and a storage for used letters
  251. int mistakeCount = 0;
  252. int revealedLetterCount = 0;
  253. string usedLetters = "";
  254.  
  255. while (revealedLetterCount < selectedWord.Length - nonLetterCount)
  256. {
  257. // At the start of each round, clear the console, display the current state of the word, drawing, and used letters
  258. Console
  259.  
  260. .Clear();
  261. Console.WriteLine(wordToDisplay);
  262. Console.WriteLine(hangmanDrawings[mistakeCount]);
  263. Console.WriteLine($"Used letters: {usedLetters}");
  264. Console.Write("Enter a letter: ");
  265.  
  266. char enteredLetter = Console.ReadLine()[0]; // Get the first character entered by the user
  267. // -> Here, the game logic will continue
  268. }
  269. Console.WriteLine($"Congratulations, you won! The word was '{selectedWord}'");
  270. Console.ReadLine();
  271. }
  272. ```
  273.  
  274. After getting the letter from the user, we implement a mechanism to check if the letter has already been used. If it hasn't, we check if it appears in the word. If it has, we notify the player and skip the iteration without consequences.
  275.  
  276. ```csharp
  277. char enteredLetter = Console.ReadLine()[0]; // Read the first character entered by the user
  278.  
  279. if (!usedLetters.Contains(enteredLetter)) // Check if the letter hasn't been used yet
  280. {
  281. usedLetters += enteredLetter; // Add the letter to the used ones
  282.  
  283. if (selectedWord.Contains(enteredLetter) && !wordToDisplay.Contains(enteredLetter)) // Check if the letter is in the word
  284. {
  285. // -> Here, the correct letter logic will continue
  286. }
  287. else
  288. {
  289. // -> Here, the incorrect letter logic will continue
  290. }
  291. }
  292. else
  293. {
  294. Console.WriteLine("This letter has already been used. Try again.");
  295. }
  296. ```
  297.  
  298. We proceed to expand the letter analysis mechanism. If the letter appears in the word, we loop through each character of the word and reveal the guessed positions. If the letter doesn't appear, it means the player made a mistake, and we subtract a life point and draw the next part of the hangman. If the player runs out of guesses, the game should terminate with a loss message.
  299.  
  300. ```csharp
  301. if (selectedWord.Contains(enteredLetter) && !wordToDisplay.Contains(enteredLetter)) // Check if the letter is in the word
  302. {
  303. for (int i = 0; i < selectedWord.Length; i++)
  304. {
  305. // If the entered letter matches the letter in the selected word
  306. if (selectedWord[i] == enteredLetter)
  307. {
  308. // Replace the corresponding position in the word to display with the guessed letter
  309. wordToDisplay = wordToDisplay.Remove(i, 1);
  310. wordToDisplay = wordToDisplay.Insert(i, enteredLetter.ToString());
  311. revealedLetterCount++; // Increase the revealed letters count
  312. }
  313. }
  314. }
  315. else
  316. {
  317. mistakeCount++; // Increase the mistake count
  318. if (mistakeCount == hangmanDrawings.Length - 1) // Check if the mistake count has reached the maximum value
  319. {
  320. Console.WriteLine(hangmanDrawings[mistakeCount]); // Display the final hangman drawing
  321. Console.WriteLine($"Unfortunately, you lost! The word was '{selectedWord}'"); // Display loss message
  322. return;
  323. }
  324. }
  325. ```
  326.  
  327. ---
  328.  
  329. ### Full `GuessWord` Method:
  330. ```csharp
  331. // Method implementing the main game logic where the user guesses letters of the word
  332. static void GuessWord(string selectedWord, string wordToDisplay, int nonLetterCount, string[] hangmanDrawings)
  333. {
  334. // Create a counter for user mistakes, a counter for revealed letters, and a storage for used letters
  335. int mistakeCount = 0;
  336. int revealedLetterCount = 0;
  337. string usedLetters = "";
  338.  
  339. while (revealedLetterCount < selectedWord.Length - nonLetterCount) // The loop continues until all letters are revealed
  340. {
  341. Console.Clear(); // Clear the console at the start of each round
  342. Console.WriteLine(wordToDisplay); // Display the current state of the word
  343. Console.WriteLine(hangmanDrawings[mistakeCount]); // Display the corresponding hangman drawing
  344. Console.WriteLine($"Used letters: {usedLetters}"); // Display used letters
  345. Console.Write("Enter a letter: ");
  346. char enteredLetter = Console.ReadLine()[0]; // Read the first character entered by the user
  347.  
  348. if (!usedLetters.Contains(enteredLetter)) // Check if the letter hasn't been used yet
  349. {
  350. usedLetters += enteredLetter; // Add the letter to the used ones
  351.  
  352. if (selectedWord.Contains(enteredLetter) && !wordToDisplay.Contains(enteredLetter)) // Check if the letter is in the word
  353. {
  354. for (int i = 0; i < selectedWord.Length; i++)
  355. {
  356. // If the entered letter matches the letter in the selected word
  357. if (selectedWord[i] == enteredLetter)
  358. {
  359. // Replace the corresponding position in the word to display with the guessed letter
  360. wordToDisplay = wordToDisplay.Remove(i, 1);
  361. wordToDisplay = wordToDisplay.Insert(i, enteredLetter.ToString());
  362. revealedLetterCount++; // Increase the revealed letters count
  363. }
  364. }
  365. }
  366. else
  367. {
  368. mistakeCount++; // Increase the mistake count
  369. if (mistakeCount == hangmanDrawings.Length - 1) // Check if the mistake count has reached the maximum value
  370. {
  371. Console.WriteLine(hangmanDrawings[mistakeCount]); // Display the final hangman drawing
  372. Console.WriteLine($"Unfortunately, you lost! The word was '{selectedWord}'"); // Display loss message
  373. return;
  374. }
  375. }
  376. }
  377. else
  378. {
  379. Console.WriteLine("This letter has already been used. Try again."); // Display message that the letter has been used
  380. }
  381. }
  382.  
  383. Console.WriteLine($"Congratulations, you won! The word was '{selectedWord}'"); // Display win message
  384. Console.ReadLine(); // Wait for user to press a key before closing the program
  385. }
  386. ```
  387.  
  388. Full program: [Link to full code](https://onlinegdb.com/hD6RTVhZ4)
  389.  
  390. ---
  391.  
  392. ### Suggestions for Code Refactoring:
  393. After completing the program, it’s a good idea to talk with the students and ask them where separate methods could be extracted from the code. It’s helpful to suggest which mechanics could be moved to separate modules. Consider which parts of the code are repeated and how extracting them could improve the program's readability.
  394. **Hint:** The most potential is in the `GuessWord` method. Examples of methods to extract: `wasLetterAlreadyUsed`, `isLetterInWord`, `checkRemainingLives`.
  395.  
  396. ---
  397.  
  398. ### Possible Extensions:
  399. - Adding a hint mechanic to reveal one random letter.
  400. - Adding the option to play again after finishing the game.
  401. - Displaying a game summary with statistics about guessed letters in a given number of attempts.
  402.  
  403. ---
  404.  
  405. ### Summary:
  406. - Can artificial intelligence be helpful in programming?
  407. - Can a method return more than one variable?
  408. - How do you check if the letter entered by the user is a character? (Answer: `char.IsLetter`)
  409. - What built-in methods of the `string` class can be useful for manipulating and analyzing strings? (Answer: `Contains`, `Length`, `Remove`, `Insert`).
  410.  
  411. ---
  412.  
  413. Let me know if you need any further modifications or clarifications!
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement