The Development Of TwistGame Based On Java Technology

Outline

TwistGame is a fantastic board game, which involves the board, pegs, and pieces. Different challenges are identified by different initial positions of the pegs or pieces. The player wins after the objective of challenge has been achieved. This is my postgraduate project from October, 2018 to September, 2018.

在这里插入图片描述

Demo

UI:

Game process: (left to right)

Introduction

Components

Board

The game is played on a board comprised of 32 locations arranged in an 8x4 grid. In the plastic game, each location consists of a circular depression in the plastic into which a piece may fit, and in the centre of the depression is a hole (well) into which a peg may be inserted at the start of the game, to form part of the challenge. Locations are encoded as a digit (1 to 8) followed by a letter (A to D). For example, in the game above, the green peg is in position 3C and the red peg is in position 6B.

Pieces

The game comprises 8 playing shapes, each of which is made of plastic and consists of three, four, or five connected loops (see the photo above). The pieces fit neatly into the depressions on the board formed by the 32 locations. Each of the loops is either filled or has a hole. In the game above, the blue piece at the left has four loops, three of which are filled and one of which has a hole. When pieces are placed, the location and orientation must be chosen such that loops that are filled are not placed on locations that contain pegs. In the game above, for example, in the first step, a blue piece placed is carefully positioned so that one of its holes fits over the blue peg at location 2B. Each piece can be flipped and rotated at 90 degree increments, allowing for 8 different orientations (four rotations and a flip with four rotations). The following illustration shows all 64 possible combinations of the 8 pieces and 8 orientations. The first four columns show four rotations. The piece is then flipped and rotated four more times. So the fifth image in the top row (a4) illustrates the flip of the left-most image (a0).
在这里插入图片描述

Strict Symmetry
Notice that piece c and piece h are symmetric, so the flipped orientations are identical to the unflipped (for example c0 is
identical to c4, and h0 is identical to h4). We describe that as ‘strictly symmetric’. We ignore the redundant rotations
with higher numberings (e.g. c4 is ignored because it is redundant with respect to c0 and has a higher rotation number).

Weak Symmetry
Notice that if we ignore the holes, aside from a, d and g, all pieces exhibit symmetry. We describe these as ‘weakly
symmetric
’, and thus take up exactly the same space on the board. We ignore the redundant rotations with higher numberings (e.g.
if a solution could be made with either e0 or e7 then we ignore the solution with e7 because it is weakly symmetric and has a higher rotation number). Other examples include b0 & b2, c0 & c2, f0 & f6, and h0 & h2, each of which are identical pairs if we ignore the holes.

Pegs

The game has seven pegs. There are two green, two blue and two yellow pegs, but just one red peg. The pegs are not placed by the player during the game, but rather, one or more pegs is placed on the board at the start of the game as part of the challenge. In the example above, two blue, two yellow, one green and one red peg are placed to form the challenge, as well as a green piece. The player has to place the remaining pieces. The particular challenge illustrated above is challenge one in the booklet that comes with the IQ-Twist game.

Objective

The objective is to place all eight coloured playing pieces onto a board comprising 32 locations(4*8) (indents) on which up to seven coloured pegs may be arranged. The player must place the pieces such that they fit together correctly on the board, without overlaps or gaps. Also, each of the pegs must be surrounded by a piece of the same colour, meaning the piece must have a hole in the necessary place.
In the photo above, a blue peg at upper right is surrounded by a blue piece, with the peg fitting exactly into a hole in the blue piece. The player will need to place the green and red pieces so that they fit neatly on the green and red pegs, and to complete the game will need to ensure that all pieces are placed with no overlaps and no gaps.

A completed game:
A completed game:

Challenges

A game starts with a challenge which involves zero or one pieces and one or more pegs being placed. Here is what the game above starts like, ready to be solved (this happens to be challenge 1 that comes with the game). Notice that this particular challenge starts with one piece placed and six pegs placed :
在这里插入图片描述
Note that the more constrained the player is, the fewer options they have, and consequently the solution to the challenge is, in general, simpler: For example, many of the ‘Wizard’ level challenges that come with the game (e.g. numbers 118-120) have just three pegs placed, which leaves the player with a large number of placements to choose from, and thus creates a much more challenging game. On the other hand, some of the ‘Starter’ challenges (e.g. number 17) have all seven pegs and one piece placed, significantly reducing the player’s options and consequently making the challenge far easier.

Solutions

Each challenge has just one solution. When comparing solutions, we ignore piece rotations that take up the same space on the board. Such rotations are described as symmetric, which is defined in more detail below. The following sequence shows one possible progression of a solution to the game above (note that the order in which the pieces are played is not important; this is just one possible ordering).
8 pieces and 8 orientations

Placement Strings

Legal Piece Placements
For a piece placement to be valid, the following must be true:

  1. All loops comprising each piece must be placed on valid board locations (no part of a piece may be off the board).
  2. All loops comprising each piece must be placed on vacant board locations (pieces may not overlap).
  3. No piece may be placed over a peg, except where the peg is the same color and the location of the peg coincides with a loop that has a hole. For example, in the game above, the blue piece at the left is placed such that it fits on the peg at location 1C.

Encoding Game State
Game states are encoded as strings. Your game will need to be able to initialize itself using these strings and some of your tasks relate directly to these strings.

Placement Strings
A placement string consists of between one and eight (inclusive) piece placements (pieces a to h), and between zero and seven peg placements. The placement string may not include any piece twice, and may not include more pegs than are available. A completed game must include eight piece placements. Each piece placement is described using four characters.

For example, the game described above is characterized (when complete) by the string a7A7b6A7c1A3d2A6e2C3f3C4g4A7
h6D0i6B0j2B0j1C0k3C0l4B0l5C0. Note that the placement string is ordered (piece a first, and piece l last), which is a requirement for valid placement strings.

Piece Placement Strings
A piece placement string consists of four characters describing the location and orientation of one particular piece on the board:
The first character identifies which of the eight shapes is being placed (a to h).
The second character identifies which column the left of the piece is in (columns are labelled 1 to 8).
The third character identifies which row the top of the piece is in (rows are labelled A to D).
The fourth character identifies which orientation the piece is in (0 to 3 for four rotations, and then 4 to 7 for four flipped rotations).

The image above shows the first and fourth characters for each of the pieces in each of their orientations (64 in total).
For example, at top left, ‘a0’ describes piece ‘a’ at orientation ‘0’. Below it, ‘b0’ describes piece ‘b’ at orientation ‘0’.
At the bottom right ‘h7’ describes piece ‘h’ at orientation ‘7’. And so on. A piece placement string starts and ends with these two characters and has two more in between which describe where the piece is placed.

Peg Placement Strings
Peg placement strings follow exactly the same format as piece placement strings, however, pegs use the characters i (red), j
(blue), k (green), and l (yellow)
, and the rotation is always 0 for a peg placement, since it makes no sense to rotate a peg, which is round.

Example Placement String
The progression of twelve images above shows the progression of the game a7A7b6A7c1A3d2A6e2C3f3C4g4A7h6D0i6B0
j1C0k3C0l4B0l5C0, starting with the starting state f3C4i6B0j2B0j1C0k3C0l4B0l5C0, then adding piece d with its left in column 2, its top in row A, and rotated and flipped to rotation 6, which is encoded as a piece placement of d2A6. The resulting placement string is d2A6f3C4i6B0j2B0j1C0k3C0l4B0l5C0, etc.

Design Summary

There are 8 classes in this project:
GUI classes: Board, Peg, Piece, Shape, Music.
Logic classes: Loop, PieceIni, TwistGame.

Class Design

Peg

Main Idea: This class repesents the 4 different pegs.
Main Function: checkPeg(char name,char colum,char roww);
Explanation: This function can place correct peg to the board if given the name,column,row of this peg.

public static void checkPeg(char name,char colum,char roww)
    {
         /*change the size of peg i and put it to the right place*/
        int row = roww -'A';
        int column = colum -'1';
        ImageView tmp = new ImageView();
        tmp.setImage(new Image(Board.Peg_URLs[name-'i']));
        double width = tmp.getImage().getWidth();
        double height = tmp.getImage().getHeight();
        double col = column*40 - 0.3*width + 80;
        double ro = row*40 - 0.3*height + 120;       
        tmp.setX(col);
        tmp.setY(ro);
        tmp.setScaleY(0.4);
        tmp.setScaleX(0.4);
        controlpeg.getChildren().add(tmp);
        // public static final Group controlpeg = new Group();
    }

Piece

Main Idea: This class helps to drag and rotate the pieces in the board.
Main Function: iniboardpiece(String pegpiece);
Explanation: Initialize pieces of board and use mathmetical method to solve the rotate or flip problem.

1. Scroll(rotate and flip)

shapesTmp.setOnScroll(event -> {                                 
                    mouseX = event.getSceneX();
                    mouseY = event.getSceneY();
                    event.consume();//destroy instance
                    
                    if (PlacedRotation[x - 'a'] != -1)//x is piece name
                        rotateCount = PlacedRotation[x - 'a'];//the Count of rotation
                    rotateCount++;//scroll one more time
                    PlacedRotation[x - 'a'] = rotateCount;//update the number of rotation
                    
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (rotateCount % 8 <= 3) {//rotateCount = 1,2,3
                        shapesTmp.setScaleY(0.4);
                        shapesTmp.setRotate((shapesTmp.getRotate() + 90) % 360);
                    } else {
                        shapesTmp.setScaleY(-0.4);//rotateCount = 4,5,6,7
                        shapesTmp.setRotate((shapesTmp.getRotate() + 90) % 360);
                    }               
                });

2. Dragged

 shapesTmp.setOnMouseDragged(event -> {      // mouse is being dragged
                    double movementX = event.getSceneX() - mouseX;
                    double movementY = event.getSceneY() - mouseY;
                    shapesTmp.setLayoutX(shapesTmp.getLayoutX() + movementX);
                    shapesTmp.setLayoutY(shapesTmp.getLayoutY() + movementY);
                    shapesTmp.toFront();
                    mouseX = event.getSceneX();
                    mouseY = event.getSceneY();
                    event.consume();
                });

3. DragDetected

 shapesTmp.setOnDragDetected(event -> {
                    mouseStartX = mouseX;
                    mouseStartY = mouseY;
                });

4. MousePressed

shapesTmp.setOnMousePressed(event -> {//used to record final place of mouse 
                    mouseX = event.getSceneX();
                    mouseY = event.getSceneY();
                    event.consume();
                });

5. MouseReleased

  • Locate the place where the piece should be put and record the rotation times
                    finalX = mouseX;
                    finalY = mouseY;
                    double moveX = finalX - mouseStartX;
                    double moveY = finalY - mouseStartY;
                    double finalvertex_X;//the place where the piece should be put
                    double finalvertex_Y;

                    if (rotateCount % 2 == 1) {
                        finalvertex_X = column * 40 + moveX + Math.abs(0.5 * 0.4 * (height - width));
                        finalvertex_Y = roww * 40 + moveY - Math.abs(0.5 * 0.4 * (height - width));
                    } else {
                        finalvertex_X = column * 40 + moveX;
                        finalvertex_Y = roww * 40 + moveY;
                    }
  • The small Circle is used to help locate the piece
                    c = new Circle(finalvertex_X, finalvertex_Y, 0.5);               
                    c.setOpacity(50);
                    c.setFill(Color.WHITE);
                    iniboardpiece.getChildren().add(c);

                    /*used to test whether the placement of piece is true*/
                    Circle tmpc = findNearestNode(findNearestDistance(finalvertex_X, finalvertex_Y), finalvertex_X, finalvertex_Y);
                    int v_x = (int) (tmpc.getCenterX() - 80) / 40 + 1;
                    int v_y = (int) (tmpc.getCenterY() - 120) / 40;
                    char c_vy = (char) (v_y + 'A');
                    
                    if (rotateCount % 2 == 1) {
                        shapesTmp.setLayoutX(tmpc.getCenterX() - column * 40 - Math.abs(0.5 * 0.4 * (height - width)));//+ Math.abs(0.5*0.4*(height-width)
                        shapesTmp.setLayoutY(tmpc.getCenterY() - roww * 40 + Math.abs(0.5 * 0.4 * (height - width)));//- Math.abs(0.5*0.4*(height-width)
                    } else {
                        shapesTmp.setLayoutX(tmpc.getCenterX() - column * 40);
                        shapesTmp.setLayoutY(tmpc.getCenterY() - roww * 40);
                    }    
                    stmp = x + "" + v_x + "" + c_vy + "" + (rotateCount % 8);//a very important string
  • Try to insert the new piece to the place where the mouse is pointing
                    List<Character> list = new ArrayList<>();
                    List<Character> listofPieces = new ArrayList<>();
                    
                    if (validString.length() > 0) {                    
                        String lpeg = new String();
                        lpeg = pegpiece + validString.toString();
                        validString.replace(0, validString.length(), "");//update the valid string
                        
                        /*add peg to the valid string*/
                        TreeSet<String> ts = new TreeSet<>();
                        for (int k = 0; k < lpeg.length() / 4; k++) {
                            String str = lpeg.substring(k * 4, (k + 1) * 4);
                            ts.add(str);
                        }

                        String validstr = "";
                        for (String s : ts) {
                           validstr += s;
                        }
                        validString.append(validstr);
                    } else validString.append(pegpiece);

                    for (char c : validString.toString().toCharArray()) {
                        list.add(c);
                    }
                    for (char c : pegpiece.toCharArray()) {
                        if (c >= 'a' && c <= 'h') {
                            listofPieces.add(c);
                        }
                    }
                    int insertPos = 0;
                    int count = 0;
                    //find the position of character which before x
                    for (int q = 1; q < 8; q++) {
                        int indexc = list.indexOf((char) (x - q));
                        if (indexc != -1 && count == 0) {
                            insertPos = indexc + 4;
                            count++;
                        }
                    }
                    validString.insert(insertPos, stmp);//prepare to insert
  • Test whether the string is valid after inserting this new piece, if this piece is not valid ,show an wrong message and remove the string of this piece from validString
                    if (isPlacementStringValid(stmp)) {
                        if (!isPlacementStringValid(validString.toString())) {//in the board but not in right place
                            Music.PutfailMusic();                           
                            validString.replace(insertPos, insertPos + 4, "");
                            PlacedRotation[x - 'a'] = rotateCount;
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            shapesTmp.setLayoutX(0);
                            shapesTmp.setLayoutY(0);
                        } else {//place successfully
                             Music.PutsuccessMusic();
                        }
                    } else {               
                        Music.PutfailMusic();                       
                        System.out.println("fail to place ,out of board!!");
                        validString.replace(insertPos, insertPos + 4, "");
                        PlacedRotation[x - 'a'] = rotateCount;
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        shapesTmp.setLayoutX(0);
                        shapesTmp.setLayoutY(0);
                    }
  • Place the piece successfully
                    if (validString.length() >= 32) {
                        if (checkSuccess(validString.toString().substring(0, 32))) {                                              
                            place[x-'a'] = true;
                            Label success = new Label();//"congratulations,successful!!"
                            Image finish = new Image((Board.succ_URL));
                            success.setGraphic(new ImageView((finish)));
                            success.setLayoutX(160);
                            success.setLayoutY(160);
                            Music.playSuccessMusic();
                            iniboardpiece.getChildren().addAll(success);
                        }
                    }
                    subs = validString.toString();
                    int pegPos = 0;
                    int countPeg = 0;
                    int piecePos = 0;
  • Remove the peg string from validString
                    List<Character> list1 = new ArrayList<>();
                    for (char c : validString.toString().toCharArray()) {
                        list1.add(c);
                    }
                    for (Character c : list) {
                        if (countPeg == 0 && c >= 'i' && c <= 'l') {
                            pegPos = list1.indexOf(c);
                            countPeg++;
                        }
                    }
                    validString.replace(pegPos, validString.length(), "");  

                    for (Character c : listofPieces) {
                        //c is redundant  piece, c should be remove
                        piecePos = validString.toString().indexOf(c);
                        if (piecePos != -1)
                            validString.replace(piecePos, piecePos + 4, "");
                    }
                    /*check whether the valid string is finished,if finished, show successful message*/
                    rotateCount = 0;
                });
                

Shape

Main Idea: This class repesents the 8 different shapes
Main Function: checkShape(char name,int column,int row,int orientation);
Explanation: This function can place correct shape to the board if given the name,column,row,and orientation of this shape

 public static void checkShape(char name, char colum, char roww, int orientation, int tag) {
       
        int row = roww-'A';
        int column = colum -'1';
        int na = name -'a';
        
        ImageView tmp = new ImageView();
        tmp.setImage(new Image(Board.URLs[na]));
        tmp.setScaleX(0.4);
        
        double width = tmp.getImage().getWidth();
        double height = tmp.getImage().getHeight();
        double col = column*40 - 0.3*width + 80;
        double ro = row*40 - 0.3*height + 120;

        if(orientation %2 ==1 )
        {
           col = col  - Math.abs(0.5*0.4*(height-width)) ;
           ro = ro + Math.abs(0.5*0.4*(height-width));
        }

        if (orientation < 4) {
           tmp.setScaleY(0.4);
           tmp.setX(col);
           tmp.setY(ro);
           tmp.setRotate(orientation * 90);
           } else if(orientation >= 4){
             tmp.setX(col);
             tmp.setY(ro);
             tmp.setRotate(orientation  * 90);
             tmp.setScaleY(-0.4);
             }
             
         if (tag == 0){
                  controlshapes.getChildren().addAll(tmp);
         }else {
                  tmp.setOpacity(0.5);
                  controlshapes.getChildren().addAll(tmp);
         } 
    }

Music

Main Idea: This class contain 3 different musics this game will use.

  1. Success
  2. Fail to put pieces
  3. Put pieces successfully
private static final String URL_BASE = "assets/";
private static final String m_URL = Board.class.getResource(URL_BASE + "start.mp3").toString();
private static AudioClip start = new AudioClip(m_URL);
public static void playStartMusic() {
        start.play();
    }

Loop

Main Idea: This class repesents the loop which has two attributes x and y and then uses 2 arraylists to store all the loops or depressions of each piec
Take Arraylist that stores the data of depressions as an example:

 /*each piece has depressions*/
    static int[] aDep = {0,2};
    static int[] bDep = {2};
    static int[] cDep = {1};
    static int[] dDep = {2,4};
    static int[] eDep = {1,2};
    static int[] fDep = {2,3};
    static int[] gDep = {0,1,3};
    static int[] hDep = {0};

 static List<int[]>piecedeps = new ArrayList<>();//arraylist to store all the depressions of each piece

     static void iniPieceDep() {//add nodes to the piecedeps
        piecedeps.add(aDep);
        piecedeps.add(bDep);
        piecedeps.add(cDep);
        piecedeps.add(dDep);
        piecedeps.add(eDep);
        piecedeps.add(fDep);
        piecedeps.add(gDep);
        piecedeps.add(hDep);
    }
   

PieceIni

Main Idea: This class realizes the rotation and flip of shapes

public class PiecesIni{
    /*initialize all the first shape of 8 pieces like a0,b0,c0,d0,e0,f0,g0,h0 and their depression placement*/
    static void IniLoopAndDepress()
    {
        Loop.iniPieceDep();
        Loop.iniPieceLoop();
    }

    /*loop[] means a loops of each piece ,and every piece can be rotated to specific degree
     * when rotateTime is 0,it means the first shape of this piece
     * one rotateTime means 90 degree rotation
     * rotateTime = 1,2,3 means  a1,a2,a3
     * this function includes some mathmetical transformations
     */
    static Loop[] rotate(Loop[] shape,int rotateTime)//totate-->1 90
    {
        Loop[] shaperotate = new Loop[shape.length];
        int max = shape[0].y;
        for (int i = 0; i < shape.length; i++) {
            if (shape[i].y > max) {
                max = shape[i].y;
            }
        }

        for (int i = 0; i < shape.length; i++) {
            shaperotate[i] = new Loop(0,0);
            shaperotate[i].x = shape[i].y * (-1) + max + 1;
            shaperotate[i].y = shape[i].x;
        }
        if (rotateTime == 0) return shape;
        else  if (rotateTime == 1) return shaperotate;
        else return rotate(shaperotate, rotateTime - 1);
    }    
    /*
     * every piece can be flipped when given specific fliptime
     * fliptime = 1,2,3,4 means a4,a5,a6,a7
     */
    static Loop[] flip(Loop[] shape,int flipTime)//
    {
        Loop[] shapeflip = new Loop[shape.length] ;
        int max = shape[0].y;
        for (int i = 0; i < shape.length; i++) {
            if (shape[i].y > max) {
                max = shape[i].y;
            }
        }
        for (int i = 0; i < shape.length; i++) {
            shapeflip[i] = new Loop(0, 0);
            shapeflip[i].x = shape[i].x;
            shapeflip[i].y = shape[i].y * (-1) + max + 1;
        }
        if (flipTime == 1) return shapeflip;
        else return rotate(shapeflip,  flipTime - 1);
    }
}

TwistGame

Main Idea: This class provides the interface for the Twist Game
Some functions:

public static boolean isPlacementWellFormed(String piecePlacement);//determine whether a piece or peg placement is well-formed
 public static boolean isPlacementStringWellFormed(String placement);//determine whether a placement is well-formed
 public static boolean isPlacementStringValid(String placement); // determine whether a placement string is valid
 public static Set<String> getViablePiecePlacements(String placement);//determine the set of valid next piece placements

Two important functions: getSolutions and InsertOfList
Main Idea: Since we can use fuction:getViablePiecePlacements() to get all the viable set of string, for example, if we get viable set like this: a1A0,a1C0,b1D2,b2C2,c2B1,c3B1. we will check whether these strings are valid:
a1A0b1D2c2B1,a1A0b1D2c3B1,a1A0b2C2c2B1,a1A0b2C2c3B1,
a1C0b1D2c2B1,a1C0b1D2c3B1,a1C0b2C2c3B1,a1C0b2C2c2B1.
在这里插入图片描述so in order to find the right place to insert, I design a function named: insertOfList().

getSolutions:
For example, if we get viable set like this: a1A0,a1C4,b1D5,b2C8, we will check whether these strings are valid: a1A0b1D5,a1A0b2C8,a1C4b1D5,a1C4b2C8.

    public static String[] getSolutions(String placement) {
        /* the tree order of all solution strings(a1A0,a1C4,b1D5,b2C8),
         * the start character of all solution strings(a,a,a,a,b,b,b,b,b)*/
        TreeSet<String> placeTreeSet = new TreeSet<>();
        
        /* in order to calculate the amount of different characters(a,b,c,d)
         * valueset stores the first character of all these viable strings (like a,b,c,no duplicates)*/
        Set<Character> valueset = new HashSet<>();
        List<TreeSet<String>> treeSetlist = new ArrayList<>();//all treesets
        
        //the value of each map is the first character of this string
        Map<String, Character> smap = new HashMap<>();
       
        //all possible solutions:(a1A0,b1D5,a1C4,b2C8)
        Set<String> placementSet = getViablePiecePlacements(placement);
        
        //change placement into the stringbuffer,it will be convenient for us to operate
        StringBuffer validString = new StringBuffer();
       
        List<String> l = new ArrayList<>();//store the results of this function
        TreeSet<String> TreeSetOfs;

        for (String s : placementSet) { //all the viable string of pieces
            placeTreeSet.add(s);
        }
        for (String s : placeTreeSet) {
        //string as the key ,the first character of this string as the value,put them into the map
            smap.put(s, s.charAt(0));
            valueset.add(s.charAt(0));
        }

        /*  use different treesets to store the viable string of each piece
         *  just like we get viable pieces like this: a1A0,b1D5,a1C4,b2C8
         *  then we can get: 
         *  treeSetlist.get(0) :a1A0a1C4 and 
         *  treeSetlist.get(1) :b1D5b2C8 
         */
        for (Character s : valueset) {
            int i = 0;
            TreeSetOfs = new TreeSet<>();
            for (Map.Entry<String, Character> entry : smap.entrySet()) {
                if (entry.getValue().equals(s)) {
                    TreeSetOfs.add(entry.getKey());
                }
            }
            treeSetlist.add(TreeSetOfs);
            i++;
        }

        for (char p : placement.toCharArray()) {
            validString.append(p);
        }
        // the most important part:recursive
        insertOfList(valueset.size() - 1, treeSetlist, validString, l);
        String[] sus = new String[l.size()]; //change list into String[]
        for (int i = 0; i < l.size(); i++) {
            sus[i] = l.get(i);
        }
        return sus;
    }

insertOfList: try to find all possible placements of given viable strings

    // 
    static void insertOfList(int n, List<TreeSet<String>> treeSetlist, StringBuffer validString, List<String> l) {
        if (n >= 0) {
            for (String s : treeSetlist.get(n)) {
                int insertPos = 0;
                int count = 0;
                /*
                find the character which is the fisrt character smaller than s.charAt(0)(like b of b1D5),
                we will find a in the existed placement, then we can insert b1D5 to the position of a plus 4
                if this character element does not exist,the position of inserting this piece(b1D5) will be 0
                */
                for (int q = 1; q < 8; q++) {
                    int indexc = validString.toString().indexOf((char) (s.charAt(0) - q));
                    if (indexc != -1 && count == 0) {
                        insertPos = indexc + 4;
                        count++;
                    }
                }
                validString.insert(insertPos, s);
                insertOfList(n - 1, treeSetlist, validString, l);//recursive
                //if all the pieces have been put to the string,we need to check whether this string placement is valid
               
                if (n == 0 && isPlacementStringValid(validString.toString())) {
                    if (isPlacementStringValid(validString.toString().substring(0, 32)))
                        l.add(validString.toString().substring(0, 32));
                }
                //we need to remove this piece in order to put other placement of this piece to the string
                validString.replace(insertPos, insertPos + 4, "");
            }
        }
    }

Conclusion

This was a big assignment of the ANU comp6710 course. The Lecturer provided us with a game pattern based on Twistgame, that is, the content mentioned in the introduction part and the test codes of some game logics. In this project, to write all codes except the test codes from scratch, I mastered a lot of java programming skills and theoretical knowledge. This project mainly contained 8 classes, and the most complex one was the Twistgame class that called other classes to achieve the whole UI and game logic.

In the process of game design, I encountered with many problems. Taking the operation on each piece for example, how to correctly decide where the piece should be placed was particularly important when I put the piece on the left board after rotating the piece from the toolbar on the right. To solve this problem, I created a virtual board containing 8*4 circles according to the board structure. Every time when the piece is dragged and placed, the code will calculate the distance between the coordinate where it is dragged and the circles so as to select the nearest circle as a fixed point to place the piece on the board. For piece rotation, the rules of coordinate changes when different pieces rotated should be found according to corresponding mathematical formulas.

The most difficult function to achieve is to get game hints, which was relating to recursion. A poor design will consume a great deal of computer resources. Thus, as summarized in the article, I designed an insertOfList function that mainly took charge of recursive to find all possible placements of given viable strings.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值