[내일배움캠프 사전캠프 과제 - Stage3. 각자 속도에 맞춰 나아가기]
드디어 달리기반의 마지막 단계인 Lv3에 도달했다!!
Lv3은 팀원과 함께하는 과제이다. 라이브 쉐어로 페어코딩을 해도 되고, 코드리뷰를 하며 서로의 코드를 피드백해도 된다.
▶ 우리팀은 둘 다 하기로 했다. 각자 문제 풀어보고서 팀원들과 정한 날짜에 모여서 코드 리뷰를 할 것이다. 모이는 날에 페어코딩도 해보기로 했다. ☞ 했음.
- 행맨 게임 설명
- 나의 풀이
- 플레이 모습
- 나의 코드 피드백 & 후기
- 페어코딩 후기
7. 행맨 게임
사용자로부터 문자를 입력받아 숨겨진 단어를 맞추는 행맨 게임을 작성하세요.
사용자가 단어의 모든 문자를 맞추거나 주어진 기회 내에 맞추지 못할 때까지 반복합니다.
- 게임 설명: 행맨 게임은 사용자가 단어를 추측하는 게임입니다. 사용자는 알파벳을 하나씩 입력하고, 맞출 때마다 단어의 해당 위치에 문자가 표시됩니다. 틀릴 경우, 기회가 줄어듭니다.
- 배열 사용: char[] 배열을 사용하여 단어를 저장하고, 추측된 문자를 저장합니다.
- 반복문 사용: 게임은 사용자가 단어를 맞추거나 기회가 끝날 때까지 반복됩니다.
- 조건문 사용: 각 입력된 문자가 단어에 포함되는지 확인합니다.
사용 변수 설명
- secretWord : 맞춰야 할 단어입니다. 예제에서는 "hangman"으로 설정되어 있습니다.
- guessWord : 사용자가 맞춘 문자를 저장하는 문자 배열로, 초기에는 언더스코어(_)로 채워져 있습니다.
- attempts : 사용자가 틀릴 수 있는 기회의 수로, 초기에는 6으로 설정되어 있습니다.
- wordGuessed : 사용자가 단어를 모두 맞췄는지를 나타내는 불리언 변수입니다.
나의 풀이
// Lv3. 7. 행맨 게임
char[] secretWord = "hangman".ToCharArray();
char[] guessWord = new char[secretWord.Length];
int attempts = 6;
bool wordGuessed = false;
int wordCount = guessWord.Length; // 남아있는 맞춰야 할 자릿수
// guessdWord 초기화
for(int i = 0; i < secretWord.Length; i++)
{
guessWord[i] = '_';
}
while(attempts > 0 && !wordGuessed)
{
Console.Write($"{attempts}번 안에 맞추세요! : ");
Console.WriteLine($"{new string(guessWord)}");
// 입력
Console.Write("알파벳을 입력하세요 : ");
char input;
bool inputSuccess = char.TryParse(Console.ReadLine(), out input);
bool isCorrect = false; // 이번 턴에 맞췄는 지 나타내는 변수
if(!inputSuccess)
{
Console.WriteLine("\n알파벳을 하나씩 입력하세요.");
continue;
}
// 맞추기
for(int i = 0; i < secretWord.Length; i++)
{
if (secretWord[i] == input)
{
guessWord[i] = input; // 맞춘 알파벳 공개'
secretWord[i] = '0'; // 같은 알파벳 정답 처리 방지
isCorrect = true; // 이번 턴에 맞췄는 지 체크
--wordCount; // 맞춰야 할 알파벳 수 차감
}
}
// 맞출 자릿수가 0이 되면 맞췄다는 의미
if (wordCount == 0)
{
Console.WriteLine($"{new string(guessWord)}. 정답입니다!");
return;
}
// 맞추지 못한 턴에는 기회 차감
if (!isCorrect)
{
attempts--;
}
Console.Clear();
}
Console.WriteLine("실패!");
행맨 게임 플레이 모습
풀면서 겪은 문제
◆ 이미 맞춘 알파벳을 또 입력했을 때도 정답 처리가 됨. 하나의 정답 알파벳만 계속 입력해도 "정답입니다!" 엔딩이 나왔음.
→ 정답 횟수 차감을 통해 정답 판정을 내렸기 때문에 생긴 문제. 1회 맞춘 부분의 문자를 '0'로 변경하면서 또 정답처리 될 수 없도록 수정하여 해결했다.
나의 코드 피드백 & 후기
팀원분들이 자유롭게 코드를 피드백해주셨다. 생각하지 못했던 실수를 찾아주시기도 하고 스스로도 느낀 허점을 짚어주시기도 했다. 가독성에 대한 의견도 나왔는데 다들 다른 의견을 가지고 계셔서 재미있었다. 얻어가는 부분도 있다고 말씀해주셔서 매우 뿌듯했다.
➖ "wordGuess 변수가 사용이 되지 않았다"
이거 정말 아차싶었다! 팀원분께서 숙제라서 의무감에 넣고 까먹은 변수냐고.. 😂 그말이 맞아서 너무 웃겼다.
변수를 의미에 맞게 사용하자면 아래처럼 수정할 수 있겠다. 그러면 현재는 while문 밖으로 나오면 실패 판정인데, attempts가 0이 될때 바로 실패하고 종료하도록 수정해야 한다. while문 조건에도 wordGuess를 넣어놓고... 정말 의미에 안맞게 영혼없이 사용한 변수다!!!! 예리하신 팀원분께 큰 감사를..
// 맞출 자릿수가 0이 되면 맞췄다는 의미
if (wordCount == 0)
{
wordGuessed = true;
Console.WriteLine($"{new string(guessWord)}. 정답입니다!");
continue;
}
➖ "중복 정답 처리 방지를 위해 secretWord를 직접 수정한 것이 아쉽다."
다 짜여진 코드에 한 줄만 추가해서 버그 수정을 하다보니 이런 코드가 된 것은 이해하지만, 게임에 재사용될 수도 있는 기존의 변수를 직접 수정한 것이 아쉽다고 표현해주셨다. 이부분은 스스로도 조금 찔렸던(?) 부분이라서 크게 공감했다. 작성할 당시에 생각하지 못했는데 더 좋은 방법이 있었다.
// 맞추기
for(int i = 0; i < secretWord.Length; i++)
{
if (secretWord[i] == input && guessWord[i] == '_')
{
guessWord[i] = input; // 맞춘 알파벳 공개'
//secretWord[i] = '0'; // 같은 알파벳 정답 처리 방지 << 기존 코드 지움
isCorrect = true; // 이번 턴에 맞췄는 지 체크
--wordCount; // 맞춰야 할 알파벳 수 차감
}
}
➖ "while문 내부 가독성이 아쉽다."
while문 내부 코드가 가독성이 아쉬워서 함수화 하는 것이 좋아보인다고 의견을 주셨다. 내용이 짧은 프로그램이라서 지금은 크게 안느껴지지만, 확실히 함수화 하는 것이 더 깔끔해보일 것으로 동의했다. 다른 팀원분은 재사용되는 코드가 없기 때문에 함수화를 추천하지 않는다는 의견도 주셨다. 짧은 프로그램이라 모두의 의견이 이해되는 부분이었다.
이후에 가독성 말씀해주신 팀원분의 코드를 보니 이해가 갔다. #region / #endregion 을 사용하셔서 코드를 블록처럼 구분하여 짜셨다. 블루프린트과 같이 비쥬얼코딩하듯이 흐름이 잘 보였다. 가독성을 높이는 방법을 한가지 더 알게 된 것 같다.
➕ "TryParse문으로 한 글자 입력받는 부분이 깔끔해보여서 마음에 든다"
어떤 팀원분께서는 얻어가는 부분이 있다고 말씀해주셨다. TryParse를 사용해서 알파벳 하나를 입력받는 부분의 코드가 마음에 든다고 해주셨다. 홍홍😊 C# 기초 문법을 공부해두길 잘한 것 같아서 뿌듯했다.
페어코딩 후기
5명 중 2명 / 3명으로 나뉘어서 페어코딩을 해봤다. 1명이 작업을 하고 나머지 인원이 옵저버가 되어 실시간으로 피드백을 하거나 의견나누고 도움을 주는 방향으로 진행되었다.
생각보다 긴장도 많이 되서 타자 속도까지 신경쓰였다. 천천히 미리 생각하고서 짜면 됐는데, 빨리 짜야한다는 생각에 손이 가는대로 썼더니 정말 비효율적인 코드가 완성되었다.. 숫자 야구 게임 만들었던 예제에서 HashSet 자료구조를 썼던 것이 기억나서 '아 그때 HashSet을 썼지!' 하고 무턱대고 사용해버렸다. 의미없이 여러번 검사하는 코드가 완성되었다. 창피한 코드니까 접어두겠다..
using System.Linq;
char[] secretWord = { 'h', 'a', 'n', 'g', 'm', 'a', 'n' };
char[] guessWord = new char[secretWord.Length];
int attempts = 6;
bool wordGuessed = false;
int answerNum = secretWord.Length;
HashSet<char> words = new HashSet<char>();
for(int i = 0; i < secretWord.Length; ++i)
{
guessWord[i] = '_';
words.Add(secretWord[i]);
}
// 행맨 게임
while(!wordGuessed && attempts > 0)
{
Console.WriteLine($"{new string(guessWord)}, attempts : {attempts}");
Console.Write("Input : ");
char[] userInput = Console.ReadLine().ToArray<char>();
if(words.Contains(userInput[0]))
{
// 대체
if(IsValidInput(userInput[0]) == false)
{
attempts--;
continue;
}
}
else
{
attempts--;
continue;
}
if(answerNum == 0)
{
wordGuessed = true;
Console.WriteLine("정답");
}
}
bool IsValidInput(char target)
{
bool flag = false;
for(int i = 0; i < secretWord.Length; ++i)
{
if (secretWord[i] == target)
{
secretWord[i] = '_';
guessWord[i] = target;
--answerNum;
flag = true;
}
}
return flag;
}
다른 팀원분들이 하시는 걸 볼때는 정말 재미있었다. 팀원분들도 긴장하셔서 다들 멈칫멈칫 하셨지만, 다들 자기만의 코딩 스타일이 돋보이는 고수분들이셨다. 잘 안되는 부분이 있을 때 코드의 의도에 맞게 해결해드렸다. "@@@하는 의도가 맞으시면 @@@로 옮기셔야 할 것 같아요~" << 제일 뿌듯했음
원래 계획대로라면 내일도 페어코딩과 코드리뷰를 진행하기로 했었지만 시간이 생각보다 오래걸려서 코드리뷰만 진행하기로 했다. 페어코딩이 떨리긴 했지만 생각보다 굉장히 재미있었다. 나중에 유니티를 개발할 때도 페어코딩을 한다면 서로 도움받을 수 있는 부분이 더 많을 것 같다. 전반적으로 신선한 경험이라 좋았다!
'공부 기록 > C#' 카테고리의 다른 글
[C#] 기초 문법 톺아보기 (1) - 입력과 출력, 배열, 필드와 프로퍼티 (0) | 2025.01.08 |
---|---|
[C#] 숫자 야구 게임 만들기 (달리기반 Lv3) (2) | 2025.01.07 |
[C#] 내일배움캠프 사전캠프 과제 - 달리기반 Lv2. 기초 문법 활용해보기 (팩토리얼 계산, 숫자 맞추기 게임, 구구단 출력, 배열 최댓값 최솟값 찾기, 정렬) (0) | 2025.01.03 |
[C#] 내일배움캠프 사전캠프 과제 - 달리기반 Lv1. 기초 문법 파헤치기 (홀수 출력, 배열 합계 및 평균 계산) (0) | 2025.01.02 |
[C#] 내일배움캠프 사전캠프 과제 - 걷기반 Lv2. 제어문(조건문, 연산자) (1) | 2024.12.31 |