学了一段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, scissors, 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}, {[2]int{rock, scissors}, win}, {[2]int{scissors, rock}, lose}, {[2]int{scissors, paper}, win}, {[2]int{paper, scissors}, lose}, {[2]int{scissors, scissors}, 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, except %v, result %v", cs, except, 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, rock}, win},
{[2]int{rock, paper}, lose},
{[2]int{rock, scissors}, win},
{[2]int{scissors, rock}, lose},
{[2]int{scissors, paper}, win},
{[2]int{paper, scissors}, lose},
{{scissors, scissors}, draw}, //原来设想[2]int是可以省略,但是在这里会造语义分析失败,从而丢失cs的数据
}
一些疑问
import分开的话(即中间有空行的话),fmt是不会将之顺序对调,不知道会不会对import产生影响
import ( "bufio" // 输入输出 "os" "fmt" "strconv" "math" "math/rand" "time" )
不分开的话,会是这样
import ( "bufio" // 输入输出 "fmt" "math" "math/rand" "os" "strconv" "time" )
有疑问加站长微信联系(非本文作者)