I'm learning Go and as an initial project, I'm trying the Learntris challenge.
Here you must take input separated by a newline from stdin. I've been reading about readers vs scanners and how scanners are the appropriate level of abstraction for most things.
Here I'm using a scanner to check for single character commands and on the command 'g' I need to read 22 lines separated by ' '. I think the way I'm treating the scanner might be wrong as I keep receiving empty arrays. my code can be seen here:
package main
import (
"fmt"
"bufio"
"os"
"learntris/internal/pkg/matrix"
)
func main() {
board := matrix.Create_mat()
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
text := scanner.Text()
char := text[0]
switch {
case char == 'q':
//quit
os.Exit(3)
case char == 'p':
//print the state of the matrix
matrix.Print_mat(board)
case char == 'g':
given(&board)
matrix.Print_mat(board)
default:
//still quit
fmt.Println("case not hit")
os.Exit(3)
}
}
}
func given(board *([][]rune)) {
scanner := bufio.NewScanner(os.Stdin)
i := 0
for scanner.Scan() {
if i == 21 { break} //only read 22 lines
fmt.Println(scanner.Text())
//will modify board here once scanner is sorted out
i++
}
}
updated given function:
func given(board *([][]rune)) {
//fmt.Println("got to given")
//expecting 22 lines of 10 items separated by spaces
scanner := bufio.NewScanner(os.Stdin)
i := 0 //my iterator for num lines(rows)
for scanner.Scan() {
//fmt.Println("scanning")
text := scanner.Text()
if len(text) >= 10{
//fmt.Println(text)
//need to split and throw away spaces
split_line := strings.Split(text, " ")
for j, j_str := range(split_line){
(*board)[i][j] = rune(j_str[0])
}
i++
}
if i == 22 {break} //stop at 22 lines
}
}
This can take an input like this:
g
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
m m m m m m m m m m
b b b b b b b b b b
c c c c c c c c c c
g g g g g g g g g g
y y y y y y y y y y
o o o o o o o o o o
r r r r r r r r r r
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
c . . . . . . . . .
c . . . . . . . . .
c . . . . g . . . .
c . . o . g g . . .
. . . o . b g . . .
. m r r o o b y y .
m m m r r b b y y .
p
q
passed via standard in. When copy and pasted into the programs input manually, it works fine but when the same text is given via ./learntris < input.txt, it will land in the default in the switch case and never take in the matrix via given.
I think the issue lies in the difference between manual input and streaming over stdin but I'm not sure what I should change.
Final edit:
func given(board *([][]rune), scanner *bufio.Scanner) {
//expecting 22 lines of 10 items separated by spaces
i := 0 //my iterator for num lines(rows)
for scanner.Scan() {
text := scanner.Text()
if len(text) >= 10{
//fmt.Println(text)
//need to split and throw away spaces
split_line := strings.Split(text, " ")
for j, j_str := range(split_line){
(*board)[i][j] = rune(j_str[0])
}
i++
}
if i == 22 {break} //stop at 22 lines
}
if scanner.Err() != nil{
fmt.Println(scanner.Err())
}
}
by passing the scanner into the function, the scanner no longer lost its intended place and didn't try to consume the matrix as the next command.