学了一段golang,觉得应该实践一下,写了这个猜拳小游戏,顺带着学习下go testing。
主程序源码:
package main import ( "bufio" // 输入输出 "fmt" "math" "math/rand" "os" "strconv" "time" ) //rock,paper,scissors const ( rock int = 1 scissors int = 2 paper int = 3 rockName string = "石头" scissorsName string = "剪刀" paperName string = "布" win int = 1 lose int = -1 draw int = 0 ) // 拳的结构 type Finger struct { value int name string } func createFinger(n int) (finger Finger) { switch n { case rock: finger.value = rock finger.name = rockName case scissors: finger.value = scissors finger.name = scissorsName case paper: finger.value = paper finger.name = paperName } return } func isAiWin(ai Finger,user Finger) int { result := ai.value - user.value // 如果是石头和布的比较,比较值正负取反 if int(math.Abs(float64(result))) == paper-rock { result = -(result) } if result < 0 { return win } else if result > 0 { return lose } return draw } func randFinger() (finger Finger) { rand := rand.New(rand.NewSource(time.Now().UnixNano())) switch rand.Intn(3) { case 0: finger.value = rock finger.name = rockName case 1: finger.value = scissors finger.name = scissorsName case 2: finger.value = paper finger.name = paperName } return } func main() { var aiFinger,userFinger Finger reader := bufio.NewReader(os.Stdin) fmt.Printf("请输入你要出的拳:%d->石头,%d->剪刀,%d->布,9->退出\n",rock,scissors,paper) for { data,_,err := reader.ReadLine() if err != nil { fmt.Println("程序出错") break } input,err := strconv.Atoi(string(data)) if err != nil { fmt.Println("格式不对,请输入数字:",input) continue } if input == 9 { break } switch input { case rock,paper: aiFinger = randFinger() fmt.Println("电脑出拳为: ",aiFinger.name) userFinger = createFinger(input) fmt.Println("你出拳为: ",userFinger.name) aiWin := isAiWin(aiFinger,userFinger) if aiWin == win { fmt.Println("你输了,继续输入:") } else if aiWin == lose { fmt.Println("你赢了,继续输入:") } else { fmt.Println("平局,继续输入:") } default: fmt.Println("输入不合要求,继续输入:") } } }
testing 源码
package main import ( "testing" // 加载test包 ) func TestCreateFinger(t *testing.T) { // 顺带掌握以下struct作为map value的初始化 cases := map[int]Finger{ rock: Finger{rock,rockName},scissors: Finger{scissors,scissorsName},paper: Finger{paper,paperName},6: Finger{},// other } for cs,except := range cases { result := createFinger(cs) if result != except { t.Errorf("case %v,except %v,result %v",cs,except,result) } } } func TestIsAiWin(t *testing.T) { // 顺带掌握以下struct作为array element的初始化 cases := [...]struct { cs [2]int except int }{ {[2]int{paper,rock},win},{[2]int{rock,paper},lose},scissors},{[2]int{scissors,{[2]int{paper,draw},} for i := 0; i < len(cases); i++ { cs := cases[i].cs except := cases[i].except result := isAiWin(createFinger(cs[0]),createFinger(cs[1])) if result != except { t.Errorf("case %v,result) } } }
执行预览
请输入你要出的拳:1->石头,2->剪刀,3->布,9->退出 3 电脑出拳为: 石头 你出拳为: 布 你赢了,继续输入: 2 电脑出拳为: 布 你出拳为: 剪刀 你赢了,继续输入: 1 电脑出拳为: 石头 你出拳为: 石头 平局,继续输入: 1 电脑出拳为: 剪刀 你出拳为: 石头 你赢了,继续输入: 1 电脑出拳为: 布 你出拳为: 石头 你输了,继续输入: 9 exit code 0,process exited normally.
实践过程中,还是发现诸多问题,例如丢失类型是长出现的问题,例如
cases := [...]struct {
cs [2]int
except int
}{
{[2]int{paper,{{scissors,//原来设想[2]int是可以省略,但是在这里会造语义分析失败,从而丢失cs的数据
}
一些疑问
import分开的话(即中间有空行的话),fmt是不会将之顺序对调,不知道会不会对import产生影响
import ( "bufio" // 输入输出 "os" "fmt" "strconv" "math" "math/rand" "time" )
不分开的话,会是这样
import ( "bufio" // 输入输出 "fmt" "math" "math/rand" "os" "strconv" "time" )