Змейка - C#
Формулировка задачи:
Привет всем. Написал змейку, принимаю критику по коду и оптимизации:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Snake { public partial class Form1 : Form { Graphics g; // графическая поверхность List<Rectangle> snake = new List<Rectangle>(); // змейка public enum Course {UP, DOWN, LEFT, RIGHT }; public int lengthSnake; // длина змейки public bool existsFood; // существование еды на поле Rectangle food = new Rectangle(); // поле с едой List<Rectangle> empty_filed = new List<Rectangle>(); // список незанятых ячеек public Random rnd = new Random(); public Course course; // направление движения public int addX, addY; // смещение координат public Form1() { InitializeComponent(); course = Course.LEFT; // начальное направление // добавляем в змейку три начальных сегмента snake.Add(new Rectangle(200, 0, 20, 20)); snake.Add(new Rectangle(220, 0, 20, 20)); snake.Add(new Rectangle(240, 0, 20, 20)); timer1.Interval = 200; // устанавливаем таймер lengthSnake = 3; // начальная длина змейки existsFood = false; // еды нет g = this.CreateGraphics();// создаем графичскую поверхность DrawSnake(); // рисуем змейку DrawFood(); // рисуем еду timer1.Enabled = true; // запускаем таймер } // Form1 private void Form1_TickTimer(object sender, EventArgs e) { Refresh(); // очищаем экран timer1.Enabled = false; // останавливаем таймер // в зависимости от выбранного направления // наращиваем координаты головы (snake[0]) if (course == Course.UP) { addX = 0; addY = -20; } if (course == Course.DOWN) { addX = 0; addY = 20; } if (course == Course.LEFT) { addX = -20; addY = 0; } if (course == Course.RIGHT) { addX = 20; addY = 0; } Rectangle prev_segment; Rectangle next_segment; prev_segment = snake[0]; // запоминаем значение старой головы // чтобы присвоить его след. сегменту // по циклу присваиваем значение предыдущего сегмента следующему for (int i = 0; i < snake.Count - 1; i++) { if (i == 0) { snake[i] = new Rectangle( snake[i].X + addX, snake[i].Y + addY, 20, 20); } if (!(snake[i + 1].IsEmpty)) { next_segment = snake[i + 1]; snake[i + 1] = prev_segment; prev_segment = next_segment; } } // если голова "съела" еду if (snake[0] == food) { snake.Add(food); // добавляем сегмент с коор-ами еды // этот сегмент пройдет через всю змейку // и "прицепиться" в конце lengthSnake++; // увеличиваем длину змейки existsFood = false; // еды нет // увеличиваем скорость через каждые 7 сегментов змейки if ((lengthSnake % 7 == 0) && (timer1.Interval > 50) ) { timer1.Interval -= 30; } } // Проверка на проигрыш if (// выход за границу игрового поля (snake[0].X < 0 || snake[0].X > 240 || snake[0].Y < 0 || snake[0].Y > 240) || // проверка на самосъедение EatMySelf()) { MessageBox.Show("Игра закончена\n Длина змейки равна: " + lengthSnake.ToString()); this.Close(); return; } DrawSnake(); // рисуем змейку DrawFood(); // рисуем еду timer1.Enabled = true; // запускаем таймер } // Form1_TickTimer // метод меняет направление, в зависимости от нажатой стрелки private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Up && course != Course.DOWN) { course = Course.UP; } if (e.KeyCode == Keys.Down && course != Course.UP) { course = Course.DOWN; } if (e.KeyCode == Keys.Left && course != Course.RIGHT) { course = Course.LEFT; } if (e.KeyCode == Keys.Right && course != Course.LEFT) { course = Course.RIGHT; } } // Form1_KeyDown private void DrawSnake() { for (int i = 0; i < snake.Count; i++) { if (i == 0) // рисуем голову g.FillRectangle(Brushes.Green, snake[i]); else // рисуем оставшиеся сегменты g.FillRectangle(Brushes.Black, snake[i]); g.DrawRectangle(Pens.Green, snake[i]); } } //DrawSnake private void DrawFood() { // если еда съедена - русуем новую if (!existsFood) { for (int i = 0; i < 13; i++) { for (int j = 0; j < 13; j++) { Rectangle temp = new Rectangle(i * 20, j * 20, 20, 20); // заполняем список свободных сегментов игрового поля if (snake.IndexOf(temp) == -1) { empty_filed.Add(temp); } } } // находим случайным образом свободную ячейку food = empty_filed[rnd.Next(0, empty_filed.Count - 1)]; empty_filed.Clear(); // очищаем список свободных сегментов игрового поля g.FillRectangle(Brushes.Red, food); // рисуем еду existsFood = true; //еда есть } else { // иначе рисуем старую еду g.FillRectangle(Brushes.Red, food); } } // проверка на самосъедение private bool EatMySelf() { int count = 0; // количество сегментов равных голове foreach (Rectangle t in snake) { if (t == snake[0]) count++; } // еда совпадает с координатами головы (это не считаем за самосъедение) if (count > 1 && food != snake[0]) return true; else return false; } // EatMySelf } }
Решение задачи: «Змейка»
textual
Листинг программы
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace Snake { public partial class Form1 : Form { Bitmap view; Graphics g; // графическая поверхность List<Rectangle> snake = new List<Rectangle>(); // змейка public enum Course {UP, DOWN, LEFT, RIGHT }; public int lengthSnake; // длина змейки public bool existsFood; // существование еды на поле Rectangle food = new Rectangle(); // поле с едой List<Rectangle> empty_filed = new List<Rectangle>(); // список незанятых ячеек public Random rnd = new Random(); public Course course; // направление движения public int addX, addY; // смещение координат public Form1() { InitializeComponent(); course = Course.LEFT; // начальное направление // добавляем в змейку три начальных сегмента snake.Add(new Rectangle(200, 0, 20, 20)); snake.Add(new Rectangle(220, 0, 20, 20)); snake.Add(new Rectangle(240, 0, 20, 20)); timer1.Interval = 200; // устанавливаем таймер lengthSnake = 3; // начальная длина змейки existsFood = false; // еды нет g = this.CreateGraphics();// создаем графичскую поверхность DrawSnake(); // рисуем змейку DrawFood(); // рисуем еду timer1.Enabled = true; // запускаем таймер } // Form1 private void Form1_TickTimer(object sender, EventArgs e) { //Refresh(); // очищаем экран g.Clear(this.BackColor); timer1.Enabled = false; // останавливаем таймер // в зависимости от выбранного направления // наращиваем координаты головы (snake[0]) if (course == Course.UP) { addX = 0; addY = -20; } if (course == Course.DOWN) { addX = 0; addY = 20; } if (course == Course.LEFT) { addX = -20; addY = 0; } if (course == Course.RIGHT) { addX = 20; addY = 0; } Rectangle prev_segment; Rectangle next_segment; prev_segment = snake[0]; // запоминаем значение старой головы // чтобы присвоить его след. сегменту // по циклу присваиваем значение предыдущего сегмента следующему for (int i = 0; i < snake.Count - 1; i++) { if (i == 0) { snake[i] = new Rectangle( snake[i].X + addX, snake[i].Y + addY, 20, 20); } if (!(snake[i + 1].IsEmpty)) { next_segment = snake[i + 1]; snake[i + 1] = prev_segment; prev_segment = next_segment; } } // если голова "съела" еду if (snake[0] == food) { snake.Add(food); // добавляем сегмент с коор-ами еды // этот сегмент пройдет через всю змейку // и "прицепиться" в конце lengthSnake++; // увеличиваем длину змейки existsFood = false; // еды нет // увеличиваем скорость через каждые 7 сегментов змейки if ((lengthSnake % 7 == 0) && (timer1.Interval > 50) ) { timer1.Interval -= 30; } } // Проверка на проигрыш if (// выход за границу игрового поля (snake[0].X < 0 || snake[0].X > 240 || snake[0].Y < 0 || snake[0].Y > 240) || // проверка на самосъедение EatMySelf()) { MessageBox.Show("Игра закончена\n Длина змейки равна: " + lengthSnake.ToString()); this.Close(); return; } DrawSnake(); // рисуем змейку DrawFood(); // рисуем еду pictureBox1.Image = (Image)view; timer1.Enabled = true; // запускаем таймер } // Form1_TickTimer // метод меняет направление, в зависимости от нажатой стрелки private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Up && course != Course.DOWN) { course = Course.UP; } if (e.KeyCode == Keys.Down && course != Course.UP) { course = Course.DOWN; } if (e.KeyCode == Keys.Left && course != Course.RIGHT) { course = Course.LEFT; } if (e.KeyCode == Keys.Right && course != Course.LEFT) { course = Course.RIGHT; } } // Form1_KeyDown private void DrawSnake() { for (int i = 0; i < snake.Count; i++) { if (i == 0) // рисуем голову g.FillRectangle(Brushes.Green, snake[i]); else // рисуем оставшиеся сегменты g.FillRectangle(Brushes.Black, snake[i]); g.DrawRectangle(Pens.Green, snake[i]); } } //DrawSnake private void DrawFood() { // если еда съедена - русуем новую if (!existsFood) { for (int i = 0; i < 13; i++) { for (int j = 0; j < 13; j++) { Rectangle temp = new Rectangle(i * 20, j * 20, 20, 20); // заполняем список свободных сегментов игрового поля if (snake.IndexOf(temp) == -1) { empty_filed.Add(temp); } } } // находим случайным образом свободную ячейку food = empty_filed[rnd.Next(0, empty_filed.Count - 1)]; empty_filed.Clear(); // очищаем список свободных сегментов игрового поля g.FillRectangle(Brushes.Red, food); // рисуем еду existsFood = true; //еда есть } else { // иначе рисуем старую еду g.FillRectangle(Brushes.Red, food); } } // проверка на самосъедение private bool EatMySelf() { int count = 0; // количество сегментов равных голове foreach (Rectangle t in snake) { if (t == snake[0]) count++; } // еда совпадает с координатами головы (это не считаем за самосъедение) if (count > 1 && food != snake[0]) return true; else return false; } // EatMySelf private void Form1_Shown(object sender, EventArgs e) { view = new Bitmap(270, 270); // инициализируем второй буфер g = Graphics.FromImage((Image)view); // и графику для него } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д