Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Excerpt

Denne siden illustrerer bruken av rutenettspill-klassene ImageGridGame og ImageGrid ved å forklare hvordan eksempelspillet Bubble er programmert.

Bubble-spillet

Bubble-spillet legger ut ikoner i et rutenett, som vist til venstre. Brukeren kan klikke på ikoner som er inntil andre ikon av samme type, og alle ikonene som henger sammen vil da forsvinne. De gjenværende ikonene vil falle ned og fylle hullene og nye ikoner vil etterfylle tomrommene som da oppstår i toppen. Hvis en f.eks. klikker i ruta nederst til venstre, så vil tre skjermikoner forsvinne og kolonne nr. 1 og 2 vil falle ned henholdsvis 1 og 2 ruter.  

Det gis poeng etter hvor mange ikoner som klikkes bort, og siden poengene øker med kvadratet av antall ikoner (antall ikoner * antall ikoner), så er det en fordel å planlegge slik at en samler flest mulig ikoner før de klikkes bort. I tilfellet nevnt over, så vil en få 9 poeng, siden 3 ruter ble klikket bort og 3 * 3 = 9.

Koden

Koden (Java og FXML) er gjengitt nederst. Her forklares hovedtrekkene i virkemåten, med fokus på hvordan felt og metoder i ImageGridGame og ImageGrid brukes. Merk at du i tillegg til filene Bubbles.java og Bubbles.fxml også trenger ikoner med navn tilsvarende imageNames-lista i Bubbles.fxml. Alle filene finnes dessuten på github, bare følg lenkene: Bubbles.java og Bubbles.fxml, ImageGridGame.java og ImageGrid.java.

FXML-filen (under til høyre) beskriver innholder i GUI-et og inneholder navn som må stemme med felt og metoder i Bubbles.java:

  • imageNames er en liste (ArrayList) med navn på ikonene/bildene som brukes, og er et felt Bubbles
  • imageGrid er (visningen av) rutenettet og er et felt i ImageGridGame
  • newAction er navnet på metoden i Bubbles som kjøres når brukeren klikker på "New game"-knappen (for å starte et nytt spill)
  • mouseClicked er navnet å metoden i ImageGridGame som kjøres når brukeren klikker på en rute i rutenettet

 

Code Block
languagejava
titleBubbles.java
collapsetrue
package trinn2;
import java.util.List;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class Bubbles extends ImageGridGame<String> {
    @FXML
    Label statusLabel;
    
    @FXML
    List<String> imageNames;
    int points = 0;
    
    @FXML
    protected void initialize() {
        super.initialize();
        newAction();
    }
    String getRandomImageName() {
        int imageNum = randomInt(0, imageNames.size() - 1);
        return imageNames.get(imageNum);
    }
    @FXML
    void newAction() {
        fillGrid(null);
        refillCells();
        points = 0;
        updateGrid();
    }
    @Override
    protected void updateGrid() {
        super.updateGrid();
        statusLabel.setText(points + " points. Remaining possibilities: " + countPossibilities());
    }
    @Override
    void mouseClicked(int x, int y) {
        final int count = burstCells(getCell(x, y), x, y, 1);
        if (count > 0) {
            updateGrid();
            runDelayed(200,
                    () -> {
                        collapseCells();
                        updateGrid();
                    },
                    () -> {
                        refillCells();
                        points += count * count;
                        updateGrid();
                    }
            );
        }
    }
    int burstCells(String value, int x, int y, int limit) {
        if (x < 0 || x >= imageGrid.getColumnCount() || y < 0 || y >= imageGrid.getRowCount()) {
            return 0;
        }
        String cell = getCell(x, y);
        if (cell != null && cell == value) {
            setCell(x, y, null);
            int count =
                    burstCells(value, x - 1, y, limit - 1) +
                    burstCells(value, x, y - 1, limit - 1) +
                    burstCells(value, x + 1, y, limit - 1) +
                    burstCells(value, x, y + 1, limit - 1);
            if (count < limit) {
                setCell(x, y, cell);
            }
            return 1 + count;
        }
        return 0;
    }
    
    void collapseCells() {
        for (int x = 0; x < imageGrid.getColumnCount(); x++) {
            int dropCount = 0;
            for (int y = imageGrid.getRowCount() - 1; y >= 0; y--) {
                String cell = getCell(x, y);
                if (cell == null) {
                    dropCount++;
                } else if (dropCount > 0) {
                    setCell(x, y + dropCount, cell);
                    setCell(x, y, null);
                }
            }
        }
    }
    void refillCells() {
        foreachCell((x, y) -> {
            if (getCell(x, y) == null) {
                setCell(x, y, getRandomImageName());
            }
        });
    }
    int countPossibilities() {
        return countCells((int x, int y) -> (burstCells(getCell(x, y), x, y, Integer.MAX_VALUE) > 1 ? 1 : 0));
    }
    //
    
    public static void main(String[] args) {
        launch(args);
    }
}
Code Block
languagejavafx
titleBubbles.fxml
collapsetrue
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.layout.BorderPane?>
<?import trinn2.ImageGrid?>

<?import java.lang.String?>
<?import java.util.ArrayList?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Button?>

<BorderPane xmlns:fx="http://javafx.com/fxml">
    <fx:define>
        <ArrayList fx:id="imageNames">
            <String fx:value="Chat"/>
            <String fx:value="Clock"/>
            <String fx:value="Friends"/>
            <String fx:value="Home"/>
            <String fx:value="Mail"/>
            <String fx:value="Movie"/>
            <String fx:value="Music"/>
            <String fx:value="Phone"/>
            <String fx:value="Search"/>
        </ArrayList>
    </fx:define>
     <top>
         <Button text="New game" onAction="#newAction"/>
     </top>
     <center>
        <ImageGrid fx:id="imageGrid" 
            onMouseClicked="#mouseClicked"
            columnCount="8" rowCount="7"
            imageUrlFormat="/trinn2/${key}.png"
            >
        </ImageGrid>
     </center>
     <bottom>
         <Label fx:id="statusLabel" text="Status"/>
     </bottom>
</BorderPane>