오늘 학습 키워드

api 사용, json 파싱

오늘 학습 한 내용을 나만의 언어로 정리하기

API 호출하는 방법

출처 출처 2

  1. 여기서 사용하려는건 JSON이기 때문에, JSON 파싱 패키지를 다운받는다.
    • 나는 newtonsoft.json을 사용하기로 함
  2. HttpClient 만들어서 설정해줌
  3. 나는 행맨을 만들것이기 때문에, 랜덤으로 단어를 뽑아주는 사이트를 찾음 단어 사이트
  4. 단어를 char 배열로 저장
  5. 단어를 다 맞췄는지 확인하는 wordGuessed 와 기회 attempts 만듬
  6. 기회가 떨어지거나 다 맞출 때 까지 계속 입력받음

행맨 코드

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!");
            }
        }
    }
}
 

코드가 너무 더러워요

뭔가 코드가 너무 더러워서 챗지피티에게 코드 좀 바꿔달라 해봄.
그랬더니 다음 문제들을 발견함.

  1. API 호출 실패 / JSON 응답 파싱 실패의 경우 예외처리 필요.
  2. data가 null 이거나 비어있을 때의 처리가 필요
  3. 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 배열로 파싱하자.

내일 학습 할 것은 무엇인지

숫자 야구 게임 만들기