지난번에 이어서 숫자야구를 마저 만들어 보도록 해봅시다!
그 다음은 키보드로 부터 입력값을 받는것인데 여기에 들어가면 알 수 있습니다.
func InputNumbers() [3]int {
// 두 개의 숫자 3개를 비교해서 결과를 반환한다.
var rst [3]int
for {
var no int
_, err := fmt.Scanf("%d", &no)
if err != nil {
fmt.Println("잘못 입력 했습니다.")
continue
}
for no > 0 { // 1
n := no%10
no = no/10
rst[idx] = n
idx++
}
break
}
return rst
}
이 Scanf가 어떻게 동작하는지 볼려면 여기에 들어가면 되는데 return값으로 몇 개를 입력받았는지와 실패 시 에러가 나옵니다.
지금은 몇개의 입력을 받았는지는 중요하지 않기 때문에 '이름없는 변수'라는 의미로 '_'표시를 사용해주면 됩니다.
그 후 if문으로 에러가 있으면 잘못입력했다는 문구를 표시 해주고 다시 입력을 받아야 하기 때문에 반복문을 써주고, 다시 돌아가기
위해 if문에 continue를 사용해서 해당 for문의 끝으로 가서 반복문이 다시 시작 됩니다.
그 다음 continue가 되지 않았다는 것은 에러가 없는 상황에 온 것인데, 여기서 숫자 3개를 뽑아야 되는데 어떤 숫자에 '%'를 하게 되면 123 % 10을 해서 나머지 값은 3, 123 / 10을 해서 몫은 12가 되고, 이렇게 하면 맨 마지막 숫자를 꺼낼 수 있고, 그걸 빼고 나머지를 만들 수 있게 됩니다.
12 % 10 = 2가 되고, 몫은 1이 됩니다. 이런식으로 하게 되면 1, 2, 3을 뽑아낼 수 있게 됩니다.
그래서 1번과 같이 반복문안에서 작성해 줍니다.
실행 하면 아래와 같이 되는데요
no이 0이 되면 빠져 나오기 때문에 3, 2, 1 순으로 숫자들이(n값) 변화하게 될 것입니다.
그 후 이 값을 rst의 현재 index값에 n을 넣어준 뒤 index를 증가시켜 주고, 그 다음 숫자를 다 뽑았기 때문에 break로 무한 반복문을 빠져나옵니다.
그 후 실행하여 결과를 확인해보죠.
아직 겹치는것을 확인하지 않았기 때문에 다음과 같이 뜨는 것을 확인 할 수 있습니다.
func InputNumbers() [3]int {
// 두 개의 숫자 3개를 비교해서 결과를 반환한다.
var rst [3]int
for {
var no int
_, err := fmt.Scanf("%d", &no)
if err != nil {
fmt.Println("잘못 입력 했습니다.")
continue
}
for no > 0 { // 1
n := no%10
no = no/10
rst[idx] = n
idx++
}
fmt.Println(rst)
break
}
return rst
}
입력한 숫자를 마지막에 출력시켜서 제대로 입력값이 출력되는지 확인해보죠.
입력값이 앞뒤로 바뀐것을 알 수 있습니다. 맨 뒤 부터 뽑히기 때문에 당연한 일입니다.
방법은 간단합니다. 앞뒤만 바꾸어주면 됩니다.
func InputNumbers() [3]int {
// 두 개의 숫자 3개를 비교해서 결과를 반환한다.
var rst [3]int
for {
var no int
_, err := fmt.Scanf("%d", &no)
if err != nil {
fmt.Println("잘못 입력 했습니다.")
continue
}
for no > 0 { // 1
n := no%10
no = no/10
rst[idx] = n
idx++
}
rst[0], rst[2] = rst[2], rst[0] // 추가
fmt.Println(rst)
break
}
return rst
}
다음과 같이 수정 해준 뒤 실행해봅시다!
제대로 들어가는 것을 확인 할 수 있습니다. 이제 겹치는 경우를 처리해보죠!
저번에 했었던 duplicated
를 사용하여 해결해보죠!
func InputNumbers() [3]int {
// 키보드로부터 0~9사이의 겹치지 않는 숫자 3개를 입력받아 반환한다.
var rst [3]int
for {
fmt.Println("겹치지 않는 0~9사이의 숫자 3개를 입력하세요.")
var no int
_, err := fmt.Scanf("%d\n", &no)
if err != nil {
fmt.Println("잘못 입력 했습니다.")
continue
}
success := true
idx := 0
for no > 0 {
n := no % 10
no = no / 10
duplicated := false
for j := 0; j < idx; j++ {
if rst[j] == n {
// 겹쳐서 다시 뽑아준다.
duplicated = true
break
}
}
if duplicated {
fmt.Println("숫자가 겹치지 않아야 합니다.")
success = false
break
}
rst[idx] = n
idx++
}
if !success {
continue
}
break
}
rst[0], rst[2] = rst[2], rst[0]
fmt.Println(rst)
return rst
}
이런식으로 수정 해주고, 실행해보죠!
겹쳤을 때의 처리가 잘 되는 것을 확인 할 수 있습니다.
그 다음 해결해야 할 것이 있는데 숫자를 4개를 입력하면 index out of range [3] with length 3
라는 에러가 뜹니다.
인덱스의 범위를 벗어났다는 소리인데 입력값이 3개를 넘었을 때 경우의 코드를 추가해줍시다!
func InputNumbers() [3]int {
// 키보드로부터 0~9사이의 겹치지 않는 숫자 3개를 입력받아 반환한다.
var rst [3]int
for {
fmt.Println("겹치지 않는 0~9사이의 숫자 3개를 입력하세요.")
var no int
_, err := fmt.Scanf("%d\n", &no)
if err != nil {
fmt.Println("잘못 입력 했습니다.")
continue
}
success := true
idx := 0
for no > 0 {
n := no % 10
no = no / 10
duplicated := false
for j := 0; j < idx; j++ {
if rst[j] == n {
// 겹쳐서 다시 뽑아준다.
duplicated = true
break
}
}
if duplicated {
fmt.Println("숫자가 겹치지 않아야 합니다.")
success = false
break
}
if idx >= 3 { // 추가
fmt.Println("3개 보다 많은 숫자를 입력하셨습니다.")
success = false
break
}
rst[idx] = n
idx++
}
if !success {
continue
}
break
}
rst[0], rst[2] = rst[2], rst[0]
fmt.Println(rst)
return rst
}
다음과 같이 수정 해준 뒤 실행 시켜 줍니다.
3개 이상 입력했을 시 문구가 뜨면서 다시 입력 받고, 3개가 입력되었을 때 정상적으로 넘어가는 것을 확인할 수 있습니다.
그리고 2자리의 숫자만 입력한 경우엔 다음과 같이 뜨게 되는데
나는 34를 입력했는데 화면에는 0 3 4가 출력되는 것을 확인 할 수 있습니다.
이 경우에는 숫자가 다 해석되고 난 뒤에 맨 마지막에 이 숫자의 갯수가 3보다 작은지 확인 시켜 주면 됩니다.
다음과 같이 수정해 줍시다.
func InputNumbers() [3]int {
// 키보드로부터 0~9사이의 겹치지 않는 숫자 3개를 입력받아 반환한다.
var rst [3]int
for {
fmt.Println("겹치지 않는 0~9사이의 숫자 3개를 입력하세요.")
var no int
_, err := fmt.Scanf("%d\n", &no)
if err != nil {
fmt.Println("잘못 입력 했습니다.")
continue
}
success := true
idx := 0
for no > 0 {
n := no % 10
no = no / 10
duplicated := false
for j := 0; j < idx; j++ {
if rst[j] == n {
// 겹쳐서 다시 뽑아준다.
duplicated = true
break
}
}
if duplicated {
fmt.Println("숫자가 겹치지 않아야 합니다.")
success = false
break
}
if idx >= 3 {
fmt.Println("3개 보다 많은 숫자를 입력하셨습니다.")
success = false
break
}
rst[idx] = n
idx++
}
if success && idx < 3 {
fmt.Println("3개의 숫자를 입력하세요.")
success = false
}
if !success {
continue
}
break
}
rst[0], rst[2] = rst[2], rst[0]
fmt.Println(rst)
return rst
}
이 후 저장 후에 실행하면 3개 보다 더 썼을 때, 겹치는 것이 있을 때, 2개의 숫자만 받았을 때 모두 처리되는 것을 확인할 수 있습니다.
이제 CompareNumbers()부분으로 넘어가서 두 개의 숫자를 비교하여 스트라이크와 볼이 몇 개 인지 반환하는 함수를 만들어보죠!
방법이야 여러 가지가 있겠지만 3 2 7 이라는 숫자가 있고, 6 2 4 라는 숫자를 비교하려 할 때 for문을 돌면서 6부터 시작해서 3, 2, 7을 비교 해보고 아무것도 없으니 0, 그 다음 2가 되서 3, 2, 7을 비교해서 자리와 숫자가 같으므로 1스트라이크, 그 다음 4가 되서 3 2 7을 비교해보고 아무것도 없으니 0 이런식으로 돌아가도록 만들어 봅시다.
func CompareNumbers(numbers, intputNumbers [3]int) bool {
// 두 개의 숫자 3개를 비교해서 결과를 반환한다.
strikes := 0
balls := 0
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if numbers[i] == inputNumbers[j] {
if i == j {
strikes++
} else {
balls++
}
break
}
}
}
이렇게 한 뒤에 strikes와 balls를 저장해서 내보낼 객체가 필요하기 때문에 struct를 하나 정의시켜 줍니다.
package main
import (
"fmt"
"math/rand"
"time"
)
type Result struct {
strikes int
balls int
}
func CompareNumbers(numbers, inputNumbers [3]int) Result {
// 두 개의 숫자 3개를 비교해서 결과를 반환한다.
strikes := 0
balls := 0
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if numbers[i] == inputNumbers[j] {
if i == j {
strikes++
} else {
balls++
}
break
}
}
}
return Result{strikes, balls}
}
이렇게 맨 위에 struct를 정의 시켜준 뒤 bool형이 아닌 만든 struct를 반환하도록 바꾸어 줍니다.
그 다음 func PrintResult()로 넘어가서 bool형이 아닌 Result가 들어가게 하고, 스트라이크와 볼이 몇 개인지 출력 시켜 줍니다.
func PrintResult(result Result) {
fmt.Printf("%dS %dB : \n", result.strikes, result.balls)
}
그 다음 func IsGameEnd()도 마찬가지로 bool형이 아닌 Result타입을 받아서 result의 strikes가 3과 같으면 끝나는걸로 처리 해줍니다.
func IsGameEnd(result Result) bool {
// 비교 결과가 3S 인지 확인
return result.strikes == 3
}
이제 결과를 확인해보죠!
이제 컴퓨터가 선택한 숫자만 출력되지 않게 하면 완성입니다.
func MakeNumbers() [3]int {
// 0~9사이의 겹치지 않는 무작위 숫자 3개를 반환한다.
var rst [3]int
for i := 0; i < 3; i++ {
for {
n := rand.Intn(10)
duplicated := false
for j := 0; j < i; j++ {
if rst[j] == n {
// 겹쳐서 다시 뽑아준다.
duplicated = true
break
}
}
if !duplicated {
rst[i] = n
break
}
}
}
// fmt.Println(rst)
return rst
}
이렇게 수정해준 뒤 다시 실행 시켜봅시다!
풀소스
package main
import (
"fmt"
"math/rand"
"time"
)
type Result struct {
strikes int
balls int
}
func main() {
// 무작위 숫자 3개를 만든다.
rand.Seed(time.Now().UnixNano())
numbers := MakeNumbers()
cnt := 0
for {
cnt++
// 사용자의 입력을 받는다.
inputNumbers := InputNumbers()
// 결과를 비교한다.
result := CompareNumbers(numbers, inputNumbers)
PrintResult(result)
// 게임이 3S인가?
if IsGameEnd(result) {
// 게임 끝
break
}
}
fmt.Printf("%d번만에 맞췄습니다.\n", cnt)
}
func MakeNumbers() [3]int {
// 0~9사이의 겹치지 않는 무작위 숫자 3개를 반환한다.
var rst [3]int
for i := 0; i < 3; i++ {
for {
n := rand.Intn(10)
duplicated := false
for j := 0; j < i; j++ {
if rst[j] == n {
// 겹쳐서 다시 뽑아준다.
duplicated = true
break
}
}
if !duplicated {
rst[i] = n
break
}
}
}
// fmt.Println(rst)
return rst
}
func InputNumbers() [3]int {
// 키보드로부터 0~9사이의 겹치지 않는 숫자 3개를 입력받아 반환한다.
var rst [3]int
for {
fmt.Println("겹치지 않는 0~9사이의 숫자 3개를 입력하세요.")
var no int
_, err := fmt.Scanf("%d\n", &no)
if err != nil {
fmt.Println("잘못 입력 했습니다.")
continue
}
success := true
idx := 0
for no > 0 {
n := no % 10
no = no / 10
duplicated := false
for j := 0; j < idx; j++ {
if rst[j] == n {
// 겹쳐서 다시 뽑아준다.
duplicated = true
break
}
}
if duplicated {
fmt.Println("숫자가 겹치지 않아야 합니다.")
success = false
break
}
if idx >= 3 {
fmt.Println("3개 보다 많은 숫자를 입력하셨습니다.")
success = false
break
}
rst[idx] = n
idx++
}
if success && idx < 3 {
fmt.Println("3개의 숫자를 입력하세요.")
success = false
}
if !success {
continue
}
break
}
rst[0], rst[2] = rst[2], rst[0]
fmt.Println(rst)
return rst
}
func CompareNumbers(numbers, inputNumbers [3]int) Result {
// 두 개의 숫자 3개를 비교해서 결과를 반환한다.
strikes := 0
balls := 0
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if numbers[i] == inputNumbers[j] {
if i == j {
strikes++
} else {
balls++
}
break
}
}
}
return Result{strikes, balls}
}
func PrintResult(result Result) {
fmt.Printf("%dS %dB : \n", result.strikes, result.balls)
}
func IsGameEnd(result Result) bool {
// 비교 결과가 3S 인지 확인
return result.strikes == 3
}
'프로그래밍(Basic) > Golang' 카테고리의 다른 글
[바미] Go - Slice에 대해 알아보자! (0) | 2020.12.29 |
---|---|
[바미] Go - Garbage Collector에 대해 알아보자! (0) | 2020.12.22 |
[바미] Go - 숫자야구를 만들어보자! (1) (2) | 2020.12.22 |
[바미] Go - 포인터에 대해 알아보자! (0) | 2020.12.22 |
[바미] Go - 구조체에 대해 알아보자! (0) | 2020.12.21 |