Oop lab/sokoban

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
หน้านี้เป็นส่วนหนึ่งของ oop lab

เกม Sokoban เป็นเกมปัญหาที่โด่งดังมากในอดีต ทดลองเล่นได้ที่ [1] หรือ [2]

ในเกมนี้ผู้เล่นจะเดินเข็นกล่องไปมาให้ไปอยู่ในตำแหน่งปลายทาง ผู้เล่นจะดันกล่องได้เท่านั้น (ดึงไม่ได้ถ้าดันไปติดกำแพงก็จบเกม) และจะสามารถดันกล่องได้แค่ใบเดียวเท่านั้น (ถ้าติดกันสองใบจะหนักเกิน ดันไม่ไหว)

เริ่มต้น

เราจะพัฒนาเกมดังกล่าวด้วยกระบวนการ TDD และหัดใช้ git ไปพร้อม ๆ กัน ดังนั้นให้สร้างโปรเจ็ค จากนั้นให้สร้าง git repository ของโปรเจ็คด้วย (ดูวิธีการได้ในคลิป egit)

กระดานเกมทั่วไป และการแสดงผล

ด้านล่างเป็นคลาส GameBoard และ unit test เบื้องต้น GameBoardTest

GameBoard.java

package sokoban;

public class GameBoard {

    private int height;
    private int width;
    private String[] baseBoard;
    private int playerRow;
    private int playerCol;
    private int numBoxes;
    private int[][] boxPositions;

    public GameBoard(String[] map) {
        loadBoard(map);
    }

    public void loadBoard(String[] map) {
        height = map.length;
        width = map[0].length();
        numBoxes = 0;
        boxPositions = new int[height*width][2];
        
        baseBoard = new String[height];
        for(int r = 0; r < height; r++) {
            baseBoard[r] = "";
            for(int c = 0; c < width; c++) {
                char mch = map[r].charAt(c);
                char sch = '.';
                switch(mch) {
                case 'A': 
                    playerRow = r;
                    playerCol = c;
                    break;
                case 'O':
                    boxPositions[numBoxes][0] = r;
                    boxPositions[numBoxes][1] = c;
                    numBoxes++;
                    break;
                default:
                    sch = mch;
                }
                baseBoard[r] += sch;
            }
        }
    }

    public int getHeight() {
        return height;
    }

    public int getWidth() {
        return width;
    }

    public int getPlayerRow() {
        return playerRow;
    }
    
    public int getPlayerCol() {
        return playerCol;
    }
    
    public void setPlayerPosition(int r, int c) {
        playerRow = r;
        playerCol = c;
    }

    public int getNumBoxes() {
        return numBoxes;
    }

    public int[] getBoxPosition(int i) {
        return new int[] { 
                boxPositions[i][0],
                boxPositions[i][1]
        };
    }
    
    public void setBoxPosition(int i, int r, int c) {
        boxPositions[i][0] = r;
        boxPositions[i][1] = c;
    }

    public boolean hasPlayerAt(int r, int c) {
        return (playerRow == r) && (playerCol == c);
    }
    
    public boolean hasBoxAt(int r, int c) {
        return false;
    }
    
    public boolean hasExitAt(int r, int c) {
        return false;
    }
    
    public String toString() {
        return "";
    }
}

GameBoardTest.java

package sokoban;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

public class GameBoardTest {

    static String smallBoardMap[] = {
        " #####",
        "#*O.A#",
        "#...O#",
        "##..*#",
        " #####"
    };
    private GameBoard smallBoard;

    @Before
    public void setUp() {
        smallBoard = new GameBoard(smallBoardMap);
    }
    
    @Test
    public void testLoadBoardProperties() {
        assertEquals(5, smallBoard.getHeight());
        assertEquals(6, smallBoard.getWidth());
    }

    @Test
    public void testLoadBoardPlayerPosition() {
        assertEquals(1, smallBoard.getPlayerRow());
        assertEquals(4, smallBoard.getPlayerCol());
    }
    
    @Test
    public void testLoadBoardNumBoxes() {
        assertEquals(2, smallBoard.getNumBoxes());
    }

    @Test
    public void testLoadBoardBoxPositions() {
        assertArrayEquals(new int[] {1, 2}, smallBoard.getBoxPosition(0));
        assertArrayEquals(new int[] {2, 4}, smallBoard.getBoxPosition(1));
    }    
    
    @Test
    public void testPlayerPositionCheck() {
        assertFalse(smallBoard.hasPlayerAt(0,0));
        assertTrue(smallBoard.hasPlayerAt(1,4));
    }
    
    @Test
    public void testPlayerPositionCheckAfterChange() {
        smallBoard.setPlayerPosition(2, 3);
        assertFalse(smallBoard.hasPlayerAt(1,4));
        assertTrue(smallBoard.hasPlayerAt(2, 3));
    }
}

การขยับ

เล่นเกมกัน!

เริ่มต้นใหม่และการถอยหลัง (undo)