diff -r 000000000000 -r 56477205fdb5 minesweeper/src/main/java/org/apidesign/demo/minesweeper/MinesModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/minesweeper/src/main/java/org/apidesign/demo/minesweeper/MinesModel.java Fri Feb 07 14:47:07 2014 +0100 @@ -0,0 +1,126 @@ +/** + * The MIT License (MIT) + * + * Copyright (C) 2013 Jaroslav Tulach + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.apidesign.demo.minesweeper; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import net.java.html.json.ComputedProperty; +import net.java.html.json.Function; +import net.java.html.json.Model; +import net.java.html.json.ModelOperation; +import net.java.html.json.Property; + +/** Model of the mine field. + */ +@Model(className = "Mines", properties = { + @Property(name = "state", type = MinesModel.GameState.class), + @Property(name = "rows", type = Row.class, array = true), +}) +final class MinesModel { + enum GameState { + IN_PROGRESS, WON, LOST; + } + + @Model(className = "Row", properties = { + @Property(name = "columns", type = Square.class, array = true) + }) + static class RowModel { + } + + @Model(className = "Square", properties = { + @Property(name = "state", type = SquareType.class), + @Property(name = "mine", type = boolean.class) + }) + static class SquareModel { + @ComputedProperty static String text(SquareType state) { + if (state == null) return " "; + switch (state) { + case MINE: return "B"; + case UNKNOWN: return "?"; + case N_0: return " "; + } + return "" + state.ordinal(); + } + } + + enum SquareType { + N_0, N_1, N_2, N_3, N_4, N_5, N_6, N_7, N_8, + UNKNOWN, MINE + } + + @ModelOperation static void init(Mines model, int width, int height, int mines) { + List rows = new ArrayList(height); + for (int y = 0; y < height; y++) { + Square[] columns = new Square[width]; + for (int x = 0; x < width; x++) { + columns[x] = new Square(SquareType.UNKNOWN, false); + } + rows.add(new Row(columns)); + } + + Random r = new Random(); + while (mines > 0) { + int x = r.nextInt(width); + int y = r.nextInt(height); + final Square s = rows.get(y).getColumns().get(x); + if (s.isMine()) { + continue; + } + s.setMine(true); + mines--; + } + + model.setState(GameState.IN_PROGRESS); + model.getRows().clear(); + model.getRows().addAll(rows); + } + + static void showAllBombs(Mines model) { + for (Row row : model.getRows()) { + for (Square square : row.getColumns()) { + if (square.isMine()) { + square.setState(SquareType.MINE); + } + } + } + } + + @Function static void click(Mines model, Square data) { + if (model.getState() != GameState.IN_PROGRESS) { + return; + } + + switch (data.getState()) { + case UNKNOWN: + if (data.isMine()) { + showAllBombs(model); + model.setState(GameState.LOST); + } else { + data.setState(SquareType.N_0); + } + break; + } + } +}