Visualizzazione dei risultati da 1 a 2 su 2
  1. #1

    Consigli implementativi gioco Snake

    Sto provando a creare il famoso Snake in java. Ho cominciato ad impostare qualcosa,
    ma come qualcuno saprà non sono molto bravo nel design delle classi.

    Per la griglia ho creato un JPanel con GridLayout:

    codice:
    import java.awt.GridLayout;
    import javax.swing.JPanel;
    
    public class Grid extends JPanel {
    
    	private static final long serialVersionUID = 1L;
    	
    	public Grid() {
    		
    		setLayout(new GridLayout(25,25));
    		
    		for(int i=0; i<25; i++) {
    			for(int j=0; j<25; j++) {
    				Cell cell = new Cell(i,j);
    				add(cell);
    			}
    		}
    	}
    }
    Poi ho creato una classe Snake contenente un ArrayList<Cell> che rappresenta
    il serpente, alla quale si possono aggiungere e rimuovere celle.
    Anche se credo che sia meglio una coda fifo.

    Poi ho creato questa classe che rappresenta una cella:

    Cell

    codice:
    public class Cell extends JLabel {
    
    	private static final long serialVersionUID = 1L;
    	private int coordX;
    	private int coordY;
    	private Color color;
    	private boolean isOccuped; //if is occuped by a part of the body of the snake
    	private boolean isSpecial; //if contains special food
    	private boolean isFood;    //if contains normal food
    
    	public Cell(int x, int y) {		
    		setPreferredSize(new Dimension(20,20));
    		setBorder(BorderFactory.createLineBorder(Color.BLACK));
    		setOccuped(false);
    		setOpaque(true);
    		setBackground(Color.white);
    		setSpecial(false);
    		setFood(false);
    		setCoordX(x);
    		setCoordY(y);
    	}
    	
    	public int getCoordX() {
    		return coordX;
    	}
    	
    	public int getCoordY() {
    		return coordY;
    	}
    	
    	public void setCoordX(int x) {
    		coordX = x;
    	}
    	
    	public void setCoordY(int y) {
    		coordY = y;
    	}
    
    	public Color getColor() {
    		return color;
    	}
    
    	public void setColor(Color color) {
    		this.color = color;
    	}
    
    	public boolean isOccuped() {
    		return isOccuped;
    	}
    
    	public void setOccuped(boolean isOccuped) {
    		this.isOccuped = isOccuped;
    	}
    
    	public boolean isSpecial() {
    		return isSpecial;
    	}
    
    	public void setSpecial(boolean isSpecial) {
    		this.isSpecial = isSpecial;
    	}
    
    	public boolean isFood() {
    		return isFood;
    	}
    
    	public void setFood(boolean isFood) {
    		this.isFood = isFood;
    	}
    }
    L'idea era creare un'altra classe Runnable, dove nel metodo run ogni tot secondi
    (sleep(millisec)) viene fatto avanzare il serpente di una cella, e dove viene creato
    il cibo in una posizione random. Siccome per ora penso che utilizzerò il pattern observer,
    la domanda è come posso aggiornare la griglia? Non posso accedere alle celle
    del GridLayout che io sappia.

    Oppure potrei creare la classe Grid stessa come runnable?

  2. #2
    Ragazzi metto il codice aggiornato. Riesco a muovere il serpente ma ho un problema nella generazione del cibo random (e non solo). Il codice del solo metodo del cibo è questo:

    codice:
    private void generateFood() {
            /*ifood = (int) (Math.random()*24);
            jfood = (int) (Math.random()*24);
            foodCell = matrix[ifood][jfood];
            while(snake.contains(foodCell)) {
                ifood = (int) (Math.random()*24);
                jfood = (int) (Math.random()*24);
                foodCell = matrix[ifood][jfood];
            }
            matrix[ifood][jfood].setFood();*/
            boolean flag = false;
            int x = 0, y = 0, k;
            while (!flag) {
                k = 0;
                x = (int) (Math.random() * CELLE);
                y = (int) (Math.random() * CELLE);
                while (k < snake.size()) {
                    if(snake.contains(matrix[x][y])) {
                        k = snake.size() + 1;
                        flag = false;
                    } else {
                        k++;
                        flag = true;
                    }
                }
            }
            matrix[x][y].setFood();
            ifood = x;
            jfood = y;
        }
    Il problema è che ad un certo punto il cibo smette di essere generato.
    Come vedete nel metodo è presente anche un'altra versione del codice che fa la medesima cosa, ma il problema persiste.

    Il codice intero è questo:

    codice:
    import java.awt.GridLayout;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.util.LinkedList;
    import javax.swing.JPanel;
    
    
    public class Grid extends JPanel implements Runnable, KeyListener {
    
    
        private static final long serialVersionUID = 1L;
        private Cell matrix[][];
        private final int CELLE = 25;
        private int difficult;
        private enum Direction {UP,LEFT,RIGHT,DOWN};
        private Direction currentDirection;        
        private boolean inGame;
        private Cell foodCell;
        private boolean food;
        private int ihead;
        private int jhead;
        private int ifood;
        private int jfood;
        private LinkedList<Cell> snake;
        
        public Grid() {
            
            this.setLayout(new GridLayout(25,25));    
            matrix = new Cell[CELLE][CELLE];
            
            for(int i = 0; i < CELLE; i++) {
                for(int j = 0; j < CELLE; j++) {
                    matrix[i][j] = new Cell();
                    matrix[i][j].set_i(i);
                    matrix[i][j].set_j(j);
                    matrix[i][j].setEmpty();
                    add(matrix[i][j]);
                }
            }
                                          
            currentDirection = Direction.RIGHT;
            snake = new LinkedList<Cell>();
            inGame = true;
            setFocusable(true);
            addKeyListener(this);
            initGame();
        }
        
        private void initGame() {
            food = false;
            ihead = CELLE/2;
            jhead = CELLE/2;
            matrix[ihead][jhead].setSnakeHead();
            snake.addFirst(matrix[ihead][jhead]);
            for(int j = jhead-1; j > (jhead - 6); j--) {
                matrix[ihead][j].setSnake();
                snake.add(matrix[ihead][j]);
            }
        }
        
        @Override
        public void run() {
    
    
            while (inGame) {
    
    
                System.out.println("ihead: " + ihead + "," + " jhead: " + jhead);            
    
    
                if (!food) {
                    food = true;
                    generateFood();
                    System.out
                            .println("ifood: " + ifood + "," + " jfood: " + jfood);
                }
                
                if (ihead == ifood && jhead == jfood) {
                    food = false;
                    matrix[snake.getLast().get_i() - 1][snake.getLast().get_j() - 1]
                            .setSnake();
                    snake.addLast(matrix[snake.getLast().get_i() - 1][snake
                            .getLast().get_j() - 1]);
                    System.out.println("mangiato!");
                }
    
    
                if (currentDirection == Direction.LEFT) {
                    matrix[snake.getLast().get_i()][snake.getLast().get_j()]
                            .setEmpty();
                    snake.removeLast();
                    matrix[snake.getFirst().get_i()][jhead].setSnake();
                    jhead--;
                    matrix[ihead][jhead].setSnakeHead();
                    snake.addFirst(matrix[ihead][jhead]);
                    pause();
    
    
                }
                if (currentDirection == Direction.RIGHT) {
                    matrix[snake.getLast().get_i()][snake.getLast().get_j()]
                            .setEmpty();
                    snake.removeLast();
                    matrix[snake.getFirst().get_i()][jhead].setSnake();
                    jhead++;
                    matrix[ihead][jhead].setSnakeHead();
                    snake.addFirst(matrix[ihead][jhead]);
                    pause();
                }
                if (currentDirection == Direction.UP) {
                    matrix[snake.getLast().get_i()][snake.getLast().get_j()]
                            .setEmpty();
                    snake.removeLast();
                    matrix[ihead][snake.getFirst().get_j()].setSnake();
                    ihead--;
                    matrix[ihead][jhead].setSnakeHead();
                    snake.addFirst(matrix[ihead][jhead]);
                    pause();
                }
                if (currentDirection == Direction.DOWN) {
                    matrix[snake.getLast().get_i()][snake.getLast().get_j()]
                            .setEmpty();
                    snake.removeLast();
                    matrix[ihead][snake.getFirst().get_j()].setSnake();
                    ihead++;
                    matrix[ihead][jhead].setSnakeHead();
                    snake.addFirst(matrix[ihead][jhead]);
                    pause();
                }
            }
        }
        
        private void generateFood() {
            /*ifood = (int) (Math.random()*24);
            jfood = (int) (Math.random()*24);
            foodCell = matrix[ifood][jfood];
            while(snake.contains(foodCell)) {
                ifood = (int) (Math.random()*24);
                jfood = (int) (Math.random()*24);
                foodCell = matrix[ifood][jfood];
            }
            matrix[ifood][jfood].setFood();*/
            boolean flag = false;
            int x = 0, y = 0, k;
            while (!flag) {
                k = 0;
                x = (int) (Math.random() * CELLE);
                y = (int) (Math.random() * CELLE);
                while (k < snake.size()) {
                    if(snake.contains(matrix[x][y])) {
                        k = snake.size() + 1;
                        flag = false;
                    } else {
                        k++;
                        flag = true;
                    }
                }
            }
            matrix[x][y].setFood();
            ifood = x;
            jfood = y;
        }
        
        private void pause() {
            try {
                Thread.sleep(difficult);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        public void setDifficult(int diff) {
            difficult = diff;
        }
    
    
        @Override
        public void keyPressed(KeyEvent event) {
            if (event.getKeyCode() == KeyEvent.VK_LEFT) {
                left();
            }
            if (event.getKeyCode() == KeyEvent.VK_RIGHT) {
                right();
            }
            if (event.getKeyCode() == KeyEvent.VK_UP) {
                up();
            }
            if (event.getKeyCode() == KeyEvent.VK_DOWN) {
                down();
            }
        }
    
    
        private void left() {
            if(currentDirection != Direction.RIGHT) {
                currentDirection = Direction.LEFT;
            }
        }
        
        private void right() {
            if(currentDirection != Direction.LEFT) {
                currentDirection = Direction.RIGHT;
            }
        }
        
        private void up() {
            if(currentDirection != Direction.DOWN) {
                currentDirection = Direction.UP;
            }
        }
        
        private void down() {
            if(currentDirection != Direction.UP) {
                currentDirection = Direction.DOWN;
            }
        }
    
    
        @Override
        public void keyReleased(KeyEvent event) {}
    
    
        @Override
        public void keyTyped(KeyEvent event) {}
    }
    Ho scelto un modo intricato e particolare per muovere ed allungare il serpente, ma non mi è venuto in mente altro. Sono sempre stato disastroso nel giocare con gli indici delle matrici. E comunque il codice è debole anche nel caso in cui il serpente riesce a mangiare
    e di conseguenza si allunga, poiché potrei ottenere un ArrayIndexOutOfBoundsException in questo punto:

    codice:
    matrix[snake.getLast().get_i() - 1][snake.getLast().get_j() - 1]
                            .setSnake();
    Dato che se il serpente si sta muovendo lungo il bordo, gli indici vanno a finire fuori.

    Aggiornamento:

    Dovrei aver risolto la questione sulla generazione del cibo. Ho tolto i 3 pause() dentro il run() e ne ho messa una sola dopo tutti gli if.

    Rimane la questione dell'allungamento del serpente.. molto spinosa -.-

    Aggiornamento 2:

    Dovrei poter risolvere tramite la gestione di tutti i casi possibili -.-
    Ultima modifica di Javino89; 01-10-2013 a 14:04

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.