Jar with src (if jdk installed)
https://drive.google.com/file/d/1yNAFEdnr-p5pDZjh0kctfWyVPR0nkLNX/view?usp=sharing
(or compile and run ~ 700 lines)
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package jsnake;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
/**
*
* @author jimak
*/
public class JSnake extends JPanel implements MouseListener,KeyListener,ComponentListener{
public static String getHelpString(){
return ""
+ "Simple Java Snake Options"
+ "\nPress"
+ "\nArrows or W-up S-down A-left D-Right to turn snake's head."
+ "\n\nY/U to decrease/increase snake's speed."
+ "\nG/H to decrease/increase Rows and Cols."
+ ""
+ "\n\nT to change paint type"
+ "\nR to change snake's color."
+ "\nL to just ignore that you just lost.(just not show the red line)"
+ ""
+ "\n\nP to Restart by having almost half being filled."
+ "\n\nEnter to Restart ."
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ ""
+ "\n\n\n(you can still play if you loose and have some move to go)";
}
static Toolkit tk=Toolkit.getDefaultToolkit();
static Dimension scr=tk.getScreenSize();
static Random rand=new Random();
public static Color randColor(){
return new Color(rand.nextInt(255),rand.nextInt(255),rand.nextInt(255));
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
try{
JFrame jfr=new JFrame("Simple Java Snake Game");
jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int insw=scr.width/10;
int insh=scr.height/10;
jfr.setBounds(insw,insh,scr.width-2*insw,scr.height-2*insh);
JSnake jsn=new JSnake();
jfr.getContentPane().add(jsn);
jfr.setVisible(true);
JOptionPane.showMessageDialog(null,getHelpString());
//throw new IllegalAccessError();
}catch(Throwable thr){
try{System.err.println(""+thr);}catch(Throwable thr2){}
try{JOptionPane.showMessageDialog(null, thr,"will exit app",JOptionPane.ERROR_MESSAGE);}catch(Throwable thr2){}
try{thr.printStackTrace();}catch(Throwable thr2){}
System.exit(-1);
}
}
static int dirs[][]=new int[4][2];
public static final int dirRight=0;
public static final int dirDown=1;
public static final int dirLeft=2;
public static final int dirUp=3;
static{
dirs[dirRight][0]=1;
dirs[dirRight][1]=0;
dirs[dirDown][0]=0;
dirs[dirDown][1]=1;
dirs[dirLeft][0]=-1;
dirs[dirLeft][1]=0;
dirs[dirUp][0]=0;
dirs[dirUp][1]=-1;
}
public static int oppositeDir(int some){
if(some==dirRight){return dirLeft;}
if(some==dirLeft){return dirRight;}
if(some==dirDown){return dirUp;}
return dirDown;
}
JButton jbFillHalf=new JButton("Restart-Half");
JButton jbRestart=new JButton("Restart");
JSpinner jspRowsCols=new JSpinner(new SpinnerNumberModel(12,5,100,1));
JPanel jpRowsCols=new JPanel(new BorderLayout());
JSpinner jspMovesPerSecond=new JSpinner(new SpinnerNumberModel(3,1,10,1));
JPanel jpMovesPerSecond=new JPanel(new BorderLayout());
JPanel jpOthers=new JPanel(new GridLayout(1,2));
JPanel jpRestartButs=new JPanel(new GridLayout(1,2));
int rows,cols;
int sqs;
int headDir=0;
byte snakex[];
byte snakey[];
int snakeLen=0;
Graphics2D g;
class SnakePainter{
void paintSnakeSquare(int x,int y){
g.fillRect(x+1, y+1, sqs-2,sqs-2);
}
public String toString(){return "fill Rect";}
};
SnakePainter currSnakePainter=new SnakePainter();
SnakePainter snakePainter[]={
currSnakePainter
,new SnakePainter(){
void paintSnakeSquare(int x,int y){g.fillOval(x, y, sqs,sqs);}
public String toString(){return "fill Oval";}
}
,new SnakePainter(){
void paintSnakeSquare(int x,int y){g.drawRect(x, y, sqs,sqs);}
public String toString(){return "Quicker";}
}
,new SnakePainter(){
void paintSnakeSquare(int x,int y){g.drawOval(x, y, sqs,sqs);}
public String toString(){return "draw Oval";}
}
,new SnakePainter(){
void paintSnakeSquare(int x,int y){g.drawOval(x, y, sqs,sqs);g.drawRect(x, y, sqs,sqs);}
public String toString(){return "draws";}
}
};
JComboBox<SnakePainter> jcombPaintType=new JComboBox<>(snakePainter);
JPanel jpPaint=new JPanel(){
public void paintComponent(Graphics gr){
super.paintComponent(gr);
g=(Graphics2D)gr;
paintSnake();
}
};
Thread thrRepainter=new Thread(){
@Override
public void run() {
while(true){
jpPaint.repaint();
try{sleep(20);}catch(InterruptedException inter){}
}
}
};
long thrMoverSleep=1000/(int)jspMovesPerSecond.getValue();
boolean thrMoverPaused=false;
Thread thrMover=new Thread(){
@Override
public void run() {
while(true){
if(thrMoverPaused){
try{sleep(600000);}catch(InterruptedException inter){}
}
else{
moveSnake();
try{sleep(thrMoverSleep);}catch(InterruptedException inter){}
}
}
}
};
void thrMoverPause(){
thrMoverPaused=true;
thrMover.interrupt();
}
void thrMoverUnpause(){
thrMoverPaused=false;
thrMover.interrupt();
}
Font bigFont=new Font("Dialog",1,24);
public JSnake(){
super(new BorderLayout());
jpPaint.setFont(bigFont);
jpRestartButs.add(jbRestart);
jpRestartButs.add(jbFillHalf);
jpRowsCols.add(BorderLayout.WEST,new JLabel("Rows&Cols"));
jpRowsCols.add(BorderLayout.CENTER,jspRowsCols);
jpRowsCols.add(BorderLayout.EAST,jpRestartButs);
jpMovesPerSecond.add(BorderLayout.WEST,new JLabel("moves/sec"));
jpMovesPerSecond.add(BorderLayout.CENTER,jspMovesPerSecond);
jpMovesPerSecond.add(BorderLayout.EAST,jcombPaintType);
jpOthers.add(jpRowsCols);
jpOthers.add(jpMovesPerSecond);
add(BorderLayout.CENTER,jpPaint);
add(BorderLayout.SOUTH,jpOthers);
jspRowsCols(null);
jbRestart();
componentResized(null);
jpPaint.addMouseListener(this);
jpPaint.addKeyListener(this);
addComponentListener(this);
jspRowsCols.addChangeListener(e->jspRowsCols(e));
jspMovesPerSecond.addChangeListener(e->jspMovesPerSecond());
jbFillHalf.addActionListener(e->jbRestartHalf());
jbRestart.addActionListener(e->jbRestart());
jcombPaintType.addItemListener(e->jcombPaintType(e));
Thread focuser=new Thread(){
public void run(){
try{sleep(1111);}catch(InterruptedException inter){}
jpPaint.requestFocusInWindow();
try{sleep(1111);}catch(InterruptedException inter){}
jpPaint.requestFocusInWindow();
}
};
focuser.setDaemon(true);
thrMover.setDaemon(true);
thrRepainter.setDaemon(true);
thrRepainter.start();
thrMover.start();
focuser.start();
}
void jcombPaintType(ItemEvent e){
if(e.getStateChange()==ItemEvent.SELECTED){
currSnakePainter=(SnakePainter)jcombPaintType.getSelectedItem();
jpPaint.requestFocusInWindow();
}
}
void nextSnakePaintType(){
int si=jcombPaintType.getSelectedIndex();
++si;
if(si>=snakePainter.length){
si=0;
}
jcombPaintType.setSelectedIndex(si);
}
void increaseSpeed(){
int next=(int)jspMovesPerSecond.getValue();
next+=1;
if(next<=(int)((SpinnerNumberModel)jspMovesPerSecond.getModel()).getMaximum()){
jspMovesPerSecond.setValue(next);
}
else{ tk.beep();}
}
void decreaseSpeed(){
int next=(int)jspMovesPerSecond.getValue();
next-=1;
if(next>=(int)((SpinnerNumberModel)jspMovesPerSecond.getModel()).getMinimum()){
jspMovesPerSecond.setValue(next);
}
else{tk.beep();}
}
void increaseRowsCols(){
int next=(int)jspRowsCols.getValue();
next+=1;
if(next<=(int)((SpinnerNumberModel)jspRowsCols.getModel()).getMaximum()){
jspRowsCols.setValue(next);
}
else{tk.beep();}
}
void decreaseRowsCols(){
int next=(int)jspRowsCols.getValue();
next-=1;
if(next>=(int)((SpinnerNumberModel)jspRowsCols.getModel()).getMinimum()){
jspRowsCols.setValue(next);
}
else{tk.beep();}
}
void jspMovesPerSecond(){
long sec=1000;
sec/=(int)jspMovesPerSecond.getValue();
thrMoverSleep=sec;
}
void jspRowsCols(ChangeEvent e){
int rc=(int)jspRowsCols.getValue();
int rcs=rc*rc;
byte neox[]=new byte[rcs];
byte neoy[]=new byte[rcs];
rows=rc;
cols=rc;
snakex=neox;
snakey=neoy;
jbRestart();
componentResized(null);
}
void jbRestartHalf(){
if(jbFillHalf.isEnabled()){
thrMoverPause();
int l=snakex.length;
int half=l/2;
int x=2;
int y=3;
if(rows<10){
y=1;
}
headDir=dirRight;
snakeLen=1;
int i=0;
snakex[i]=(byte)x;
snakey[i]=(byte)y;
++y;
++i;
boolean ystartOdd=y%2==1;
while(y<rows){
if(ystartOdd==(y%2==1)){
x=2;
while(x<cols){
snakex[i]=(byte)x;
snakey[i]=(byte)y;
++i;++snakeLen;
++x;
}
}
else{
x=cols-1;
while(x>1){
snakex[i]=(byte)x;
snakey[i]=(byte)y;
++i;++snakeLen;
--x;
}
}
++y;
}
lost=false;won=false;
createNewRandomApple();
jpPaint.requestFocusInWindow();
thrMoverUnpause();
//jbFillHalf.setEnabled(false);
}else{tk.beep();}
}
void jbRestart(){
setAllEmpty(2,2,0);
}
void setAllEmpty(int snakeI,int snakeJ,int dir){
thrMoverPause();
jbFillHalf.setEnabled(true);
lost=false;won=false;
snakeLen=1;
snakex[0]=(byte)snakeI;
snakey[0]=(byte)snakeJ;
headDir=dir;
createNewRandomApple();
jpPaint.requestFocusInWindow();
thrMoverUnpause();
}
int applei=-1,applej=-1;
int availables=0;
void createNewRandomApple(){
Vector<Integer> avXs=new Vector<>();
Vector<Integer> avYs=new Vector<>();
int i=0;
while(i<rows){
int j=0;
while(j<cols){
int s=0;
boolean snakeHasThisSquare=false;
while(s<snakeLen){
if(snakex[s]==j && snakey[s]==i){
snakeHasThisSquare=true;
s=snakeLen;
}
++s;
}
if(!snakeHasThisSquare){
avXs.add(j);
avYs.add(i);
}
++j;
}
++i;
}
int size=avXs.size();
availables=size-1;
won=availables<rows;
if(size>0){
int appleIndex=rand.nextInt(size);
applei=avXs.get(appleIndex);
applej=avYs.get(appleIndex);
}
else{
System.out.println("You won !!!! ");
won=true;
}
//System.out.println("Availables: "+availables);
}
boolean snakeContains(int r,int c){
int i=0;
while(i<snakeLen){
if(snakex[i]==r && snakey[i]==c){
return true;
}
i++;
}
return false;
}
void moveSnake(){
//System.out.println("moviung");
int i=0;
int headi=snakex[0];
int headj=snakey[0];
int nextheadi=headi+dirs[headDir][0];
int nextheadj=headj+dirs[headDir][1];
if(nextheadi<0 ||nextheadi>=cols || nextheadj<0 || nextheadj>=rows){
lost=true;
}
else{
if(snakeContains(nextheadi, nextheadj)){
lost=true;
}
else{
if(nextheadi==applei && nextheadj==applej){
//System.out.println("eating increase snake len");
int last=snakeLen;
while(last>0){
snakex[last]=snakex[last-1];
snakey[last]=snakey[last-1];
--last;
}
snakeLen++;
snakex[0]=(byte)nextheadi;
snakey[0]=(byte)nextheadj;
createNewRandomApple();
jpPaint.repaint();
}
else{
int last=snakeLen-1;
while(last>0){
snakex[last]=snakex[last-1];
snakey[last]=snakey[last-1];
--last;
}
snakex[0]=(byte)nextheadi;
snakey[0]=(byte)nextheadj;
}
}
}
}
int headDir(){
int out=-1;
if(snakeLen>1){
if(snakex[0]>snakex[1]){
return dirRight;
}
else if(snakex[0]<snakex[1]){
return dirLeft;
}
else if(snakey[0]>snakey[1]){
return dirDown;
}
else{
return dirUp;
}
}
return out;
}
void setDir(int newDir){
int dirCurr=headDir();
if(dirCurr>-1){
if(newDir!=oppositeDir(dirCurr)){
headDir=newDir;
}
else{
System.out.println("avoid set opposite direction");
}
}
else{
headDir=newDir;
}
}
Color colSnake=Color.blue;
Color colSq=Color.white;
Color colWall=new Color(10,55,88,88);
boolean lost=false;
boolean won=false;
int wall=10;
int wall2=wall*2;
void paintSnake(){
g.setColor(colWall);
int x=0;
int y=0;
g.fillRect(0, 0, wall2+(cols)*sqs,wall);//up wall
g.fillRect(0, wall+((rows)*sqs),wall2+(cols)*sqs, wall);//down wall
g.fillRect(x,wall2, wall, (rows)*sqs-wall2);//left wall
g.fillRect(wall+cols*sqs,wall2, wall, (rows)*sqs-wall2);//right wall
g.setColor(colSq);
int i=0,j;
x=wall;
y=wall;
while(i<rows){
j=i%2;
x=wall+j*sqs;
while(j<cols){
g.fillRect(x,y, sqs,sqs);
j+=2;
x+=sqs*2;
}
y+=sqs;
++i;
}
g.setColor(colSnake);
i=0;
while(i<snakeLen){
x=snakex[i];
y=snakey[i];
x*=sqs;
y*=sqs;
x+=wall;
y+=wall;
currSnakePainter.paintSnakeSquare(x, y);
//g.fillOval(x,y, sqs,sqs);
//g.fillRect(x,y, sqs,sqs);
//g.drawRect(x,y, sqs,sqs);
//g.drawOval(x,y, sqs,sqs);
++i;
}
g.setColor(Color.red);
g.fillRect(wall+applei*sqs, wall+applej*sqs, sqs,sqs);
i=0;
x=snakex[i];
y=snakey[i];
x*=sqs;
y*=sqs;
x+=sqs/2;
y+=sqs/2;
x+=wall;
y+=wall;
int xn=x+dirs[headDir][0]*sqs;
int yn=y+dirs[headDir][1]*sqs;
g.drawLine(x,y,xn,yn);
if(lost){
g.setColor(Color.RED);
g.drawLine(0,0,1000,1000);
}
g.setColor(Color.green);
g.drawString("Remains = "+availables,1,bigFont.getSize());
if(won){
g.setColor(Color.MAGENTA);
g.translate((cols/2)*sqs, (rows/2)*sqs);
g.rotate(theta);theta+=Math.toRadians(10);
g.drawString("You won ",0,0);
}
}
double theta=0;
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
jpPaint.requestFocusInWindow();
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int kc=e.getKeyCode();
if((kc==KeyEvent.VK_UP||kc==KeyEvent.VK_W) && headDir!=dirDown){
//System.out.println("up");
setDir(dirUp);
}
else if((kc==KeyEvent.VK_DOWN||kc==KeyEvent.VK_S) && headDir!=dirUp){
//System.out.println("down");
setDir(dirDown);
}
else if((kc==KeyEvent.VK_LEFT||kc==KeyEvent.VK_A) && headDir!=dirRight){
//System.out.println("left");
setDir(dirLeft);
}
else if((kc==KeyEvent.VK_RIGHT||kc==KeyEvent.VK_D) && headDir!=dirLeft){
//System.out.println("right");
setDir(dirRight);
}
else if(kc==KeyEvent.VK_ENTER){
jbRestart();
}
else if(kc==KeyEvent.VK_P){
jbRestartHalf();
}
else if(kc==KeyEvent.VK_Y){
decreaseSpeed();
}
else if(kc==KeyEvent.VK_U){
increaseSpeed();
}
else if(kc==KeyEvent.VK_G){
decreaseRowsCols();
}
else if(kc==KeyEvent.VK_H){
increaseRowsCols();
}
else if(kc==KeyEvent.VK_L){
lost=false;
}
else if(kc==KeyEvent.VK_R){
colSnake=randColor();
}
else if(kc==KeyEvent.VK_T){
nextSnakePaintType();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void componentResized(ComponentEvent e) {
int fitsrows=(jpPaint.getHeight()-wall*2)/(rows);
int fitscols=(jpPaint.getWidth()-wall*2)/(cols);
sqs=Math.min(fitscols, fitsrows);
jpPaint.repaint();
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentShown(ComponentEvent e) {
}
@Override
public void componentHidden(ComponentEvent e) {
}
}
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου