/* * MIT License * * Copyright (c) 2019 Alexey Edelev * * This file is part of NeuralNetwork project https://git.semlanik.org/semlanik/NeuralNetwork * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and * to permit persons to whom the Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be included in all copies * or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ package snakesimulator func (p Point) Copy() (pCopy *Point) { pCopy = &Point{ X: p.X, Y: p.Y, } return } func NewSnake(direction Direction, field Field) (s *Snake) { fieldCenterX := field.Width / 2 fieldCenterY := field.Height / 2 switch direction { case Direction_Left: s = &Snake{ Points: []*Point{ &Point{X: fieldCenterX - 1, Y: fieldCenterY}, &Point{X: fieldCenterX, Y: fieldCenterY}, &Point{X: fieldCenterX + 1, Y: fieldCenterY}, }, } case Direction_Right: s = &Snake{ Points: []*Point{ &Point{X: fieldCenterX + 1, Y: fieldCenterY}, &Point{X: fieldCenterX, Y: fieldCenterY}, &Point{X: fieldCenterX - 1, Y: fieldCenterY}, }, } case Direction_Down: s = &Snake{ Points: []*Point{ &Point{X: fieldCenterX, Y: fieldCenterY - 1}, &Point{X: fieldCenterX, Y: fieldCenterY}, &Point{X: fieldCenterX, Y: fieldCenterY + 1}, }, } default: s = &Snake{ Points: []*Point{ &Point{X: fieldCenterX, Y: fieldCenterY + 1}, &Point{X: fieldCenterX, Y: fieldCenterY}, &Point{X: fieldCenterX, Y: fieldCenterY - 1}, }, } } return } func (s *Snake) NewHead(direction Direction) (newHead *Point) { newHead = s.Points[0].Copy() switch direction { case Direction_Up: newHead.Y -= 1 case Direction_Down: newHead.Y += 1 case Direction_Right: newHead.X += 1 case Direction_Left: newHead.X -= 1 } return } func (s *Snake) Move(newHead *Point) { s.Points = s.Points[:len(s.Points)-1] s.Points = append([]*Point{newHead}, s.Points...) } func (s *Snake) Feed(food *Point) { s.Points = append([]*Point{food}, s.Points...) } func (s *Snake) selfCollision(head *Point, direction Direction) bool { selfCollisionIndex := -1 for index, point := range s.Points[:len(s.Points)-1] { if point.X == head.X && point.Y == head.Y { selfCollisionIndex = index break } } if selfCollisionIndex == 1 { switch direction { case Direction_Up: head.Y += 2 case Direction_Down: head.Y -= 2 case Direction_Left: head.X += 2 default: head.X -= 2 } return false } return selfCollisionIndex >= 0 } func wallCollision(head *Point, field Field) bool { return head.X >= field.Width || head.Y >= field.Height || head.X < 0 || head.Y < 0 } func foodCollision(head *Point, food *Point) bool { return head.X == food.X && head.Y == food.Y }