트랙
/
Ruby
Ruby
/
연습 문제
/
체스 게임
체스 게임

체스 게임

학습 연습 문제

소개

범위는 두 값 사이의 구간을 나타내요. 범위를 지원하는 가장 흔한 타입은 Integer와 String이에요. 범위는 컬렉션을 빠르게 만들거나, 문자열을 자르거나, 값이 범위에 들어 있는지 확인하거나, 반복하는 등 여러 가지 일에 쓸 수 있어요. 범위 연산자 .. 또는 ...로 만들어요(각각 끝 값을 포함하고 포함하지 않아요).

1..5  # => 1..5
1...5 # => 1...5

(1..5).to_a # => [1, 2, 3, 4, 5]
(1...5).to_a # => [1, 2, 3, 4]

범위 연산자가 두 개인 이유는 끝 값을 포함하는 범위와 포함하지 않는 범위를 모두 만들 수 있게 하기 위해서예요. 예를 들어 0부터 시작하는 인덱스를 다룰 때 유용해요.

범위는 Range 생성자인 new를 사용해서 만들 수도 있어요.

Range.new(1, 5) # A range containing 1, 2, 3, 4, 5
Note

Ruby에서 범위 연산자 ..나 ...로 범위를 만들고 그 범위에 메서드를 호출하려면, 범위를 괄호로 감싸야 해요. 그렇지 않으면 메서드가 범위 연산자의 두 번째 인자에 호출되기 때문이에요.

(1..5).sum # => 15
1..5.sum # => Error: undefined method `sum' for 5:Integer (NoMethodError)

부분 문자열 가져오기

문자열을 자르고 싶을 때는 범위 연산자로 부분 문자열을 얻을 수 있어요. 즉, 부분 문자열의 시작과 끝 인덱스로 범위를 만드는 거예요.

"Hello World"[0..4] # => "Hello"
"Hello World"[6..10] # => "World"

음수 인덱스를 사용해서 문자열 끝에서부터 부분 문자열을 얻을 수도 있어요.

"Hello World"[-5..-1] # => "World"
"Hello World"[6..-4] # => "Wo"

범위 메서드

범위에는 함께 사용할 수 있는 메서드들이 있어요. 예를 들어, 범위에 있는 모든 값의 합을 구하거나 범위에 어떤 값이 포함되어 있는지 확인할 때 이런 메서드를 쓸 수 있어요.

메서드 설명 예시
sum 범위에 있는 모든 값의 합을 반환해요 (1..5).sum # => 15
size 범위의 크기를 반환해요 (1..5).size # => 5
include? 범위에 주어진 값이 포함되어 있으면 true, 그렇지 않으면 false를 반환해요 (1..5).include?(3) # => true

끝이 없는 범위와 시작이 없는 범위

범위는 끝이 없을 수도, 시작이 없을 수도 있어요. 끝이 없거나 시작이 없는 범위는 시작 값이나 끝 값이 nil이지만, 범위를 정의할 때 nil은 생략할 수 있어요.

시작이 없거나 끝이 없는 범위는 예를 들어 문자열을 처음부터 또는 끝까지 자르고 싶을 때 유용해요.

"Hello World"[0..] # => "Hello World"
"Hello World"[4..] # => "o World"
"Hello World"[..5] # => "Hello "
Caution

컬렉션에 사용하지 않으면, 끝이 없는 범위는 주의해서 사용하지 않을 경우 끝없는 시퀀스를 초래할 수 있어요.

문자열 범위

문자열도 범위에 사용할 수 있고, 두 문자열 사이의 문자열 구간을 얻을 수 있어요. 특정 문자열을 사용할 때 동작이 조금 예상 밖일 수 있으니 주의해서 사용해요.

("aa".."az").to_a # => ["aa", "ab", "ac", ..., "az"]

지침

체스 애호가라면 누구나 자신만의 체스 게임을 한번 만들어 보고 싶어 하죠. 온라인에 이미 체스 구현이 많이 있긴 하지만, 직접 만든 것은 세상에 하나뿐일 거예요!

먼저 기물의 기본 이동 시스템을 구현하는 것부터 시작해요.

체스 게임은 가로 8칸, 세로 8칸인 보드에서 진행돼요. 각 칸은 문자 하나와 숫자 하나로 나타내요.

1. 랭크와 파일 범위 정의하기

게임은 보드의 랭크를 저장할 수 있어야 해요. 랭크는 보드의 행이고, 1부터 8까지의 숫자로 나타내요.

게임은 보드의 파일도 저장해야 해요. 파일은 보드의 열이고, A부터 H까지의 문자로 구분해요.

랭크와 파일의 범위를 각각 저장하는 Chess::RANKS와 Chess::FILES 상수를 정의해요.

Chess::RANKS
# => 1..8

Chess::FILES
# => 'A'..'H'

2. 칸이 유효한지 확인하기

게임은 어떤 칸이 유효한지 확인해야 해요. 칸의 랭크와 파일이 각각 랭크와 파일의 범위 안에 있으면 유효한 칸이에요.

랭크를 정수로 담는 rank 인자와 파일을 문자로 담는 file 인자를 받는 Chess.valid_square? 메서드를 정의해요. 이 메서드는 rank와 file이 랭크와 파일의 범위 안에 있으면 true를 반환하고, 그렇지 않으면 false를 반환해야 해요.

Chess.valid_square?(1, 'A')
# => true

3. 플레이어의 닉네임 가져오기

게임은 플레이어의 닉네임을 알아내야 해요. 닉네임은 플레이어의 이름에서 앞 2글자, 성에서 뒤 2글자를 따서 만들어요. 닉네임은 모두 대문자로 표기해야 해요.

플레이어의 이름을 문자열로 담는 first_name 인자와 플레이어의 성을 문자열로 담는 last_name 인자를 받는 Chess.nickname 메서드를 정의해요. 이 메서드는 플레이어의 닉네임을 대문자 문자열로 반환해야 해요.

Chess.nickname("John", "Doe")
# => "JOOE"

4. 이동 메시지 만들기

게임은 어떤 플레이어가 어느 칸으로 이동했는지 알려 주는 메시지를 만들어야 해요. 메시지에는 플레이어의 닉네임과 이동한 칸을 사용해요. 또한 칸의 파일과 랭크가 파일과 랭크의 범위 안에 있는지 확인해서 이동이 유효한지도 판단해야 해요.

이동이 유효하면 메시지는 "{nickname} moved to {square}"여야 해요. 이동이 유효하지 않으면 메시지는 "{nickname} attempted to move to {square}, but that is not a valid square"여야 해요.

플레이어의 이름을 문자열로 담는 first_name 인자, 플레이어의 성을 문자열로 담는 last_name 인자, 플레이어가 이동한 칸을 문자열로 담는 square 인자를 받는 Chess.move_message 메서드를 정의해요. 이 메서드는 이동 메시지를 문자열로 반환해야 해요.

Chess.move_message("John", "Doe", "A1")
# => "JOOE moved to A1"
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Ruby Exercism

체스 게임 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Ruby 트랙을 개념 21개연습 문제 121개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.