Skip to content

Commit

Permalink
LS (QWH or Latin Square)
Browse files Browse the repository at this point in the history
Added ability to change interface to accept Latin square puzzles
  • Loading branch information
SudokuMonster committed Nov 23, 2019
1 parent 3fd16e7 commit 4352073
Show file tree
Hide file tree
Showing 18 changed files with 486 additions and 85 deletions.
2 changes: 1 addition & 1 deletion diuf/sudoku/Cell.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void setValueAndCancel(int value, Grid targetGrid) {
assert value != 0;
targetGrid.setCellValue(this.index, value);
targetGrid.clearCellPotentialValues(this.index);
for(int i = 0; i < 20; i++) {
for(int i = 0; i < (Settings.getInstance().isBlocks() ? 20 : 16); i++) {
targetGrid.removeCellPotentialValue(Grid.visibleCellIndex[this.index][i], value);
}
}
Expand Down
382 changes: 372 additions & 10 deletions diuf/sudoku/Grid.java

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions diuf/sudoku/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
public class Settings {

public final static int VERSION = 1;
public final static int REVISION = 10;
public final static String SUBREV = ".4";
public final static int REVISION = 11;
public final static String SUBREV = ".1";
public final static String releaseDate = "2019-11-14";
public final static String releaseYear = "2019";
public final static String releaseLicence = "Lesser General Public License";
Expand Down
6 changes: 5 additions & 1 deletion diuf/sudoku/generator/Generator.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,11 @@ public Grid generate(Random rnd, Symmetry symmetry) {
for (Point p : points) {
//Cell cell = grid.getCell(p.x, p.y);
//if (cell.getValue() != 0) {
grid.resetGiven(y * 9 + x);
if (grid.getCellValue(p.x, p.y) != 0) {
//cell.setValue(0);
grid.setCellValue(p.x, p.y, 0);

cellRemoved = true;
}
}
Expand All @@ -124,8 +126,10 @@ public Grid generate(Random rnd, Symmetry symmetry) {
assert false : "Invalid grid";
} else {
// Failed. Put the cells back and try with next cell
for (Point p : points)
for (Point p : points){
grid.setCellValue(p.x, p.y, solution.getCellValue(p.x, p.y));
grid.setGiven(y * 9 + x);
}
//attempts += 1;
}
}
Expand Down
24 changes: 17 additions & 7 deletions diuf/sudoku/gui/SudokuFrame.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public class SudokuFrame extends JFrame implements Asker {
private JRadioButtonMenuItem mitChessMode = null;
private JCheckBoxMenuItem mitAntiAliasing = null;
private JMenu variantsMenu = null;
private JCheckBoxMenuItem mitVanilla = null;
//private JCheckBoxMenuItem mitVanilla = null;
private JCheckBoxMenuItem mitLQ = null;
private JCheckBoxMenuItem mitX = null;
private JCheckBoxMenuItem mitDG = null;
Expand Down Expand Up @@ -328,8 +328,10 @@ private void initialize() {
Experimental = ".1";
ExSuffix ="New Rating ";
}
if (!getInstance().isBlocks())
ExSuffix += "Latin Square ";
if (getInstance().isBringBackSE121()) {
Experimental =" (Original Sudoku Explainer 1.2.1 mode)";
Experimental =" (Explainer 1.2.1 mode)";
}
this.setTitle(ExSuffix + "Sukaku Explainer " + VERSION + "." + REVISION + SUBREV + Experimental);
JMenuBar menuBar = getJJMenuBar();
Expand Down Expand Up @@ -1389,7 +1391,7 @@ private JMenu getVariantsMenu() {
variantsMenu = new JMenu();
variantsMenu.setText("Variants");
//variantsMenu.setMnemonic(java.awt.event.KeyEvent.VK_H);
variantsMenu.add(getMitVanilla());
//variantsMenu.add(getMitVanilla());
variantsMenu.add(getMitLQ());
//getMitShowWelcome().setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
//variantsMenu.addSeparator();
Expand All @@ -1399,21 +1401,21 @@ private JMenu getVariantsMenu() {
return variantsMenu;
}

private JCheckBoxMenuItem getMitVanilla() {
/* private JCheckBoxMenuItem getMitVanilla() {
if (mitVanilla == null) {
mitVanilla = new JCheckBoxMenuItem();
mitVanilla.setText("Vanilla Sudoku");
mitVanilla.setSelected(true);
mitVanilla.setToolTipText("Vanilla Sudoku with Row, Columns and Blocks");
mitVanilla.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent e) {
mitVanilla.setSelected(true);
mitVanilla.setSelected(!mitLQ.isSelected());
}
});
}
return mitVanilla;
}

*/
private JCheckBoxMenuItem getMitLQ() {
if (mitLQ == null) {
mitLQ = new JCheckBoxMenuItem();
Expand All @@ -1422,7 +1424,15 @@ private JCheckBoxMenuItem getMitLQ() {
mitLQ.setToolTipText("Latin Square with Row and columns only. No Blocks");
mitLQ.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent e) {
mitLQ.setSelected(false);
Settings.getInstance().setBlocks(!mitLQ.isSelected());
Grid.changeVisibleCells();
if (Settings.getInstance().isBlocks()) {
}
engine.clearGrid();
engine.clearHints();
initialize();
repaintViews();
showWelcomeText();
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions diuf/sudoku/gui/SudokuPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ private boolean initFillColor(Graphics g, Cell cell, boolean origin) {
Color col;
boolean ret = false;

if ((cell.getX() / 3 % 2 == 0) ^ (cell.getY() / 3 % 2 == 0)) {
if (((cell.getX() / 3 % 2 == 0) ^ (cell.getY() / 3 % 2 == 0)) && Settings.getInstance().isBlocks()) {
col = alternativeColor;
} else {
col = Color.white;
Expand Down Expand Up @@ -622,7 +622,7 @@ private void paintSelectionAndFocus(Graphics g) {
private void paintGrid(Graphics g) {
for (int i = 0; i <= 9; i++) {
int lineWidth;
if (i % 3 == 0) {
if ((i % 3 == 0 && Settings.getInstance().isBlocks()) || i % 9 == 0) {
lineWidth = 4;
g.setColor(borderColor);
} else {
Expand Down
6 changes: 4 additions & 2 deletions diuf/sudoku/solver/Solver.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,12 +193,14 @@ public Solver(Grid grid) {
}
else {
addIfWorth(SolvingTechnique.HiddenSingle, directHintProducers, new HiddenSingle());
addIfWorth(SolvingTechnique.DirectPointing, directHintProducers, new Locking(true));
if (Settings.getInstance().isBlocks())
addIfWorth(SolvingTechnique.DirectPointing, directHintProducers, new Locking(true));
addIfWorth(SolvingTechnique.DirectHiddenPair, directHintProducers, new HiddenSet(2, true));
addIfWorth(SolvingTechnique.NakedSingle, directHintProducers, new NakedSingle());
addIfWorth(SolvingTechnique.DirectHiddenTriplet, directHintProducers, new HiddenSet(3, true));
indirectHintProducers = new ArrayList<IndirectHintProducer>();
addIfWorth(SolvingTechnique.PointingClaiming, indirectHintProducers, new Locking(false));
if (Settings.getInstance().isBlocks())
addIfWorth(SolvingTechnique.PointingClaiming, indirectHintProducers, new Locking(false));
addIfWorth(SolvingTechnique.NakedPair, indirectHintProducers, new NakedSet(2));
addIfWorth(SolvingTechnique.XWing, indirectHintProducers, new Fisherman(2));
addIfWorth(SolvingTechnique.HiddenPair, indirectHintProducers, new HiddenSet(2, false));
Expand Down
2 changes: 1 addition & 1 deletion diuf/sudoku/solver/checks/BruteForceAnalysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ private boolean analyse(Grid grid, boolean isReverse, Random rnd,
* imply that the sudoku has no solution.
*/
private boolean isFillable(Grid grid) {
for (int regionTypeIndex = 0; regionTypeIndex < 3; regionTypeIndex++) {
for (int regionTypeIndex = (Settings.getInstance().isBlocks() ? 0 : 1); regionTypeIndex < 3; regionTypeIndex++) {
Grid.Region[] regions = Grid.getRegions(regionTypeIndex);
for (int i = 0; i < 9; i++) {
Grid.Region region = regions[i];
Expand Down
4 changes: 2 additions & 2 deletions diuf/sudoku/solver/checks/NoDoubles.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void getHints(Grid grid, HintsAccumulator accu)
// Iterate on region types
//for (Class<? extends Grid.Region> regionType : Grid.getRegionTypes()) {
// Grid.Region[] regions = grid.getRegions(regionType);
for (int regionTypeIndex = 0; regionTypeIndex < 3; regionTypeIndex++) {
for (int regionTypeIndex = (Settings.getInstance().isBlocks() ? 0 : 1); regionTypeIndex < 3; regionTypeIndex++) {
Grid.Region[] regions = Grid.getRegions(regionTypeIndex);

// Iterate on occurances of a region
Expand Down Expand Up @@ -74,7 +74,7 @@ public boolean isValid(Grid grid) {
// Iterate on region types
//for (Class<? extends Grid.Region> regionType : Grid.getRegionTypes()) {
// Grid.Region[] regions = grid.getRegions(regionType);
for (int regionTypeIndex = 0; regionTypeIndex < 3; regionTypeIndex++) {
for (int regionTypeIndex = (Settings.getInstance().isBlocks() ? 0 : 1); regionTypeIndex < 3; regionTypeIndex++) {
Grid.Region[] regions = Grid.getRegions(regionTypeIndex);

// Iterate on occurances of a region
Expand Down
3 changes: 2 additions & 1 deletion diuf/sudoku/solver/rules/HiddenSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public HiddenSet(int degree, boolean isDirect) {
}

public void getHints(Grid grid, HintsAccumulator accu) throws InterruptedException {
getHints(grid, 0, accu); //block
if (Settings.getInstance().isBlocks())
getHints(grid, 0, accu); //block
getHints(grid, 2, accu); //column
getHints(grid, 1, accu); //row
}
Expand Down
6 changes: 4 additions & 2 deletions diuf/sudoku/solver/rules/HiddenSingle.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ public class HiddenSingle implements DirectHintProducer {

public void getHints(Grid grid, HintsAccumulator accu) throws InterruptedException {
// First alone cells (last empty cell in a region)
getHints(grid, 0, accu, true); //block
if (Settings.getInstance().isBlocks())
getHints(grid, 0, accu, true); //block
getHints(grid, 2, accu, true); //column
getHints(grid, 1, accu, true); //row
// Then hidden cells
getHints(grid, 0, accu, false); //block
if (Settings.getInstance().isBlocks())
getHints(grid, 0, accu, false); //block
getHints(grid, 2, accu, false); //column
getHints(grid, 1, accu, false); //row
}
Expand Down
3 changes: 2 additions & 1 deletion diuf/sudoku/solver/rules/NakedSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public NakedSet(int degree) {
}

public void getHints(Grid grid, HintsAccumulator accu) throws InterruptedException {
getHints(grid, 0, accu); //block
if (Settings.getInstance().isBlocks())
getHints(grid, 0, accu); //block
getHints(grid, 2, accu); //column
getHints(grid, 1, accu); //row
}
Expand Down
33 changes: 20 additions & 13 deletions diuf/sudoku/solver/rules/StrongLinks.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ public void getHints(Grid grid, HintsAccumulator accu) throws InterruptedExcepti
int linkNumber = 0;
int setNumber = 0;
while (linkNumber < degree) {
//For Latin Square
if (!Settings.getInstance().isBlocks() && setsAll[setNumber][8 - degree + linkNumber] == 0) {
linkNumber = 0;
setNumber++;
continue;
}
Set[linkNumber] = setsAll[setNumber][8 - degree + linkNumber];
linkNumber++;
if (linkNumber == degree && (setNumber < 45 && (degree == 8 || setsAll[setNumber][8 - degree - 1] != 1))) {
Expand Down Expand Up @@ -140,20 +146,21 @@ else if (bridge2Support == null) {
else if (bridge2.getY() == bridge1Support.getY() && bridge1.getY() == bridge2Support.getY())
return (Grid.Row)Grid.getRegionAt(1,bridge1.getIndex());
}
if (bridge1.getB() == bridge2.getB()) {
if (bridge1Support == null && bridge2Support == null)
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
else if (bridge1Support == null) {
if (bridge1.getB() == bridge2Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2Support == null) {
if (bridge2.getB() == bridge1Support.getB())
if (Settings.getInstance().isBlocks())
if (bridge1.getB() == bridge2.getB()) {
if (bridge1Support == null && bridge2Support == null)
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2.getB() == bridge1Support.getB() && bridge1.getB() == bridge2Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge1Support == null) {
if (bridge1.getB() == bridge2Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2Support == null) {
if (bridge2.getB() == bridge1Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2.getB() == bridge1Support.getB() && bridge1.getB() == bridge2Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
return null;
}

Expand Down
29 changes: 15 additions & 14 deletions diuf/sudoku/solver/rules/TurbotFish.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void getHints(Grid grid, HintsAccumulator accu) throws InterruptedExcepti
};
List<TurbotFishHint> hintsFinal = new ArrayList<TurbotFishHint>();
List<TurbotFishHint> hintsStart;
for (int i = 0; i < 5 ; i++) {
for (int i = 0; i < (Settings.getInstance().isBlocks() ? 5 : 3) ; i++) {
hintsStart = getHints(grid, Sets[i][0], Sets[i][1]);
for (TurbotFishHint hint : hintsStart)
hintsFinal.add(hint);
Expand Down Expand Up @@ -87,20 +87,21 @@ else if (bridge2Support == null) {
else if (bridge2.getY() == bridge1Support.getY())
return (Grid.Row)Grid.getRegionAt(1,bridge1.getIndex());
}
if (bridge1.getB() == bridge2.getB()) {
if (bridge1Support == null && bridge2Support == null)
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
else if (bridge1Support == null) {
if (bridge1.getB() == bridge2Support.getB())
if (Settings.getInstance().isBlocks())
if (bridge1.getB() == bridge2.getB()) {
if (bridge1Support == null && bridge2Support == null)
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2Support == null) {
if (bridge2.getB() == bridge1Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2.getB() == bridge1Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge1Support == null) {
if (bridge1.getB() == bridge2Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2Support == null) {
if (bridge2.getB() == bridge1Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
else if (bridge2.getB() == bridge1Support.getB())
return (Grid.Block)Grid.getRegionAt(0,bridge1.getIndex());
}
return null;
}

Expand Down
25 changes: 14 additions & 11 deletions diuf/sudoku/solver/rules/chaining/Chaining.java
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ private void doBinaryChaining(Grid grid, Potential pOn, Potential pOff,

private void doRegionChainings(Grid grid, List<ChainingHint> result, Cell cell,
int value, LinkedSet<Potential> onToOn, LinkedSet<Potential> onToOff) {
for (int regionTypeIndex = 0; regionTypeIndex < 3; regionTypeIndex++) {
for (int regionTypeIndex = (Settings.getInstance().isBlocks() ? 0 : 1); regionTypeIndex < 3; regionTypeIndex++) {
Grid.Region region = Grid.getRegionAt(regionTypeIndex, cell.getIndex());
BitSet potentialPositions = region.getPotentialPositions(grid, value);

Expand Down Expand Up @@ -591,18 +591,20 @@ private Set<Potential> getOnToOff(Grid grid, Potential p, boolean isYChainEnable
Grid.Region box = Grid.getRegionAt(0, potentialCellIndex);
BitSet boxPositions = box.copyPotentialPositions(grid, p.value);
boxPositions.clear(box.indexOf(p.cell));
for (int i = boxPositions.nextSetBit(0); i >= 0; i = boxPositions.nextSetBit(i + 1)) {
Cell cell = box.getCell(i);
result.add(new Potential(cell, p.value, false, p,
getRegionCause(0),
"the value can occur only once in the " + box.toString()));
}
if (Settings.getInstance().isBlocks())
for (int i = boxPositions.nextSetBit(0); i >= 0; i = boxPositions.nextSetBit(i + 1)) {
Cell cell = box.getCell(i);
result.add(new Potential(cell, p.value, false, p,
getRegionCause(0),
"the value can occur only once in the " + box.toString()));
}
Grid.Region row = Grid.getRegionAt(1, potentialCellIndex);
BitSet rowPositions = row.copyPotentialPositions(grid, p.value);
rowPositions.clear(row.indexOf(p.cell));
for (int i = rowPositions.nextSetBit(0); i >= 0; i = rowPositions.nextSetBit(i + 1)) {
Cell cell = row.getCell(i);
if(box.contains(cell)) continue;
if (Settings.getInstance().isBlocks())
if(box.contains(cell)) continue;
result.add(new Potential(cell, p.value, false, p,
getRegionCause(1),
"the value can occur only once in the " + row.toString()));
Expand All @@ -612,7 +614,8 @@ private Set<Potential> getOnToOff(Grid grid, Potential p, boolean isYChainEnable
colPositions.clear(col.indexOf(p.cell));
for (int i = colPositions.nextSetBit(0); i >= 0; i = colPositions.nextSetBit(i + 1)) {
Cell cell = col.getCell(i);
if(box.contains(cell)) continue;
if (Settings.getInstance().isBlocks())
if(box.contains(cell)) continue;
result.add(new Potential(cell, p.value, false, p,
getRegionCause(2),
"the value can occur only once in the " + col.toString()));
Expand Down Expand Up @@ -660,7 +663,7 @@ private void addHiddenParentsOfRegion(Potential p, Grid grid, Grid source,
}

static Potential.Cause getRegionCause(Region region) { //still in use by collectRuleParents where for regionchaining region is used for repaint and stings
if (region instanceof Block)
if (region instanceof Block && Settings.getInstance().isBlocks())
return Potential.Cause.HiddenBlock;
else if (region instanceof Column)
return Potential.Cause.HiddenColumn;
Expand Down Expand Up @@ -709,7 +712,7 @@ private Set<Potential> getOffToOn(Grid grid, Potential p, Grid source,
if (isXChainEnabled) {
// Second rule: if there are only two positions for this potential, the other one gets on
int thisValue = p.value;
for(int regionTypeIndex = 0; regionTypeIndex < 3; regionTypeIndex++) {
for(int regionTypeIndex = (Settings.getInstance().isBlocks() ? 0 : 1); regionTypeIndex < 3; regionTypeIndex++) {
Region r = Grid.regions[regionTypeIndex][Grid.cellRegions[thisCellIndex][regionTypeIndex]];
int otherPosition = -1;
for(int regionCellIndex = 0; regionCellIndex < 9; regionCellIndex++) {
Expand Down
Loading

0 comments on commit 4352073

Please sign in to comment.