001package ball.game.crossword; 002/*- 003 * ########################################################################## 004 * Game Applications and Utilities 005 * %% 006 * Copyright (C) 2010 - 2022 Allen D. Ball 007 * %% 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 * ########################################################################## 020 */ 021import java.util.List; 022import java.util.stream.Collectors; 023 024import static java.lang.Character.isDigit; 025import static java.lang.Character.isLetter; 026import static java.lang.Character.isLowerCase; 027import static java.lang.Character.toLowerCase; 028import static java.lang.Character.toUpperCase; 029 030/** 031 * Crossword {@link Puzzle} {@link Cell}. 032 * 033 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 034 */ 035public class Cell implements Cloneable { 036 private static final Block BLOCK = new Block(); 037 038 private final Boolean special; 039 private Character solution = null; 040 041 private Cell(boolean special) { this.special = special; } 042 043 private Cell(boolean special, Character solution) { 044 this(special); 045 046 setSolution(solution); 047 } 048 049 public boolean isBlock() { return false; } 050 051 public boolean isSpecial() { return special; } 052 053 public boolean isSolved() { return solution != null; } 054 055 public Character getSolution() { return solution; } 056 public void setSolution(Character solution) { this.solution = solution; } 057 058 @Override 059 public Cell clone() throws CloneNotSupportedException { 060 return (Cell) super.clone(); 061 } 062 063 @Override 064 public String toString() { 065 char representation = '.'; 066 067 if (isSolved()) { 068 representation = getSolution(); 069 070 if (isSpecial()) { 071 representation = toLowerCase(representation); 072 } else { 073 representation = toUpperCase(representation); 074 } 075 } 076 077 return String.valueOf(representation); 078 } 079 080 /** 081 * Factory method to produce a {@link Cell}. 082 * 083 * @param character The {@code char} representing the 084 * {@link Cell}. 085 * 086 * @return The new {@link Cell}. 087 */ 088 public static Cell getInstance(char character) { 089 Cell cell = null; 090 091 switch (character) { 092 case '.': 093 cell = new Cell(false); 094 break; 095 096 case '#': 097 cell = BLOCK; 098 break; 099 100 default: 101 if (isLetter(character)) { 102 cell = new Cell(isLowerCase(character), toUpperCase(character)); 103 } else if (isDigit(character)) { 104 cell = new Cell(false, character); 105 } else { 106 throw new IllegalArgumentException(String.valueOf(character)); 107 } 108 break; 109 } 110 111 return cell; 112 } 113 114 public static List<Cell> getRowFrom(String line) { 115 return (line.chars() 116 .mapToObj(c -> getInstance((char) c)) 117 .collect(Collectors.toList())); 118 } 119 120 private static class Block extends Cell { 121 private Block() { super(false); } 122 123 @Override 124 public boolean isBlock() { return true; } 125 126 @Override 127 public boolean isSolved() { return true; } 128 129 @Override 130 public void setSolution(Character solution) { 131 throw new IllegalStateException(); 132 } 133 134 @Override 135 public String toString() { return "#"; } 136 } 137}