/* "Dots" -- A simple Java applet-based puzzle game Copyright (c) 1999 Aaron Hertzmann http://www.mrl.nyu.edu/hertzmann This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. The GNU Public license is available at www.fsf.org. Notes: * For instructions on how to play and other information, please visit http://www.mrl.nyu.edu/hertzmann/dots * This was written in 1996, with Java 1.0. I haven't made any attempt to clean it up for distribution, but it's not too complicated. * To compile this program with a command-line javac compiler, just type: % javac Dots.java */ import java.awt.*; import java.applet.*; import java.util.Random; import java.util.Vector; public class Dots extends Applet { public void init() { setLayout(new BorderLayout()); Label messageLabel = new Label("\"Dots\" by Aaron Hertzmann"); add("North",messageLabel); DrawPanel dp = new DrawPanel(messageLabel); add("Center", dp); add("South",new DrawControls(dp)); } public boolean handleEvent(Event e) { switch (e.id) { case Event.WINDOW_DESTROY: System.exit(0); return true; default: return false; } } public static void main(String args[]) { Frame f = new Frame("Dots"); Dots Dots = new Dots(); Dots.init(); Dots.start(); f.add("Center", Dots); f.resize(400, 400); f.show(); } } class DrawPanel extends Panel { Board board; Checkbox answerBox; public DrawPanel(Label ml) { setBackground(Color.white); answerBox = new Checkbox("Answer"); board = new Board(ml,answerBox); } public boolean handleEvent(Event e) { switch (e.id) { case Event.MOUSE_DOWN: board.mouseDown(e,getGraphics()); return false; case Event.WINDOW_DESTROY: System.exit(0); return true; default: return false; } } public void paint(Graphics g) { Rectangle r = bounds(); board.screenWidth = r.width; board.screenHeight = r.height; board.drawBoard(g); board.fillBoard(g); } void newBoard() { Graphics g = getGraphics(); Rectangle r = bounds(); g.clearRect(0,0,r.width,r.height); board.newBoard(); board.drawBoard(g); } void newSize(int size) { board.width = board.height = size; newBoard(); } void newProb(int p) { board.probability = p; newBoard(); } void erase() { board.erase(getGraphics()); } void answer(boolean b) { board.answer = b; repaint(); } void setBW(boolean bw) { board.blackAndWhite = bw; repaint(); } } class DrawControls extends Panel { DrawPanel target; public DrawControls(DrawPanel target) { this.target = target; setLayout(new FlowLayout()); setBackground(Color.lightGray); add(new Button("New")); add(new Button("Erase")); add(target.answerBox); Choice menu = new Choice(); menu.addItem("2x2"); menu.addItem("5x5"); menu.addItem("10x10"); menu.addItem("12x12"); menu.addItem("15x15"); menu.addItem("20x20"); menu.setBackground(Color.lightGray); menu.select("10x10"); add(menu); Choice p = new Choice(); p.addItem("25%"); p.addItem("40%"); p.addItem("45%"); p.addItem("50%"); p.addItem("55%"); p.addItem("60%"); p.select("50%"); add(p); add(new Button("Custom")); add(new Checkbox("B&W")); } public void paint(Graphics g) { Rectangle r = bounds(); g.setColor(Color.lightGray); g.draw3DRect(0, 0, r.width, r.height, false); } public boolean action(Event e, Object arg) { if (e.target instanceof Button) { String choice = (String)arg; if (arg.equals("New")) target.newBoard(); else if (arg.equals("Erase")) target.erase(); else if (choice.equals("Custom")) { CustomFrame cf = new CustomFrame(target); } } else if (e.target instanceof Choice) { String choice = (String)arg; if (choice.equals("2x2")) target.newSize(2); else if (choice.equals("5x5")) target.newSize(5); else if (choice.equals("10x10")) target.newSize(10); else if (choice.equals("15x15")) target.newSize(15); else if (choice.equals("12x12")) target.newSize(12); else if (choice.equals("20x20")) target.newSize(20); else if (choice.equals("25%")) target.newProb(25); else if (choice.equals("40%")) target.newProb(40); else if (choice.equals("45%")) target.newProb(45); else if (choice.equals("50%")) target.newProb(50); else if(choice.equals("55%")) target.newProb(55); else if (choice.equals("60%")) target.newProb(60); } else if (e.target instanceof Checkbox) { String choice = ((Checkbox)e.target).getLabel(); boolean b = ((Boolean)e.arg).booleanValue(); if (choice.equals("Answer")) { target.answer(b); } else if (choice.equals("B&W")) target.setBW(b); } return true; } } class Board { // bit fields static final int DOT = 1; // really a dot static final int GUESS = 2; // user thinks there's a dot static final int EMPTY_GUESS = 4; // user thinks it's empty int screenWidth = 400; // screen size int screenHeight = 400; // screen size int leftMargin = 5; int topMargin = 5; int boxWidth; int boxHeight; int[][] board; boolean[] correctColumns; // which columns are correctly marked boolean[] correctRows; int numColsCorrect; int numRowsCorrect; int[][] columns; // lists of numbers along the top int[][] rows; // lists of numbers along the side int width; // number of boxes in the board's width int height; int bHeight; // number of boxes in the width, including the side #'s int bWidth; int probability; // probability*100 that a box has a dot in it Random rand; boolean blackAndWhite = false; boolean answer = false; Label messageLabel; Checkbox answerBox; Board(Label ml,Checkbox ab) { width = 10; height = 10; probability = 50; rand = new Random(); messageLabel = ml; answerBox = ab; newBoard(); } void message(String text) { messageLabel.setText(text); } void resetAnswerBox() { answer = false; answerBox.setState(false); } void newBoard() { resetAnswerBox(); board = new int[width][height]; correctColumns = new boolean[width]; correctRows = new boolean[height]; int sum; numColsCorrect = 0; numRowsCorrect = 0; for(int i=0;i bHeight) bHeight = columns[i].length; } for(int i=0;i bWidth) bWidth = rows[i].length; } for(int i=0;i= width && y >= height) return; int left = leftMargin+(bWidth+x)*boxWidth; int top = topMargin+(bHeight+y)*boxHeight; Color drawColor; if ((board[x][y] & GUESS) == GUESS) drawColor = Color.black; else { if ((board[x][y] & EMPTY_GUESS) == EMPTY_GUESS) { drawColor = (blackAndWhite ? Color.white : Color.orange); } else drawColor = Color.white; } g.setColor(drawColor); g.fillRect(left+1,top+1,boxWidth-1,boxHeight-1); if (blackAndWhite && ((board[x][y] & EMPTY_GUESS) == EMPTY_GUESS)) { g.setColor(Color.black); g.drawLine(left+1,top+1,left+boxWidth,top+boxHeight); g.drawLine(left+1,top+boxHeight,left+boxWidth,top+1); } if (answer && (board[x][y] & DOT) == DOT) drawAnswerSquare(g,x,y); } void mouseDown(Event e,Graphics g) { int left = leftMargin+bWidth*boxWidth; int top = topMargin+bHeight*boxHeight; int right = leftMargin+(bWidth+width+1)*boxWidth; int bottom = topMargin+(bHeight+height+1)*boxHeight; int cx = (e.x-left)/boxWidth; int cy = (e.y-top)/boxHeight; if (cx < 0 || cy < 0 || cx >= width || cy >= height) return; // right mouse button if ((e.modifiers & Event.META_MASK) == Event.META_MASK) { board[cx][cy] &= ~GUESS; if ((board[cx][cy] & EMPTY_GUESS) == EMPTY_GUESS) board[cx][cy] &= ~EMPTY_GUESS; else board[cx][cy] |= EMPTY_GUESS; } else { board[cx][cy] &= ~EMPTY_GUESS; if ((board[cx][cy] & GUESS) == GUESS) board[cx][cy] &= ~GUESS; else board[cx][cy] |= GUESS; } drawSquare(g,cx,cy); boolean newVal = checkColumn(cx); if (correctColumns[cx] && !newVal) numColsCorrect --; else if (!correctColumns[cx] && newVal) numColsCorrect ++; correctColumns[cx] = newVal; newVal = checkRow(cy); if (correctRows[cy] && !newVal) numRowsCorrect --; else if (!correctRows[cy] && newVal) numRowsCorrect ++; correctRows[cy] = newVal; if (numColsCorrect == width && numRowsCorrect == height) message("Correct!"); else message(""); /* String m = (numColsCorrect == width && numRowsCorrect == height ? "Correct " : ""); m+= (numColsCorrect+" "+numRowsCorrect); for(int i=0;i= columns[x].length || count != columns[x][n]) return false; count = 0; lastNum = false; n++; continue; } if((board[x][y] & GUESS) == GUESS) { count = 1; lastNum = true; continue; } } if (lastNum && (n >= columns[x].length || count != columns[x][n])) return false; if (lastNum) n++; return (n == columns[x].length); } boolean checkRow(int y) { boolean lastNum = false; int count = 0; int n = 0; for(int x=0;x= rows[y].length || count != rows[y][n]) return false; count = 0; lastNum = false; n++; continue; } if((board[x][y] & GUESS) == GUESS) { count = 1; lastNum = true; continue; } } if (lastNum && (n >= rows[y].length || count != rows[y][n])) return false; if (lastNum) n++; return (n == rows[y].length); } void erase(Graphics g) { resetAnswerBox(); for(int x=0;x= width && y >= height) return; int left = leftMargin+(bWidth+x)*boxWidth; int top = topMargin+(bHeight+y)*boxHeight; if (blackAndWhite) g.setColor(Color.white); else g.setColor(Color.blue); g.fillRect(left+boxWidth/3,top+boxWidth/3,boxWidth/3,boxHeight/3); if (blackAndWhite) { g.setColor(Color.black); g.drawRect(left+boxWidth/3,top+boxWidth/3,boxWidth/3,boxHeight/3); } } void fillBoard(Graphics g) { for(int x=0;x