简体   繁体   中英

Numbering A Crossword Java ACM Graphics

The problem asks for an acm graphics program that reads a txt file like this:

      R      
     FUN     
    SALES    
   RECEIPT   
  MERE@FARM  
 DOVE@@@RAIL 
MORE@@@@@DRAW
 HARD@@@TIED 
  LION@SAND  
   EVENING   
    EVADE    
     ARE     
      D      

and makes a crossword puzzle, with blank squares on letters, black squares on '@', and nothing on empty spaces. The problem also asks that "if the square is at the beginning of a word running across, down, or both, the square should contain a number that is assigned sequentially through the puzzle."

I have the square drawing working, but I'm stuck on drawing the numbers correctly. There is something wrong with how I'm detecting null space and black squares. Can someone tell me what I'm doing wrong, please?

Here is the code:

import acm.program.*;
import java.io.*;
import java.util.*;
import acm.graphics.*;
import java.awt.*;

public class Crossword extends GraphicsProgram {
public void run() {
    String fileName = "crosswordfile.txt";
    makeCrosswordPuzzle(fileName);
}
private static final int sqCon = 15; // constant for square x and y dimensions
private int y = 0;
public void makeCrosswordPuzzle(String fileName) {
    BufferedReader rd;
    int y = 0; // y value for the square being added during that loop. increments by sqCon after every line
    int wordNumber = 1; // variable for numbers added to certain boxes. increments every time the program adds a number
    try {
        rd = new BufferedReader(new FileReader(fileName));
        String line = rd.readLine(); //reads one line of the text document at a time and makes it a string

        while (line != null) {
            int x = 0;


            for (int i = 0; i < line.length(); i++) {

                char lineChar = line.charAt(i);// the character being examined for each loop

                GRect whiteSq = new GRect(sqCon,sqCon); //GRect for blank squares

                GRect blackSq = new GRect(sqCon,sqCon);//GRect for black squares
                blackSq.setFilled(true);
                blackSq.setFillColor(Color.BLACK);

                if (lineChar == '@'){
                    add (blackSq,x,y);

                }
                if (Character.isLetter(lineChar)) {

                    add (whiteSq, x, y);

                    // if the element above or to the left of the current focus is null or blackSq, place the number and then increment wordNumber
                    GObject above = getElementAt(x+sqCon/2,y-sqCon/2);
                    GObject left = getElementAt(x-sqCon/2, y+sqCon/2);

                    GLabel wordNumberLabel = new GLabel(Integer.toString(wordNumber));
                    if (above == null || left == null || above == blackSq || left == blackSq) {

                        add(wordNumberLabel,x,y+sqCon);
                        wordNumber++;
                    }
                }
                x += sqCon;
            }
            line = rd.readLine();
            y += sqCon;
        }
        rd.close();
    }
    catch (IOException e) {
        throw new ErrorException(e);
    }
}

}

Edited to add:

I copied your code over to my Eclipse and ran it. Here's the result.

填字游戏解决方案

You did fine on the upper half, but you missed the down numbers on the lower half.

Here's the same code, reformatted so it's easier to read.

import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import acm.graphics.GLabel;
import acm.graphics.GObject;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;
import acm.util.ErrorException;

public class Crossword extends GraphicsProgram {
    private static final long   serialVersionUID    = -7971434624427958742L;

    public void run() {
//      String fileName = "crosswordfile.txt";
        String fileName = "C:/Eclipse/eclipse-4.2-work/com.ggl.testing/crosswordfile.txt";
        makeCrosswordPuzzle(fileName);
    }

    private static final int    sqCon   = 15;   // constant for square x and y
                                                // dimensions
    private int                 y       = 0;

    public void makeCrosswordPuzzle(String fileName) {
        BufferedReader rd;
        int y = 0; // y value for the square being added during that loop.
                    // increments by sqCon after every line
        int wordNumber = 1; // variable for numbers added to certain boxes.
                            // increments every time the program adds a number
        try {
            rd = new BufferedReader(new FileReader(fileName));
            String line = rd.readLine(); // reads one line of the text document
                                            // at a time and makes it a string

            while (line != null) {
                int x = 0;

                for (int i = 0; i < line.length(); i++) {

                    char lineChar = line.charAt(i);// the character being
                                                    // examined for each loop

                    GRect whiteSq = new GRect(sqCon, sqCon); // GRect for blank
                                                                // squares

                    GRect blackSq = new GRect(sqCon, sqCon);// GRect for black
                                                            // squares
                    blackSq.setFilled(true);
                    blackSq.setFillColor(Color.BLACK);

                    if (lineChar == '@') {
                        add(blackSq, x, y);

                    }
                    if (Character.isLetter(lineChar)) {

                        add(whiteSq, x, y);

                        // if the element above or to the left of the current
                        // focus is null or blackSq, place the number and then
                        // increment wordNumber
                        GObject above = getElementAt(x + sqCon / 2, y - sqCon
                                / 2);
                        GObject left = getElementAt(x - sqCon / 2, y + sqCon
                                / 2);

                        GLabel wordNumberLabel = new GLabel(
                                Integer.toString(wordNumber));
                        if (above == null || left == null || above == blackSq
                                || left == blackSq) {

                            add(wordNumberLabel, x, y + sqCon);
                            wordNumber++;
                        }
                    }
                    x += sqCon;
                }
                line = rd.readLine();
                y += sqCon;
            }
            rd.close();
        } catch (IOException e) {
            throw new ErrorException(e);
        }
    }

}

I followed the advice of my own comment. I created the crossword puzzle answer, numbered the crossword puzzle answer, and finally drew the crossword puzzle answer.

Here's the applet result:

填字游戏答案

I kept a List of crossword puzzle cells. That way, I could determine the length and the width of the puzzle by the number of characters on a row and the number of rows of the input text file. I didn't have to hard code the dimensions.

For each crossword cell, I kept track of whether or not it was a letter, and whether or not it was a dark space.

When determining where to put the numbers, I followed 2 rules.

  1. An across number is placed where the cell left of the cell is empty or dark, and there are three or more letters across.

  2. A down number is placed where the cell above the cell is empty or dark, there are three or more letters down, and there is no across number.

You can see in the code that I had to do some debug printing to get the crossword puzzle clue numbering correct. I broke the process into many methods to keep each method as simple as possible.

Finally, I drew the crossword puzzle answer from the information in the List.

Here's the code:

import java.awt.Color;
import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import acm.graphics.GLabel;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;
import acm.util.ErrorException;

public class Crossword extends GraphicsProgram {
    private static final boolean DEBUG = false;

    private static final long serialVersionUID = -7971434624427958742L;

    private List<CrosswordCell> crosswordCellList;

    @Override
    public void run() {
        this.crosswordCellList = new ArrayList<CrosswordCell>();
//      String fileName = "crosswordfile.txt";
        String fileName = "C:/Eclipse/eclipse-4.2-work/" + 
                "com.ggl.testing/crosswordfile.txt";
        try {
            readCrosswordAnswer(fileName);
            if (DEBUG) printCrosswordAnswer();
            numberCrosswordCells();
            if (DEBUG) printCrosswordAnswer();
            drawCrosswordAnswer();
        } catch (FileNotFoundException e) {
            throw new ErrorException(e);
        } catch (IOException e) {
            throw new ErrorException(e);
        }
    }

    private void readCrosswordAnswer(String fileName) 
            throws FileNotFoundException, IOException {
        BufferedReader reader = 
                new BufferedReader(new FileReader(fileName));
        String line = "";
        int row = 0;
        while ((line = reader.readLine()) != null) {
            for (int column = 0; column < line.length(); column++) {
                CrosswordCell cell = new CrosswordCell(column, row);
                char lineChar = line.charAt(column);
                if (lineChar == '@') {
                    cell.setDarkCell(true);
                } else if (Character.isLetter(lineChar)) {
                    cell.setLetter(true);
                }
                crosswordCellList.add(cell);
            }
            row++;
        }
        reader.close();
    }

    public void printCrosswordAnswer() {
        for (CrosswordCell cell : crosswordCellList) {
            System.out.println(cell);
        }
    }

    private void numberCrosswordCells() {
        int clueNumber = 1;
        for (CrosswordCell cell : crosswordCellList) {
            if (cell.isLetter()) {
                clueNumber = testCell(cell, clueNumber);
            }
        }
    }

    private int testCell(CrosswordCell cell, int clueNumber) {
        Point p = cell.getLocation();
        CrosswordCell leftCell = getLeftCell(p.x, p.y);
        List<CrosswordCell> acrossList = getRightCells(p.x, p.y);
        if (DEBUG) {
            System.out.print(p);
            System.out.println(", " + leftCell + " " + 
                    acrossList.size());
        }
        if ((leftCell == null) && (acrossList.size() >= 3)) {
            cell.setClueNumber(clueNumber++);
        } else {
            CrosswordCell aboveCell = getAboveCell(p.x, p.y);
            List<CrosswordCell> downList = getBelowCells(p.x, p.y);
            if (DEBUG) {
                System.out.print(p);
                System.out.println(", " + aboveCell + " " + 
                        downList.size());
            }
            if ((aboveCell == null) && (downList.size() >= 3)) {
                cell.setClueNumber(clueNumber++);
            }
        }
        return clueNumber;
    }

    private CrosswordCell getAboveCell(int x, int y) {
        int yy = y - 1;
        return getCell(x, yy);
    }

    private CrosswordCell getLeftCell(int x, int y) {
        int xx = x - 1;
        return getCell(xx, y);
    }

    private List<CrosswordCell> getBelowCells(int x, int y) {
        List<CrosswordCell> list = new ArrayList<CrosswordCell>();
        for (int i = y; i < (y + 3); i++) {
            CrosswordCell cell = getCell(x, i);
            if (cell != null) {
                list.add(cell);
            }
        }
        return list;
    }

    private List<CrosswordCell> getRightCells(int x, int y) {
        List<CrosswordCell> list = new ArrayList<CrosswordCell>();
        for (int i = x; i < (x + 3); i++) {
            CrosswordCell cell = getCell(i, y);
            if (cell != null) {
                list.add(cell);
            }
        }
        return list;
    }

    private CrosswordCell getCell(int x, int y) {
        for (CrosswordCell cell : crosswordCellList) {      
            Point p = cell.getLocation();
            if ((p.x == x) && (p.y == y)) {
                if (cell.isDarkCell()) {
                    return null;
                } else if (cell.isLetter()){
                    return cell;
                } else {
                    return null;
                }
            }
        }
        return null;
    }

    private void drawCrosswordAnswer() {
        int sqCon = 32;
        for (CrosswordCell cell : crosswordCellList) {
            Point p = cell.getLocation();
            if (cell.isDarkCell()) {
                drawDarkCell(p, sqCon);
            } else if (cell.isLetter()) {
                drawLetterCell(cell, p, sqCon);
            }
        }
    }

    private void drawDarkCell(Point p, int sqCon) {
        GRect blackSq = new GRect(sqCon, sqCon);
        blackSq.setFilled(true);
        blackSq.setFillColor(Color.BLACK);
        add(blackSq, p.x * sqCon, p.y * sqCon);
    }

    private void drawLetterCell(CrosswordCell cell, Point p, int sqCon) {
        GRect whiteSq = new GRect(sqCon, sqCon);
        add(whiteSq, p.x * sqCon, p.y * sqCon);
        if (cell.getClueNumber() > 0) {
            String label = Integer.toString(cell.getClueNumber());
            GLabel wordNumberLabel = new GLabel(label);
            add(wordNumberLabel, p.x * sqCon + 2, p.y * sqCon + 14);
        }
    }

    class CrosswordCell {
        private boolean darkCell;
        private boolean isLetter;

        private int clueNumber;

        private Point location;

        public CrosswordCell(int x, int y) {
            this.location = new Point(x, y);
            this.clueNumber = 0;
            this.darkCell = false;
            this.isLetter = false;
        }

        public boolean isDarkCell() {
            return darkCell;
        }

        public void setDarkCell(boolean darkCell) {
            this.darkCell = darkCell;
        }

        public boolean isLetter() {
            return isLetter;
        }

        public void setLetter(boolean isLetter) {
            this.isLetter = isLetter;
        }

        public int getClueNumber() {
            return clueNumber;
        }

        public void setClueNumber(int clueNumber) {
            this.clueNumber = clueNumber;
        }

        public Point getLocation() {
            return location;
        }

        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("CrosswordCell [location=");
            builder.append(location);
            builder.append(", clueNumber=");
            builder.append(clueNumber);
            builder.append(", darkCell=");
            builder.append(darkCell);
            builder.append(", isLetter=");
            builder.append(isLetter);
            builder.append("]");
            return builder.toString();
        }

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM