snakesimulator.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package snakesimulator
  2. import (
  3. fmt "fmt"
  4. "math/rand"
  5. "net"
  6. "time"
  7. grpc "google.golang.org/grpc"
  8. )
  9. type SnakeSimulator struct {
  10. field *Field
  11. snake *Snake
  12. fieldUpdateQueue chan bool
  13. snakeUpdateQueue chan bool
  14. }
  15. func NewSnakeSimulator() (s *SnakeSimulator) {
  16. s = &SnakeSimulator{
  17. field: &Field{
  18. Food: &Point{},
  19. Width: 40,
  20. Height: 40,
  21. },
  22. snake: &Snake{
  23. Points: []*Point{
  24. &Point{X: 20, Y: 20},
  25. &Point{X: 21, Y: 20},
  26. &Point{X: 22, Y: 20},
  27. },
  28. },
  29. fieldUpdateQueue: make(chan bool, 2),
  30. snakeUpdateQueue: make(chan bool, 2),
  31. }
  32. return
  33. }
  34. func (s *SnakeSimulator) Run() {
  35. go func() {
  36. grpcServer := grpc.NewServer()
  37. RegisterSnakeSimulatorServer(grpcServer, s)
  38. lis, err := net.Listen("tcp", "localhost:65002")
  39. if err != nil {
  40. fmt.Printf("Failed to listen: %v\n", err)
  41. }
  42. fmt.Printf("Listen SnakeSimulator localhost:65002\n")
  43. if err := grpcServer.Serve(lis); err != nil {
  44. fmt.Printf("Failed to serve: %v\n", err)
  45. }
  46. }()
  47. s.field.GenerateNextFood()
  48. for true {
  49. direction := rand.Int31()%4 + 1
  50. newHead := s.snake.NewHead(Direction(direction))
  51. if newHead.X == s.field.Food.X && newHead.Y == s.field.Food.Y {
  52. s.snake.Feed(newHead)
  53. s.field.GenerateNextFood()
  54. s.fieldUpdateQueue <- true
  55. } else if newHead.X >= s.field.Width || newHead.Y >= s.field.Height {
  56. fmt.Printf("Game over\n")
  57. break
  58. } else if selfCollisionIndex := s.snake.SelfCollision(newHead); selfCollisionIndex > 0 {
  59. if selfCollisionIndex == 1 {
  60. fmt.Printf("Step backward, skip\n")
  61. continue
  62. }
  63. fmt.Printf("Game over self collision\n")
  64. break
  65. } else {
  66. s.snake.Move(newHead)
  67. }
  68. s.snakeUpdateQueue <- true
  69. time.Sleep(50 * time.Millisecond)
  70. }
  71. }
  72. func (s *SnakeSimulator) Field(_ *None, srv SnakeSimulator_FieldServer) error {
  73. ctx := srv.Context()
  74. for {
  75. select {
  76. case <-ctx.Done():
  77. return ctx.Err()
  78. default:
  79. }
  80. srv.Send(s.field)
  81. <-s.fieldUpdateQueue
  82. }
  83. }
  84. func (s *SnakeSimulator) Snake(_ *None, srv SnakeSimulator_SnakeServer) error {
  85. ctx := srv.Context()
  86. for {
  87. select {
  88. case <-ctx.Done():
  89. return ctx.Err()
  90. default:
  91. }
  92. srv.Send(s.snake)
  93. <-s.snakeUpdateQueue
  94. }
  95. }