Hi everyone. I have to do a simple Sokoban game, but I am new in Java and I really don't know how to begin. If you can help me with some advices or tutorials I'll be very thankful.

Recommended Answers

All 5 Replies

Where do you have problems with in specific?
I'd suggest you to perform a Google search on 'Sokoban', look at existing implementations, play a couple of them and see how it works.
Familiarize yourself with the rules of the game. Start coding, and when you encounter problems come back and ask for help.

Of course what you really want is a 2D array to store the current state of the game, an x and y variable to store the current location of your little warehouse manager guy, a list of (x,y) target points for the boxes, a javax.swing.JPanel to draw everything, and a java.awt.event.KeyListener on that JPanel to allow the keyboard to control the warehouse worker. Once you have that, you are practically done except for the frills.

Here is a code for the Sobokan Board. I took it from http://zetcode.com/tutorials/javagamestutorial/sokoban/, and I made some changes.
I get an error:Exception in thread "main" java.lang.NullPointerException

package sokoban;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Board extends JPanel
{

    private final int DISTANCE_BORDER_GAMEGRAPHICS = 30;
    private final int SPACE = 20;
    private final int LEFT_COLLISION = 1;
    private final int RIGHT_COLLISION = 2;
    private final int UP_COLLISION = 3;
    private final int DOWN_COLLISION = 4;

    private  ArrayList<Wall> Walls;
    private  ArrayList<Objective> Objectives;
    private  ArrayList<Box> Boxes;

     private Player soko;
     private int width = 0;
     private int height = 0;
     private boolean completed = false;

     private String level =
             "    ######\n"
           + "    ##** #\n"
           + "    ##$  #\n"
           + "  #### @ $##\n"
           + "  #########\n";


     public Board() {

            addKeyListener(new SokoAdapter());
            setFocusable(true);
            initiateGame();
        }

     public int getBoardWidth() {
            return this.width;
        }

     public int getBoardHeight() {
            return this.height;
        }

     public final void initiateGame() {

            int x = DISTANCE_BORDER_GAMEGRAPHICS;
            int y = DISTANCE_BORDER_GAMEGRAPHICS;

            Wall wall;
            Box box;
            Objective objective;


            for (int i = 0; i < level.length(); i++) {

                char item = level.charAt(i);

                if (item == '\n') {
                    y += SPACE;
                    if (this.width < x) {
                        this.width = x;
                    }
                    x = DISTANCE_BORDER_GAMEGRAPHICS;
                } else if (item == '#') {
                    wall = new Wall(x, y);
                    Walls.add(wall);
                    x += SPACE;
                } else if (item == '$') {
                    box = new Box(x, y);
                    Boxes.add(box);
                    x += SPACE;
                } else if (item == '*') {
                    objective = new Objective(x, y);
                    Objectives.add(objective);
                    x += SPACE;
                } else if (item == '@') {
                    soko = new Player(x, y);
                    x += SPACE;
                } else if (item == ' ') {
                    x += SPACE;
                }

                height = y;
            }
        }

     public void buildGame(Graphics g) {

            g.setColor(new Color(250, 240, 170));
            g.fillRect(0, 0, this.getWidth(), this.getHeight());

            ArrayList world = new ArrayList();
            world.addAll(Walls);
            world.addAll(Objectives);
            world.addAll(Boxes);
            world.add(soko);

            for (int i = 0; i < world.size(); i++) {

                Actor item = (Actor) world.get(i);

                if ((item instanceof Player)
                        || (item instanceof Box)) {
                    g.drawImage(item.getImage(), item.x() + 2, item.y() + 2, this);
                } else {
                    g.drawImage(item.getImage(), item.x(), item.y(), this);
                }

                if (completed) {
                    g.setColor(new Color(0, 0, 0));
                    g.drawString("Completed", 25, 20);
                }

            }
        }

     @Override
        public void paint(Graphics g) {
            super.paint(g);
            buildGame(g);
        }

        class SokoAdapter extends KeyAdapter {

            @Override
            public void keyPressed(KeyEvent e) {

                if (completed) {
                    return;
                }


                int key = e.getKeyCode();


                if (key == KeyEvent.VK_LEFT) {
                    if (checkWallCollision(soko, LEFT_COLLISION)) {
                        return;
                    }

                    if (checkBoxCollision(LEFT_COLLISION)) {
                        return;
                    }

                    soko.move(-SPACE, 0);

                } else if (key == KeyEvent.VK_RIGHT) {

                    if (checkWallCollision(soko,
                            RIGHT_COLLISION)) {
                        return;
                    }

                    if (checkBoxCollision(RIGHT_COLLISION)) {
                        return;
                    }

                    soko.move(SPACE, 0);

                } else if (key == KeyEvent.VK_UP) {

                    if (checkWallCollision(soko,
                            UP_COLLISION)) {
                        return;
                    }

                    if (checkBoxCollision(UP_COLLISION)) {
                        return;
                    }

                    soko.move(0, -SPACE);

                } else if (key == KeyEvent.VK_DOWN) {

                    if (checkWallCollision(soko,
                            DOWN_COLLISION)) {
                        return;
                    }

                    if (checkBoxCollision(DOWN_COLLISION)) {
                        return;
                    }

                    soko.move(0, SPACE);

                } else if (key == KeyEvent.VK_R) {
                    restartLevel();
                }

                repaint();
            }
        }

        private boolean checkWallCollision(Actor actor, int type) {

            if (type == LEFT_COLLISION) {

                for (int i = 0; i < Walls.size(); i++) {
                    Wall wall = (Wall) Walls.get(i);
                    if (actor.isLeftCollision(wall)) {
                        return true;
                    }
                }
                return false;

            } else if (type == RIGHT_COLLISION) {

                for (int i = 0; i < Walls.size(); i++) {
                    Wall wall = (Wall) Walls.get(i);
                    if (actor.isRightCollision(wall)) {
                        return true;
                    }
                }
                return false;

            } else if (type == UP_COLLISION) {

                for (int i = 0; i < Walls.size(); i++) {
                    Wall wall = (Wall) Walls.get(i);
                    if (actor.isTopCollision(wall)) {
                        return true;
                    }
                }
                return false;

            } else if (type == DOWN_COLLISION) {

                for (int i = 0; i < Walls.size(); i++) {
                    Wall wall = (Wall) Walls.get(i);
                    if (actor.isBottomCollision(wall)) {
                        return true;
                    }
                }
                return false;
            }
            return false;
        }

        private boolean checkBoxCollision(int type) {

            if (type == LEFT_COLLISION) {

                for (int i = 0; i < Boxes.size(); i++) {

                    Box box = (Box) Boxes.get(i);
                    if (soko.isLeftCollision(box)) {

                        for (int j=0; j < Boxes.size(); j++) {
                            Box item = (Box) Boxes.get(j);
                            if (!box.equals(item)) {
                                if (box.isLeftCollision(item)) {
                                    return true;
                                }
                            }
                            if (checkWallCollision(box,
                                    LEFT_COLLISION)) {
                                return true;
                            }
                        }
                        box.move(-SPACE, 0);
                        isCompleted();
                    }
                }
                return false;

            } else if (type == RIGHT_COLLISION) {

                for (int i = 0; i < Boxes.size(); i++) {

                    Box box = (Box) Boxes.get(i);
                    if (soko.isRightCollision(box)) {
                        for (int j=0; j < Boxes.size(); j++) {

                            Box item = (Box) Boxes.get(j);
                            if (!box.equals(item)) {
                                if (box.isRightCollision(item)) {
                                    return true;
                                }
                            }
                            if (checkWallCollision(box,
                                    RIGHT_COLLISION)) {
                                return true;
                            }
                        }
                        box.move(SPACE, 0);
                        isCompleted();                   
                    }
                }
                return false;

            } else if (type == UP_COLLISION) {

                for (int i = 0; i < Boxes.size(); i++) {

                    Box box = (Box) Boxes.get(i);
                    if (soko.isTopCollision(box)) {
                        for (int j = 0; j < Boxes.size(); j++) {

                            Box item = (Box) Boxes.get(j);
                            if (!box.equals(item)) {
                                if (box.isTopCollision(item)) {
                                    return true;
                                }
                            }
                            if (checkWallCollision(box,
                                    UP_COLLISION)) {
                                return true;
                            }
                        }
                        box.move(0, -SPACE);
                        isCompleted();
                    }
                }

                return false;

            } else if (type == DOWN_COLLISION) {

                for (int i = 0; i < Boxes.size(); i++) {

                    Box box = (Box) Boxes.get(i);
                    if (soko.isBottomCollision(box)) {
                        for (int j = 0; j < Boxes.size(); j++) {

                            Box item = (Box) Boxes.get(j);
                            if (!box.equals(item)) {
                                if (box.isBottomCollision(item)) {
                                    return true;
                                }
                            }
                            if (checkWallCollision(box,
                                    DOWN_COLLISION)) {
                                return true;
                            }
                        }
                        box.move(0, SPACE);
                        isCompleted();
                    }
                }
            }

            return false;
        }

        public void isCompleted() {

            int num = Boxes.size();
            int compl = 0;

            for (int i = 0; i < num; i++) {
                Box box = (Box) Boxes.get(i);
                for (int j = 0; j < num; j++) {
                    Objective Objective = (Objective) Objectives.get(j);
                    if (box.x() == Objective.x()
                            && box.y() == Objective.y()) {
                        compl += 1;
                    }
                }
            }

            if (compl == num) {
                completed = true;
                repaint();
            }
        }

        public void restartLevel() {

            Objectives.clear();
            Boxes.clear();
            Walls.clear();
            initiateGame();
            if (completed) {
                completed = false;
            }
        }
    } 

I suggest that you make one yourself from scratch. It's really a nice simple game that can be made from scratch without excessive effort. The way it is done above is certainly using excessive effort. Instead of using a 2D array to represent the board, it is using sprites and collision detection for no apparent reason. I would abandon that whole implementation of Sokoban and make something simpler if I were you.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.