Как написать свою змейку на Java за 15 минут
Пишем змейку на C++
Давным-давно, когда мониторы были зелёными, а 64Кб оперативы на борту считалось нормой, существовала игрушка под названием Snake. Она также была известна под названиями Змейка, Удав, Питон и даже Червяк. По прошествии времени появилось множество клонов этой игры под различные платформы: от Flash до мобильных телефонов и смартфонов. Но вот та реализация, работающая в текстовом режиме, видимо умерла вместе с теми компьютерами, для которых она была написана.
И вот, за пару свободных вечеров был написан очередной клон легендарного Snake, который я и представляю вашему вниманию: Oldschool Snake.
Как играть
Управление змейкой клавишами управления курсором. Esc — завершение игры. Для выхода из игры надо нажать Esc или клавишу N на вопрос «Once more?». Змейка не должна натыкаться на стенки и на собственный хвост. Это — смерть. Змейка не умеет ползать хвостом вперёд. Попытаться заставить её это сделать — верная смерть. Кормить змейку надо, естественно, долларами. Когда змейка ест, она растёт.
Top 10 определяется по рейтингу. Общий рейтинг складывается из суммы рейтинговых очков, полученных за каждую съеденную еду. Рейтинговые очки прямо пропорциональны длине змейки и обратно пропорциональны времени, затраченному на достижение очередной порции еды.
Лицензия
GNU GPL. То есть можно свободно распространять, изучать исходный текст, вносить изменения в исходный текст, использовать в своих некоммерческих проектах.
Замечания по реализации
Игрушка очень простая. Основа игрушки была написана за пару вечеров. Правда потом, наверное, неделя ушла на отладку и, главным образом, на тестирование и допиливание. Вполне возможно, что где-то затаились недобитые баги. Отстрел разрешён.
В этот вариант программы уже заложены некоторые возможности по усовершенствованию игры. Но при этом теряется аутентичность.
Программа написана для Windows 2000 Professional (и выше). Для переноса под другие операционки необходимо переписать реализацию класса CScreen и иметь порт библиотеки conio.h .
Компилировал TDM-GCC 4.8.1 С другими компиляторами не проверял.
Вопросы, замечание, предложения, ошибки — пожалуйста в комментарии. Но, скажу сразу, не судите строго за стиль — написано было быстро и, что называется, «для себя».
Как написать свою змейку на Java за 15 минут
Профиль
Группа: Участник
Сообщений: 38
Регистрация: 1.11.2007
Где: город Королёв
Репутация: нет
Всего: нет
Всем привет.
Не так давно начал изучать яву, и из-за необходимости практики решил написать своё приложение, так как нормальных идей нету остановился на змейке.
Итак змейку я представил как ArrayList содержащий в себе экземпляры класса отдельных кусочков её хвоста (квадратиков).
Шаг представляется добавлением нового экземпляра квадратика и стиранием предыдущего, но вот как раз в этом месте у меня косяк 🙁
Простой класс, нет ничего особенного и описывать не буду
Код |
/** * Направления. */ public class Direction < protected static final byte UP=0, DOWN=1, LEFT=3, RIGHT=2; /** * текущее направление */ private byte NOW; /** * Конструктор, первоначально змея смотрит вверх. */ public Direction() < NOW=UP; > /** * Поворачивает змею. * @param WHERE куда повернуть */ public void turn(byte WHERE) < if((NOW==UP && WHERE!=DOWN) || (NOW==LEFT && WHERE!=RIGHT) || (NOW==DOWN && WHERE!=UP) || (NOW==RIGHT && WHERE!=LEFT)) NOW=WHERE; > |
public byte getNOW() <
return NOW;
>
>
Класс апплета, вроде тоже ничего сложного, надо сказать что пробел имитирует съедание змейкой одного объекта и фон чёрный для того чтобы было понятно как происходит движение змеи:
Код |
import java.awt.Color; import java.awt.Graphics; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.*; |
public class Game extends JApplet implements Runnable <
private Direction direction = new Direction();
Snake our_snake = new Snake();
public Game() <
setBackground(Color.BLACK);
addKeyListener(new KeyAdapter() <
@Override
public void keyPressed(KeyEvent e) <
switch(e.getKeyCode()) <
case KeyEvent.VK_DOWN:
direction.turn(Direction.DOWN);break;
case KeyEvent.VK_UP:
direction.turn(Direction.UP);break;
case KeyEvent.VK_LEFT:
direction.turn(Direction.LEFT);break;
case KeyEvent.VK_RIGHT:
direction.turn(Direction.RIGHT);break;
case KeyEvent.VK_SPACE:
our_snake.add();
>
>
>);
>
@Override
public void paint(Graphics g) <
// g.clearRect(0, 0, getWidth(), getHeight());
showStatus(Integer.toString(our_snake.ckolko()));
our_snake.step(direction);
our_snake.paint(g);
>
public void run() <
for(;;) <
try <
Thread.sleep(250);
> catch (InterruptedException ex) <>
repaint();
>
>
@Override
public void start() <
Thread thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
>
>
И основной класс, который описывает змею, по идее тоже всё просто, но у меня косяк в методе paint, я не понимаю почему если добавить один квадратик, то предыдущие перестанут закрашиваться белым 🙁 в этом основной косяк.
Код |
import java.awt.*; import java.util.ArrayList; |
public class Snake <
/**
* Класс описывает поведение каждого отдельного квадрата
* хвоста змеи.
*/
private class Square <
int NOW_X , NOW_Y;
private void paint(int x, int y, int part, Graphics g) <
g.setColor(Color.green); // хвост зелёный
g.fillRect(x, y, part, part); //квадратный
NOW_X = x;
NOW_Y = y;
>
private void erase(int part, Graphics g) <
g.setColor(Color.white);
g.fillRect(NOW_X, NOW_Y, part, part);
>
private int getNOW_X() <
return NOW_X;
>
private int getNOW_Y() <
return NOW_Y;
>
>
/**
* Динамический массив содержит все отдельные части хвоста змеи.
*/
ArrayList al = new ArrayList(4);
/**
* Ширина и высота одной части змеи
*/
private final int part = 6;
/**
* Текущие координаты.
*/
private int x=200,y=225;
/**
* С помощью этого флага удлиняем змейку.
*/
private boolean delete = true;
/**
* Конструктор
*/
Snake()
protected void paint(Graphics g) <
if(delete) <
al.get(al.size()-1).erase(part, g); // мне кажется элементы не стираются когда их больше одного из-за отсутствия имени у экземпляра
// класса, хотя может я не прав, это просто догадака
al.remove(al.size()-1);
>
delete = true;
al.add(new Square()); // попробуйте перенести эти строки в начало метода
al.get(0).paint(x, y, part, g); // опять же почему будет такой результат я не понимаю, стираться всё-равно же должно
>
protected void add() <
delete = false;
>
public int ckolko() <
return al.size();
>
protected void step(Direction direction) <
switch(direction.getNOW()) <
case Direction.UP:
y -= 6;break;
case Direction.DOWN:
y += 6;break;
case Direction.LEFT:
x -= 6;break;
case Direction.RIGHT:
x += 6;break;
>
>
>
Это сообщение отредактировал(а) invis87 — 4.4.2009, 12:49
Kangaroo |
|
|
Код |
if(delete) < al.get(0).erase(part, g); // тут использовать 0 al.remove(0); > delete = true; al.add(new Square()); al.get(al.size()-1).paint(x, y, part, g); // а тут — последний элемент |
invis87 |
|
|
invis87 |
|
|
Код |
import java.awt.*; import java.util.Random; import java.util.ArrayList; /** * * @author invis */ public class Snake < /** * Класс описывает поведение каждого отдельного квадрата * хвоста змеи. */ private class Square < private int NOW_X , NOW_Y; |
private void paint(int x, int y, int part, Graphics g) <
g.setColor(Color.green); // хвост зелёный
g.fillRect(x, y, part, part); //квадратный
NOW_X = x;
NOW_Y = y;
>
private void erase(int part, Graphics g) <
g.setColor(Color.white);
g.fillRect(NOW_X, NOW_Y, part, part);
>
>
/**
* Динамический массив содержит все отдельные части хвоста змеи.
*/
ArrayList al = new ArrayList(4);
/**
* Ширина и высота одной части змеи
*/
private final int part = 6;
/**
* Объект для рисования «еды» в случайном месте.
*/
Random random = new Random();
/**
* Текущие координаты.
*/
private int x=216,y=216;
/**
* Координата Х «еды».
*/
private int eatX;
/**
* Координата Y «еды».
*/
private int eatY;
/**
* С помощью этого флага удлиняем змейку.
*/
private boolean delete = true;
/**
* Создана ли уже «еда» для змейки.
*/
private boolean alreadyCreate = false;
/**
* Жива ли змея.
*/
protected boolean alive = true;
/**
* Конструктор создаёт один экземпляр квадратика.
*/
Snake()
protected void paint(Graphics g) <
if(delete) <
al.get(0).erase(part, g);
al.remove(0);
>else
al.add(new Square());
al.get(al.size()-1).paint(x, y, part, g);
>
public int gdeY() <
return al.get(al.size()-1).NOW_Y;
>
public int gdeX() <
return al.get(al.size()-1).NOW_X;
>
protected void step(Direction direction) <
switch(direction.getNOW()) <
case Direction.UP:
y -= 6;break;
case Direction.DOWN:
y += 6;break;
case Direction.LEFT:
x -= 6;break;
case Direction.RIGHT:
x += 6;break;
>
//не врезалась ли змейка в стену
if(x > 471 || x 471|| y
Код |
/** * Направления. * @author invis */ public class Direction < protected static final byte UP=0, DOWN=1, LEFT=3, RIGHT=2; /** * текущее направление */ private byte NOW; /** * Конструктор, первоначально змея смотрит вверх. */ public Direction() < NOW=UP; > /** * Поворачивает змею. * @param WHERE куда повернуть */ public void turn(byte WHERE) < if((NOW==UP && WHERE!=DOWN) || (NOW==LEFT && WHERE!=RIGHT) || (NOW==DOWN && WHERE!=UP) || (NOW==RIGHT && WHERE!=LEFT)) NOW=WHERE; > |
public byte getNOW() <
return NOW;
>
>
Код |
import java.awt.Color; import java.awt.Graphics; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.*; /** * * @author invis */ public class Game extends JApplet implements Runnable < private Direction direction = new Direction(); Snake our_snake = new Snake(); /** * Флаг нужнг для передачи фокуса во время первого рисования. */ boolean mFirstPaint = true; |
public Game() <
setSize(480, 480);
setBackground(Color.white);
addKeyListener(new KeyAdapter() <
@Override
public void keyPressed(KeyEvent e) <
switch(e.getKeyCode()) <
case KeyEvent.VK_DOWN:
direction.turn(Direction.DOWN);break;
case KeyEvent.VK_UP:
direction.turn(Direction.UP);break;
case KeyEvent.VK_LEFT:
direction.turn(Direction.LEFT);break;
case KeyEvent.VK_RIGHT:
direction.turn(Direction.RIGHT);break;
>
>
>);
>
/**
* Выводит сообщение о поражении.
*/
public void loose() <
getGraphics().drawString(«LOOSER», 220, 230);
>
@Override
public void paint(Graphics g) <
// передаём фокус апплету
if (mFirstPaint) <
mFirstPaint = false;
requestFocus();
>
showStatus(«X — » + Integer.toString(our_snake.gdeX()) + «; Y — » + Integer.toString(our_snake.gdeY()));
g.setColor(Color.black);
g.drawRect(4, 4, 471, 471);
our_snake.step(direction);
our_snake.paint(g);
our_snake.food(g);
>
public void run() <
while(our_snake.alive) <
try <
Thread.sleep(100);
> catch (InterruptedException ex) <>
repaint();
>
if(!our_snake.alive)
>
@Override
public void start() <
Thread thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
>
>
P.S. лучше открывать в appletviewer. У меня googlechrome и если апплет открыть 5-й страницей, то он немного подлагивает.
P.S.S Такая большая скорость только из-за того, что поле большое.
Это сообщение отредактировал(а) invis87 — 14.4.2009, 00:08
zoidberg |
|
|
KapsuL |
|
|
korob2001 |
|
|
О сайте Наши цены Соглашение Наши гарантии Способы оплаты Вопросы и ответы Отзывы клиентов Бонусы и скидки Регистрация Вакансии |
||
Мы работаем ЕЖЕДНЕВНО с 9:30 до 23:30 msk |
||
Программа Среда программирования: Java NetBeans Название работы: 2D игра Змейка(питон) на Java Вид работы: Программа Описание: Написать на языке Java обычную 2D игру «змейка». |