Змея что это за программа

Как сделать игру «Змейка» на Python

Помните аркадную игру «Змейка», в которую когда-то играли на неубиваемой нокии? Оказывается, что написать классическую «змейку» сможет каждый новичок. О том, как сделать змейку на Python и накормить ее яблоками, расскажет Настя Мартынова — веб-писатель REG.RU.

Змейка (Snake) — это игра, созданная Танели Арманто в 1997 году специально для телефона Nokia. Змейка стала переломным моментом в развитии мобильного гейминга и завоевала сердца миллионов людей. Несмотря на свою примитивность, даже спустя 25 лет эта игра остается популярной.

Хоть Танели Арманто и считается создателем змейки, идея игры ему не принадлежит. Первый вариант змейки появился аж в 1976 году и назывался Blockade. После были созданы десятки клонов этой игры с разными названиями. Арманто при создании игры вдохновился одним из таких клонов, который был установлен на его Apple Macintosh.

А мы вдохновились Танели Арманто и решили рассказать, как сделать игру змейка самостоятельно! С этим справятся даже те, кто только недавно начал изучать программирование.

Случаи, когда змеи забрались в дома!

Для создания змейки можно использовать разные языки программирования. Мы будем использовать… питон ! Язык программирования Python универсален: он подходит как для решения повседневных задач, так и для создания простых игр.

Змейку на Python можно написать несколькими способами. Первый — при помощи библиотеки Python PyGame, которую используют для создания игр. Второй — с помощью встроенной библиотеки Turtle. В статье мы опишем второй способ.

Помимо Turtle, мы будем использовать два других модуля:

  1. Time — для добавления задержки в выполнении программы.
  2. Random — для генерации случайного числа/цвета/формы.

Какие инструменты нам понадобятся:

  • редактор исходного кода на ваш выбор. Можно воспользоваться редактором VSCode или средой разработки PyCharm;
  • установленный Python 3.

Как работает игра «Змейка»

Игрок управляет змейкой при помощи кнопок направления — вверх, вниз, влево, вправо. Ползая, змейка должна собирать еду, за которую начисляются очки. Цель игры — набрать как можно больше очков. Игра заканчивается, если змейка врезается в стену или в себя.

Для написания игры мы проделаем следующие шаги:

  • импортируем модули в программу,
  • создадим экран игры с помощью модуля Turtle,
  • зададим кнопки направления движения змеи,
  • реализуем игровой процесс.

Прежде всего создайте файл snakegame.py в вашем редакторе кода. А затем приступайте к созданию змейки по нашей инструкции.

Импортируем модули

В этой части кода мы импортируем 3 модуля — turtle, time и random. Помимо этого, мы зададим значения по умолчанию:

  • начальный счет — score,
  • наибольший счет — high score,
  • время задержки — delay.

Добавим в Python строки кода:

Источник: www.reg.ru

Все о змеях | Film Studio Aves

Игра «Змейка» на Python c использованием модуля Pygame

Игра «Змейка» на Python c использованием модуля Pygame

Змейка — одна из самых популярных аркадных игр всех времен. В этой игре основная цель игрока – поймать максимальное количество фруктов, не ударившись о стену или себя. Создание игры может стать проблемой при изучении Python или Pygame. Это один из лучших проектов для начинающих, который каждый начинающий программист должен принять как вызов. Научиться создавать видеоигры довольно интересно и весело.

Мы будем использовать Pygame для создания этой игры . Pygame — это библиотека с открытым исходным кодом, предназначенная для создания видеоигр. Она имеет встроенные графические и звуковые библиотеки.

Установка
Чтобы установить Pygame, вам нужно открыть терминал или командную строку и ввести следующую команду:

pip install pygame

Шаг 1: Сначала мы импортируем необходимые библиотеки.

После этого мы определяем ширину и высоту окна, в котором будет проходить игра.
И определим цвет в формате RGB, который мы будем использовать в нашей игре для отображения текста.

# importing libraries import pygame import time import random snake_speed = 15 # Window size window_x = 720 window_y = 480 # defining colors black = pygame.Color(0, 0, 0) white = pygame.Color(255, 255, 255) red = pygame.Color(255, 0, 0) green = pygame.Color(0, 255, 0) blue = pygame.Color(0, 0, 255)

Шаг 2: После импорта библиотек нам нужно инициализировать Pygame с помощью метода pygame.init().

Создадим игровое окно, используя ширину и высоту, определенные на предыдущем шаге.
Здесь pygame.time.Clock() будет использоваться дальше в основной логике игры для изменения скорости змейки.

# Initialising pygame pygame.init() # Initialise game window pygame.display.set_caption(‘GeeksforGeeks Snakes’) game_window = pygame.display.set_mode((window_x, window_y)) # FPS (frames per second) controller fps = pygame.time.Clock()

Шаг 3: Инициализируем положение змейки и ее размер.

После инициализации положения змейки инициализируем положение фруктов случайным образом в любом месте заданной высоты и ширины.
Установив направление ВПРАВО, мы гарантируем, что всякий раз, когда пользователь запускает программу/игру, змейка должна двигаться вправо к экрану.

# defining snake default position snake_position = [100, 50] # defining first 4 blocks of snake # body snake_body = [ [100, 50], [90, 50], [80, 50], [70, 50] ] # fruit position fruit_position = [random.randrange(1, (window_x//10)) * 10, random.randrange(1, (window_y//10)) * 10] fruit_spawn = True # setting default snake direction # towards right direction = ‘RIGHT’ change_to = direction

Шаг 4: Создадим функцию для отображения счета игрока.

В этой функции, во-первых, мы создаем объект шрифта.
Затем мы используем рендеринг для создания фоновой поверхности, которую мы будем менять при каждом обновлении нашей игры.
Создадим прямоугольный объект для объекта текстовой поверхности (где текст будет обновляться)
Затем мы отобразим счет, используя blit. blit , который принимает два аргумента screen.blit(background,(x,y))

# initial score score = 0 # displaying Score function def show_score(choice, color, font, size): # creating font object score_font score_font = pygame.font.SysFont(font, size) # create the display surface object # score_surface score_surface = score_font.render(‘Score : ‘ + str(score), True, color) # create a rectangular object for the # text surface object score_rect = score_surface.get_rect() # displaying text game_window.blit(score_surface, score_rect)

Шаг 5: Теперь создадим функцию завершения игры, которая будет отображать счет после того, как змейка ударится о стену или о саму себя.

В первой строке мы создаем объект шрифта для отображения результатов.
Затем мы создадим текстовые поверхности для рендеринга партитуры.
После этого мы устанавим положение текста в середине игровой области.
Отобразим результаты с помощью blit и обновите счет, обновив поверхность с помощью flip().
Мы используем sleep(2), чтобы подождать 2 секунды, прежде чем закрыть окно с помощью quit().

# game over function def game_over(): # creating font object my_font my_font = pygame.font.SysFont(‘times new roman’, 50) # creating a text surface on which text # will be drawn game_over_surface = my_font.render(‘Your Score is : ‘ + str(score), True, red) # create a rectangular object for the text # surface object game_over_rect = game_over_surface.get_rect() # setting position of the text game_over_rect.midtop = (window_x/2, window_y/4) # blit will draw the text on screen game_window.blit(game_over_surface, game_over_rect) pygame.display.flip() # after 2 seconds we will quit the # program time.sleep(2) # deactivating pygame library pygame.quit() # quit the program quit()

Шаг 6: Теперь мы создадим нашу основную функцию, которая будет делать следующие вещи:

Мы будем проверять ключи, которые будут отвечать за движение змейки, а затем создадим специальное условие, при котором змея не должна двигаться в противоположном направлении мгновенно.
После этого, если змейка и фрукт столкнутся, мы увеличим счет на 10, и новый фрукт будет инициализоравн.
После этого проверяем, ударилась змейка о стену или нет. Если змейка ударится о стену, мы вызовем функцию Game Over.
Если змейка ударит себя так же будет вызвана функция окончания Game Over.
И, наконец, мы будем отображать результаты с помощью созданной ранее функции show_score.

# Main Function while True: # handling key events for event in pygame.event.get(): if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: change_to = ‘UP’ if event.key == pygame.K_DOWN: change_to = ‘DOWN’ if event.key == pygame.K_LEFT: change_to = ‘LEFT’ if event.key == pygame.K_RIGHT: change_to = ‘RIGHT’ # If two keys pressed simultaneously # we don’t want snake to move into two directions # simultaneously if change_to == ‘UP’ and direction != ‘DOWN’: direction = ‘UP’ if change_to == ‘DOWN’ and direction != ‘UP’: direction = ‘DOWN’ if change_to == ‘LEFT’ and direction != ‘RIGHT’: direction = ‘LEFT’ if change_to == ‘RIGHT’ and direction != ‘LEFT’: direction = ‘RIGHT’ # Moving the snake if direction == ‘UP’: snake_position[1] -= 10 if direction == ‘DOWN’: snake_position[1] += 10 if direction == ‘LEFT’: snake_position[0] -= 10 if direction == ‘RIGHT’: snake_position[0] += 10 # Snake body growing mechanism # if fruits and snakes collide then scores will be # incremented by 10 snake_body.insert(0, list(snake_position)) if snake_position[0] == fruit_position[0] and snake_position[1] == fruit_position[1]: score += 10 fruit_spawn = False else: snake_body.pop() if not fruit_spawn: fruit_position = [random.randrange(1, (window_x//10)) * 10, random.randrange(1, (window_y//10)) * 10] fruit_spawn = True game_window.fill(black) for pos in snake_body: pygame.draw.rect(game_window, green, pygame.Rect( pos[0], pos[1], 10, 10)) pygame.draw.rect(game_window, white, pygame.Rect( fruit_position[0], fruit_position[1], 10, 10)) # Game Over conditions if snake_position[0] < 0 or snake_position[0] >window_x-10: game_over() if snake_position[1] < 0 or snake_position[1] >window_y-10: game_over() # Touching the snake body for block in snake_body[1:]: if snake_position[0] == block[0] and snake_position[1] == block[1]: game_over() # displaying score countinuously show_score(1, white, ‘times new roman’, 20) # Refresh game screen pygame.display.update() # Frame Per Second /Refresh Rate fps.tick(snake_speed)

Читайте также:
Программа сирена что это

Источник: uproger.com

Своя игра: создаём собственную «Змейку»

Не так давно мы разбирали, как искусственный интеллект учится играть в змейку. А теперь мы сами сделаем такую игру, чтобы ей могли насладиться обычные люди. Что нам понадобится:

  • HTML, чтобы можно было играть прямо в браузере;
  • CSS для украшений;
  • JavaScript для самой игры.

Логика игры

У классической змейки правила простые:

  • есть поле из клеточек, где случайным образом появляется еда;
  • есть змейка, которая всё время двигается и которой мы можем управлять;
  • если змейка на своём пути встречает еду — еда исчезает, появляется в новом месте, а сама змейка удлиняется на одну клеточку;
  • если змейка врежется в стену или в саму себя, игра заканчивается.

Чтобы играть было проще, мы сделаем так, чтобы змейка не врезалась в стенки, а проходила сквозь них. Если что — сможете это сами потом настроить в коде, когда захотите посложнее.

Последовательность наших действий будет такой:

  1. Делаем пустую HTML-страницу.
  2. Настраиваем внешний вид с помощью CSS.
  3. Рисуем игровое поле.
  4. Пишем скрипт, который и будет отвечать за всю игру.

Делаем HTML-страницу

С этим всё просто: берём стандартный код и сохраняем его как файл snake.html .

Змейка

Это даст нам пустую страницу, которую мы сейчас немного настроим стилями.

Настраиваем внешний вид

За внешний вид на странице у нас отвечает раздел , поэтому мы просто добавим в него CSS-код:

html, body < height: 100%; margin: 0; >/*Задаём глобальные параметры*/ body < background: black; display: flex; align-items: center; justify-content: center; >/*Делаем границу вокруг игрового поля*/ canvas

Теперь у нас на странице нет лишних отступов, зато всё по центру, есть чёрный фон и граница вокруг игрового поля. Самое время создать само игровое поле.

Рисуем игровое поле

Поле делается очень просто:

400 пикселей в ширину, столько же в высоту, название поля — game. Этого достаточно, чтобы браузер отобразил холст с такими размерами и позволил нам на нём рисовать.

Пишем скрипт

1. Зададим все переменные, которые нам понадобятся.

// Поле, на котором всё будет происходить, — тоже как бы переменная var canvas = document.getElementById(‘game’); // Классическая змейка — двухмерная, сделаем такую же var context = canvas.getContext(‘2d’); // Размер одной клеточки на поле — 16 пикселей var grid = 16; // Служебная переменная, которая отвечает за скорость змейки var count = 0; // А вот и сама змейка var snake = < // Начальные координаты x: 160, y: 160, // Скорость змейки — в каждом новом кадре змейка смещается по оси Х или У. На старте будет двигаться горизонтально, поэтому скорость по игреку равна нулю. dx: grid, dy: 0, // Тащим за собой хвост, который пока пустой cells: [], // Стартовая длина змейки — 4 клеточки maxCells: 4 >; // А это — еда. Представим, что это красные яблоки. var apple = < // Начальные координаты яблока x: 320, y: 320 >;

2. Сделаем генератор случайных чисел. Он нам понадобится, чтобы размещать еду на поле случайным образом.

// Делаем генератор случайных чисел в заданном диапазоне

function getRandomInt(min, max) <
return Math.floor(Math.random() * (max — min)) + min;

3. Напишем основной игровой цикл, который будет работать бесконечно.

// Игровой цикл — основной процесс, внутри которого будет всё происходить function loop() < // Дальше будет хитрая функция, которая замедляет скорость игры с 60 кадров в секунду до 15. Для этого она пропускает три кадра из четырёх, то есть срабатывает каждый четвёртый кадр игры.

Было 60 кадров в секунду, станет 15. requestAnimationFrame(loop); // Игровой код выполнится только один раз из четырёх, в этом и суть замедления кадров, а пока переменная count меньше четырёх, код выполняться не будет. if (++count < 4) < return; >// Обнуляем переменную скорости count = 0; // Очищаем игровое поле context.clearRect(0, 0, canvas.width, canvas.height); // Двигаем змейку с нужной скоростью snake.x += snake.dx; snake.y += snake.dy; // Если змейка достигла края поля по горизонтали — продолжаем её движение с противоположной стороны if (snake.x < 0) < snake.x = canvas.width — grid; >else if (snake.x >= canvas.width) < snake.x = 0; >// Делаем то же самое для движения по вертикали if (snake.y < 0) < snake.y = canvas.height — grid; >else if (snake.y >= canvas.height) < snake.y = 0; >// Продолжаем двигаться в выбранном направлении. Голова всегда впереди, поэтому добавляем её координаты в начало массива, который отвечает за всю змейку. snake.cells.unshift(< x: snake.x, y: snake.y >); // Сразу после этого удаляем последний элемент из массива змейки, потому что она движется и постоянно особождает клетки после себя if (snake.cells.length > snake.maxCells) < snake.cells.pop(); >// Рисуем еду — красное яблоко context.fillStyle = ‘red’; context.fillRect(apple.x, apple.y, grid — 1, grid — 1); // Одно движение змейки — один новый нарисованный квадратик context.fillStyle = ‘green’; // Обрабатываем каждый элемент змейки snake.cells.forEach(function (cell, index) < // Чтобы создать эффект клеточек, делаем зелёные квадратики меньше на один пиксель, чтобы вокруг них образовалась чёрная граница context.fillRect(cell.x, cell.y, grid — 1, grid — 1); // Если змейка добралась до яблока. if (cell.x === apple.x cell.y === apple.y) < // увеличиваем длину змейки snake.maxCells++; // Рисуем новое яблочко // Помним, что размер холста у нас 400×400, при этом он разбит на ячейки — 25 в каждую сторону apple.x = getRandomInt(0, 25) * grid; apple.y = getRandomInt(0, 25) * grid; >// Проверяем, не столкнулась ли змея сама с собой // Для этого перебираем весь массив и смотрим, есть ли у нас в массиве змейки две клетки с одинаковыми координатами for (var i = index + 1; i < snake.cells.length; i++) < // Если такие клетки есть — начинаем игру заново if (cell.x === snake.cells[i].x cell.y === snake.cells[i].y) < // Задаём стартовые параметры основным переменным snake.x = 160; snake.y = 160; snake.cells = []; snake.maxCells = 4; snake.dx = grid; snake.dy = 0; // Ставим яблочко в случайное место apple.x = getRandomInt(0, 25) * grid; apple.y = getRandomInt(0, 25) * grid; >> >); >

4. Сделаем управление стрелочками на клавиатуре.

// Смотрим, какие нажимаются клавиши, и реагируем на них нужным образом document.addEventListener(‘keydown’, function (e) < // Дополнительно проверяем такой момент: если змейка движется, например, влево, то ещё одно нажатие влево или вправо ничего не поменяет — змейка продолжит двигаться в ту же сторону, что и раньше. Это сделано для того, чтобы не разворачивать весь массив со змейкой на лету и не усложнять код игры. // Стрелка влево // Если нажата стрелка влево, и при этом змейка никуда не движется по горизонтали… if (e.which === 37 snake.dx === 0) < // то даём ей движение по горизонтали, влево, а вертикальное — останавливаем // Та же самая логика будет и в остальных кнопках snake.dx = -grid; snake.dy = 0; >// Стрелка вверх else if (e.which === 38 snake.dy === 0) < snake.dy = -grid; snake.dx = 0; >// Стрелка вправо else if (e.which === 39 snake.dx === 0) < snake.dx = grid; snake.dy = 0; >// Стрелка вниз else if (e.which === 40 snake.dy === 0) < snake.dy = grid; snake.dx = 0; >>);

Читайте также:
Софт программы что это такое

5. Запускаем игру. Для этого достаточно запустить предыдущий бесконечный цикл, поэтому пишем:

6. Наслаждаемся результатом:

Чтобы у вас тоже получилось такое, просто скопируйте готовый код, сохраните его как HTML-файл и откройте в браузере.

Змейка html, body < height: 100%; margin: 0; >/*Задаём глобальные параметры*/ body < background: black; display: flex; align-items: center; justify-content: center; >/*Делаем границу вокруг игрового поля*/ canvas // Поле, на котором всё будет происходить, — тоже как бы переменная var canvas = document.getElementById(‘game’); // Классическая змейка — двухмерная, сделаем такую же var context = canvas.getContext(‘2d’); // Размер одной клеточки на поле — 16 пикселей var grid = 16; // Служебная переменная, которая отвечает за скорость змейки var count = 0; // А вот и сама змейка var snake = < // Начальные координаты x: 160, y: 160, // Скорость змейки — в каждом новом кадре змейка смещается по оси Х или У. На старте будет двигаться горизонтально, поэтому скорость по игреку равна нулю. dx: grid, dy: 0, // Тащим за собой хвост, который пока пустой cells: [], // Стартовая длина змейки — 4 клеточки maxCells: 4 >; // А это — еда. Представим, что это красные яблоки. var apple = < // Начальные координаты яблока x: 320, y: 320 >; // Делаем генератор случайных чисел в заданном диапазоне function getRandomInt(min, max) < return Math.floor(Math.random() * (max — min)) + min; >// Игровой цикл — основной процесс, внутри которого будет всё происходить function loop() < // Хитрая функция, которая замедляет скорость игры с 60 кадров в секунду до 15 (60/15 = 4) requestAnimationFrame(loop); // Игровой код выполнится только один раз из четырёх, в этом и суть замедления кадров, а пока переменная count меньше четырёх, код выполняться не будет if (++count < 4) < return; >// Обнуляем переменную скорости count = 0; // Очищаем игровое поле context.clearRect(0, 0, canvas.width, canvas.height); // Двигаем змейку с нужной скоростью snake.x += snake.dx; snake.y += snake.dy; // Если змейка достигла края поля по горизонтали — продолжаем её движение с противоположной строны if (snake.x < 0) < snake.x = canvas.width — grid; >else if (snake.x >= canvas.width) < snake.x = 0; >// Делаем то же самое для движения по вертикали if (snake.y < 0) < snake.y = canvas.height — grid; >else if (snake.y >= canvas.height) < snake.y = 0; >// Продолжаем двигаться в выбранном направлении. Голова всегда впереди, поэтому добавляем её координаты в начало массива, который отвечает за всю змейку snake.cells.unshift(< x: snake.x, y: snake.y >); // Сразу после этого удаляем последний элемент из массива змейки, потому что она движется и постоянно освобождает клетки после себя if (snake.cells.length > snake.maxCells) < snake.cells.pop(); >// Рисуем еду — красное яблоко context.fillStyle = ‘red’; context.fillRect(apple.x, apple.y, grid — 1, grid — 1); // Одно движение змейки — один новый нарисованный квадратик context.fillStyle = ‘green’; // Обрабатываем каждый элемент змейки snake.cells.forEach(function (cell, index) < // Чтобы создать эффект клеточек, делаем зелёные квадратики меньше на один пиксель, чтобы вокруг них образовалась чёрная граница context.fillRect(cell.x, cell.y, grid — 1, grid — 1); // Если змейка добралась до яблока. if (cell.x === apple.x cell.y === apple.y) < // увеличиваем длину змейки snake.maxCells++; // Рисуем новое яблочко // Помним, что размер холста у нас 400×400, при этом он разбит на ячейки — 25 в каждую сторону apple.x = getRandomInt(0, 25) * grid; apple.y = getRandomInt(0, 25) * grid; >// Проверяем, не столкнулась ли змея сама с собой // Для этого перебираем весь массив и смотрим, есть ли у нас в массиве змейки две клетки с одинаковыми координатами for (var i = index + 1; i < snake.cells.length; i++) < // Если такие клетки есть — начинаем игру заново if (cell.x === snake.cells[i].x cell.y === snake.cells[i].y) < // Задаём стартовые параметры основным переменным snake.x = 160; snake.y = 160; snake.cells = []; snake.maxCells = 4; snake.dx = grid; snake.dy = 0; // Ставим яблочко в случайное место apple.x = getRandomInt(0, 25) * grid; apple.y = getRandomInt(0, 25) * grid; >> >); > // Смотрим, какие нажимаются клавиши, и реагируем на них нужным образом document.addEventListener(‘keydown’, function (e) < // Дополнительно проверяем такой момент: если змейка движется, например, влево, то ещё одно нажатие влево или вправо ничего не поменяет — змейка продолжит двигаться в ту же сторону, что и раньше. Это сделано для того, чтобы не разворачивать весь массив со змейкой на лету и не усложнять код игры. // Стрелка влево // Если нажата стрелка влево, и при этом змейка никуда не движется по горизонтали… if (e.which === 37 snake.dx === 0) < // то даём ей движение по горизонтали, влево, а вертикальное — останавливаем // Та же самая логика будет и в остальных кнопках snake.dx = -grid; snake.dy = 0; >// Стрелка вверх else if (e.which === 38 snake.dy === 0) < snake.dy = -grid; snake.dx = 0; >// Стрелка вправо else if (e.which === 39 snake.dx === 0) < snake.dx = grid; snake.dy = 0; >// Стрелка вниз else if (e.which === 40 snake.dy === 0) < snake.dy = grid; snake.dx = 0; >>); // Запускаем игру requestAnimationFrame(loop);

Как улучшить

Этот код — самая простая реализация змейки, и игру можно сделать ещё лучше:

  • выводить количество набранных очков;
  • сделать так, чтобы нельзя было проходить сквозь стены;
  • добавить препятствия;
  • поставить таймер — кто больше соберёт еды за 5 минут;
  • добавить вторую змейку и играть вдвоём.

Проголосуйте за тот вариант, который вам больше всего нравится, в комментариях, или сделайте свою змейку, где всё это будет одновременно.

Получите ИТ-профессию

Если вам интересно писать код и сразу видеть результат своей работы — загляните в «Практикум». Там есть классные тренажёры, интересные проекты и много хорошего кода!

Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию

Апскиллинг, как говорится

Апскиллинг — это, например, переход с уровня junior на уровень middle, а потом — senior. У «Яндекс Практикума» есть курсы ровно для этого: от алгоритмов и типов данных до модных фреймворков.

Апскиллинг, как говорится Апскиллинг, как говорится Апскиллинг, как говорится Апскиллинг, как говорится

Получите ИТ-профессию

В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.

Источник: thecode.media

Своя змейка, или пишем первый проект. Часть 0

Привет Хабр! Меня зовут Евгений «Nage», и я начал заниматься программированием около года назад, в свободное от работы время. Просмотрев множество различных туториалов по программированию задаешься вопросом «а что же делать дальше?», ведь в основном все рассказывают про самые основы и дальше как правило не заходят. Вот после продолжительного времени за просмотром разных роликов про одно и тоже я решил что стоит двигаться дальше, и браться за первый проект. И так, сейчас мы разберем как можно написать игру «Змейка» в консоли со своими начальными знаниями.

Глава 1. Итак, с чего начнем?

Для начала нам ничего лишнего не понадобится, только блокнот (или ваш любимый редактор), и компилятор C#, он присутствует по умолчанию в Windows, находится он в С:WindowsMicrosoft.NETFrameworkv4.0.30319csc.exe. Можно использовать компилятор последней версии который поставляется с visual studio, он находится Microsoft Visual Studio2017CommunityMSBuild15.0BinRoslyncsc.exe.

Создадим файл для быстрой компиляции нашего кода, сохранил файл с расширением .bat со следующим содержимым:

Таким способом мы можем скомпилировать только один файл, поэтому мы будем писать все классы в одном документе (я не разобрался еще как компилировать несколько файлов в один .exe через консоль, да и это не тема нашей статьи, может кто нибудь расскажет в комментариях).

Для тех кто сразу хочет увидеть весь код.

Скрытый текст

Читайте также:
Asus sonicmaster что это за программа

Глава 2. Первые шаги

Подготовим поле нашей игры, начиная с точки входа в нашу программу. Задаем переменные X и Y, размер и буфер окна консоли, и скроем отображение курсора.

using System; using System.Collections.Generic; using System.Linq; class Game< static readonly int x = 80; static readonly int y = 26; static void Main()< Console.SetWindowSize(x + 1, y + 1); Console.SetBufferSize(x + 1, y + 1); Console.CursorVisible = false; >// Main() >// class Game

Для вывода на экран нашей «графики» создадим свой тип данных — точка. Он будет содержать координаты и символ, который будет выводится на экран. Также сделаем методы для вывода на экран точки и ее «стирания».

struct Point < public int x < get; set; >public int y < get; set; >public char ch < get; set; >public static implicit operator Point((int, int, char) value) => new Point ; public void Draw() < DrawPoint(ch); >public void Clear() < DrawPoint(‘ ‘); >private void DrawPoint(char _ch) < Console.SetCursorPosition(x, y); Console.Write(_ch); >>

Это интересно!
Оператор => называется лямбда-оператор, он используется в качестве определения анонимных лямбда выражений, и в качестве тела, состоящего из одного выражения, синтаксический сахар, заменяющий оператор return. Приведенный выше метод переопределения оператора (про его назначение чуть ниже) можно переписать так:

public static bool operator ==(Point a, Point b) < if (a.x == b.x a.y == b.y)< return true; >else < return false; >>

Создадим класс стен, границы игрового поля. Напишем 2 метода на создание вертикальных и горизонтальных линий, и в конструкторе вызываем отрисовку всех 4х сторон заданным символом. Список всех точек в стенке нам пригодится позже.

class Walls < private char ch; private Listwall = new List(); public Walls(int x, int y, char ch) < this.ch = ch; DrawHorizontal(x, 0); DrawHorizontal(x, y); DrawVertical(0, y); DrawVertical(x, y); >private void DrawHorizontal(int x, int y) < for (int i = 0; i < x; i++)< Point p = (i, y, ch); p.Draw(); wall.Add(p); >> private void DrawVertical(int x, int y) < for (int i = 0; i < y; i++) < Point p = (x, i, ch); p.Draw(); wall.Add(p); >> >// class Walls

Как вы могли заметить для инициализации типа данных Point используется форма Point p = (x, y, ch); как и у встроенных типов, это становится возможным при переопределении оператора implicit, в котором описывается как задаются переменные.

Конструкция (int, int, char) называется кортежем, и работает только с .net 4.7+, по этому если у вас не установлен visual studio, то в вашем распоряжении только компилятор v4.0.30319 и нужно использовать стандартную инициализацию через оператор new.

Вернемся к классу Game и объявим поле walls, а в методе Main инициализируем ее.

class Game< static Walls walls; static void Main()< walls = new Walls(x, y, ‘#’); .

Все! Можно скомпилировать код и посмотреть, что наше поле построилось, и самая легкая часть позади.

Глава 3. А что сегодня на завтрак?

Добавим генерацию еды на нашем поле, для этого создадим класс FoodFactory, который и будет заниматься созданием еды внутри границ.

class FoodFactory < int x; int y; char ch; public Point food < get; private set; >Random random = new Random(); public FoodFactory(int x, int y, char ch) < this.x = x; this.y = y; this.ch = ch; >public void CreateFood() < food = (random.Next(2, x — 2), random.Next(2, y — 2), ch); food.Draw(); >>

Добавляем инициализацию фабрики и создадим еду на поле

Глава 4. Время главного героя

Перейдем к созданию самой змеи, и для начала определим перечисление направления движения змейки.

enum Direction

Теперь можем создать класс змейки, где опишем как она будет ползать, поворачивать. Определим список точек змеи, наше перечисление, шаг на сколько будет перемещаться за ход, и ссылки на хвостовую и головную точки, и конструктор, в котором рисуем змею в заданных координатах и заданной длинны при старте игры.

class Snake < private Listsnake; private Direction direction; private int step = 1; private Point tail; private Point head; bool rotate = true; public Snake(int x, int y, int length)< direction = Direction.RIGHT; snake = new List(); for (int i = x — length; i < x; i++) < Point p = (i, y, ‘*’); snake.Add(p); p.Draw(); >> //Методы движения и поворота в зависимости он направления движения змейки. public Point GetHead() => snake.Last(); public void Move() < head = GetNextPoint(); snake.Add(head); tail = snake.First(); snake.Remove(tail); tail.Clear(); head.Draw(); rotate = true; >public Point GetNextPoint() < Point p = GetHead(); switch (direction) < case Direction.LEFT: p.x -= step; break; case Direction.RIGHT: p.x += step; break; case Direction.UP: p.y -= step; break; case Direction.DOWN: p.y += step; break; >return p; > public void Rotation(ConsoleKey key) < if (rotate) < switch (direction) < case Direction.LEFT: case Direction.RIGHT: if (key == ConsoleKey.DownArrow) direction = Direction.DOWN; else if (key == ConsoleKey.UpArrow) direction = Direction.UP; break; case Direction.UP: case Direction.DOWN: if (key == ConsoleKey.LeftArrow) direction = Direction.LEFT; else if (key == ConsoleKey.RightArrow) direction = Direction.RIGHT; break; >rotate = false; > > >//class Snake

В методе поворота, что бы избежать возможности повернуть сразу на 180 градусов, просто указываем, что в каждом направлении мы можем повернуть только в 2 стороны. А проблему поворота на 180 градусов двумя нажатиями — поставив «переключатель», отключаем возможность поворачивать после первого нажатия, и включаем после очередного хода.

Осталось вывести ее на экран.

class Game< static Snake snake; static void Main()< snake = new Snake(x / 2, y / 2, 3); .

Готово! теперь у нас есть все что нужно, поле огороженное стенами, рандомно появляющаяся еда, и змейка. Пришла пора заставить все это взаимодействовать друг с другом.

Глава 5. Л-логика

Заставим нашу змейку двигаться, напишем бесконечный цикл для считывания клавиш нажатых на клавиатуре, и передаем клавишу в метод поворота змеи

class Game < static void Main () < while (true) < if (Console.KeyAvailable) < ConsoleKeyInfo key = Console.ReadKey (); snake.Rotation(key.Key); >.

для движения змеи воспользуемся классом .net который будет запускать метод Loop через определенные промежутки времени.

using System.Threading; class Game < static Timer time; static void Main () < time = new Timer (Loop, null, 0, 200); .

Теперь, перед тем как написать метод движения змейки, надо реализовать взаимодействие головы с едой, стенками и хвостом змеи. Для этого надо написать метод, позволяющий сравнивать две точки на совпадение координат. Переопределим оператор равенства и не равенства, их обязательно нужно переопределять в паре.

struct Point < public static bool operator == (Point a, Point b) =>(a.x == b.x a.y == b.y) ? true : false; public static bool operator != (Point a, Point b) => (a.x != b.x || a.y != b.y) ? true : false; .

Теперь можно написать метод, который будет проверять совпадает ли интересующая нас точка с какой нибудь из массива стен.

class Walls < public bool IsHit (Point p) < foreach (var w in wall) < if (p == w) < return true; >> return false; > .

И похожий метод проверяющий не совпадает ли точка с хвостом.

class Snake < public bool IsHit (Point p) < for (int i = snake.Count — 2; i >0; i—) < if (snake[i] == p) < return true; >> return false; > .

И методом проверки съела ли еду наша змейка, и сразу делаем ее длиннее.

class Snake < public bool Eat (Point p) < head = GetNextPoint (); if (head == p) < snake.Add (head); head.Draw (); return true; >return false; > .

теперь можно написать метод движения, со всеми нужными проверками.

class Snake < static void Loop (object obj) < if (walls.IsHit (snake.GetHead ()) || snake.IsHit (snake.GetHead ())) < time.Change (0, Timeout.Infinite); >else if (snake.Eat (foodFactory.food)) < foodFactory.CreateFood (); >else < snake.Move (); >> .

Вот и все! Наша змейка в консоли закончена и можно поиграть.

Заключение

Мы посмотрели как можно реализовать первую простенькую игру с небольшим использованием ООП, научились перегружать операторы, посмотрели на кортежи и лямбда оператор, надеюсь это было полезно!

Это была пилотная статья, и если вам понравилось, я напишу про реализацию змейки на Unity.
Всем удачи!

Источник: habr.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru