Нет проверки на то, что яблоко попадёт на змею. 
 Чтобы змея не пыталась повернуть на себя и врезаться можно сделать так: 
 * Добавить новую переменную int newDir 
 * В функцию restart() добавить dir = newDir = 2; 
 * В функции tick() изменить код после if (end) {}: 
 Код
if (keys[KeyEvent.VK_W] && dir != 1) newDir = 0; 
 if (keys[KeyEvent.VK_S] && dir != 0) newDir = 1; 
 if (keys[KeyEvent.VK_A] && dir != 3) newDir = 2; 
 if (keys[KeyEvent.VK_D] && dir != 2) newDir = 3; 
    
 if (ticks++ % 30 == 0) { 
  dir = newDir;