오늘 학습 키워드
api 사용, json 파싱
오늘 학습 한 내용을 나만의 언어로 정리하기
API 호출하는 방법
- 여기서 사용하려는건 JSON이기 때문에, JSON 파싱 패키지를 다운받는다.
- 나는 newtonsoft.json을 사용하기로 함
- HttpClient 만들어서 설정해줌
- 나는 행맨을 만들것이기 때문에, 랜덤으로 단어를 뽑아주는 사이트를 찾음 단어 사이트
- 단어를 char 배열로 저장
- 단어를 다 맞췄는지 확인하는 wordGuessed 와 기회 attempts 만듬
- 기회가 떨어지거나 다 맞출 때 까지 계속 입력받음
행맨 코드
using System;
using System.Collections.Generic;
using System.Collections;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
private static readonly HttpClient client = new HttpClient();
static async Task<string[]?> GetWord()
{
var url = "https://random-word-api.herokuapp.com/word";
var response = await client.GetStringAsync(url);
string[] data = JsonConvert.DeserializeObject<string[]>(response);
return data;
}
public static async Task Main(String[] args)
{
var data = await GetWord();
char[] secretWord = data[0].ToCharArray();
char[] guessWord = new char[secretWord.Length];
for (int i = 0; i < secretWord.Length; i++) guessWord[i] = '_';
int attempts = 6;
bool wordGuessed = false;
while (!wordGuessed && attempts > 0)
{
Console.Clear();
Console.WriteLine(guessWord);
Console.WriteLine($"Remain attempts : {attempts}");
Console.Write("Write Character : ");
string? guess = Console.ReadLine();
if(guess == null)
{
continue;
}
else if (guess.Length > 1)
{
Console.WriteLine("Please Enter One Character.");
continue;
}
else
{
char guessChr = guess[0];
if(!char.IsLetter(guessChr))
{
Console.WriteLine("Please Enter One Character.");
continue;
}
bool hasChr = false;
for (int i = 0; i < secretWord.Length; i++)
{
if (secretWord[i] == guessChr)
{
hasChr = true;
guessWord[i] = guessChr;
}
}
if (!hasChr)
{
Console.WriteLine($"There's no {guessChr}");
attempts -= 1;
}
if (secretWord == guessWord)
{
wordGuessed = true;
break;
}
}
}
if (!wordGuessed)
{
string answer = new string(secretWord);
Console.WriteLine($"Failed! Answer is {answer}");
}
else
{
Console.WriteLine("congratulation! you win!");
}
}
}
}
코드가 너무 더러워요
뭔가 코드가 너무 더러워서 챗지피티에게 코드 좀 바꿔달라 해봄.
그랬더니 다음 문제들을 발견함.
- API 호출 실패 / JSON 응답 파싱 실패의 경우 예외처리 필요.
- data가 null 이거나 비어있을 때의 처리가 필요
- secretWordf == guessWord 하면 참조 비교라서, 늘 false임.
using System;
using System.Collections.Generic;
using System.Collections;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
private static readonly HttpClient client = new HttpClient();
static async Task<string[]?> GetWord()
{
try
{
var url = "https://random-word-api.herokuapp.com/word";
var response = await client.GetStringAsync(url);
string[] data = JsonConvert.DeserializeObject<string[]>(response);
return data;
}
catch (HttpRequestException e)
{
Console.WriteLine($"Network error: {e.Message}");
}
catch (JsonException e)
{
Console.WriteLine($"JSON parse error: {e.Message}");
}
catch (Exception e)
{
Console.WriteLine($"Unexpected error: {e.Message}");
}
return null;
}
public static async Task Main(String[] args)
{
// 랜덤 단어 불러오기
var data = await GetWord();
if (data == null || data.Length == 0)
{
Console.WriteLine("Failed to get a word from API.");
return;
}
char[] secretWord = data[0].ToCharArray();
char[] guessWord = new char[secretWord.Length];
for (int i = 0; i < secretWord.Length; i++) guessWord[i] = '_';
int attempts = 6;
bool wordGuessed = false;
// 맞추거나, 기회 다 소모하면 끝
while (!wordGuessed && attempts > 0)
{
Console.WriteLine("-----------------------------------");
Console.WriteLine(guessWord);
Console.WriteLine($"Remain attempts : {attempts}");
Console.Write("Write Character : ");
string? guess = Console.ReadLine();
// 빈 글자의 경우 continue
if(string.IsNullOrWhiteSpace(guess))
{
continue;
}
// 여러 글자를 입력한 경우 continue
else if (guess.Length > 1)
{
Console.WriteLine("Please Enter One Character.");
continue;
}
// 대문자 입력했을 수 있으니 소문자화 한 후 문자인지 체크
char guessChr = char.ToLower(guess[0]);
if(!char.IsLetter(guessChr))
{
Console.WriteLine("Please Enter One Alphabet Character.");
continue;
}
// 그 문자를 가지고 있는지 확인
bool hasChr = false;
for (int i = 0; i < secretWord.Length; i++)
{
if (secretWord[i] == guessChr)
{
hasChr = true; // 가지고 있음
guessWord[i] = guessChr;
}
}
// 가지고 있지 않으면 기회 차감
if (!hasChr)
{
Console.WriteLine($"There's no {guessChr} in the answer");
attempts -= 1;
}
// 문자를 다 맞췄으면 break
if (new string(secretWord) == new string(guessWord))
{
wordGuessed = true;
break;
}
}
// 기회 다 차감했는데 못 맞춘 경우
if (!wordGuessed)
{
Console.WriteLine($"Failed! Answer is {new string(secretWord)}");
}
// 맞춘 경우
else
{
Console.WriteLine("congratulation! you win!");
}
}
}
}
학습하며 겪었던 문제점 & 에러
- 문제&에러에 대한 정의
평소에 파싱하던 json은 대부분 키:값 으로 이루어져 있었음. 근데 이 사이트는 [“overfamiliarity”] 이런식으로 그냥 키도 없고 값만 있는 형태라서 당황함
- 내가 한 시도
검색을 함
- 해결 방법
string[] words = JsonConvert.DeserializeObject<string[]>(json);
그냥 바로 string array 로 파싱하면 되는거였음.
- 새롭게 알게 된 점
키:값 형태가 아니면 굳이 json 객체를 만들 필요가 없다.
- 이 문제&에러를 다시 만나게 되었다면?
키 없는 경우에는 그냥 string 배열로 파싱하자.
내일 학습 할 것은 무엇인지
숫자 야구 게임 만들기