Sat, 25 Jul 2020 14:01:28 +0200
converts to maven project
--- a/.hgignore Fri Feb 01 10:18:47 2013 +0100 +++ b/.hgignore Sat Jul 25 14:01:28 2020 +0200 @@ -3,3 +3,5 @@ \.chg\..*$ \.rej$ \.conflict\~$ +.iml$ +.idea/
--- a/build.xml Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- You may freely edit this file. See commented blocks below for --> -<!-- some examples of how to customize the build. --> -<!-- (If you delete it and reopen the project it will be recreated.) --> -<!-- By default, only the Clean and Build commands use this build script. --> -<!-- Commands such as Run, Debug, and Test only use this build script if --> -<!-- the Compile on Save feature is turned off for the project. --> -<!-- You can turn off the Compile on Save (or Deploy on Save) setting --> -<!-- in the project's Project Properties dialog box.--> -<project name="Sudoku" default="default" basedir="."> - <description>Builds, tests, and runs the project Sudoku.</description> - <import file="nbproject/build-impl.xml"/> - <!-- - - There exist several targets which are by default empty and which can be - used for execution of your tasks. These targets are usually executed - before and after some main targets. They are: - - -pre-init: called before initialization of project properties - -post-init: called after initialization of project properties - -pre-compile: called before javac compilation - -post-compile: called after javac compilation - -pre-compile-single: called before javac compilation of single file - -post-compile-single: called after javac compilation of single file - -pre-compile-test: called before javac compilation of JUnit tests - -post-compile-test: called after javac compilation of JUnit tests - -pre-compile-test-single: called before javac compilation of single JUnit test - -post-compile-test-single: called after javac compilation of single JUunit test - -pre-jar: called before JAR building - -post-jar: called after JAR building - -post-clean: called after cleaning build products - - (Targets beginning with '-' are not intended to be called on their own.) - - Example of inserting an obfuscator after compilation could look like this: - - <target name="-post-compile"> - <obfuscate> - <fileset dir="${build.classes.dir}"/> - </obfuscate> - </target> - - For list of available properties check the imported - nbproject/build-impl.xml file. - - - Another way to customize the build is by overriding existing main targets. - The targets of interest are: - - -init-macrodef-javac: defines macro for javac compilation - -init-macrodef-junit: defines macro for junit execution - -init-macrodef-debug: defines macro for class debugging - -init-macrodef-java: defines macro for class execution - -do-jar-with-manifest: JAR building (if you are using a manifest) - -do-jar-without-manifest: JAR building (if you are not using a manifest) - run: execution of project - -javadoc-build: Javadoc generation - test-report: JUnit report generation - - An example of overriding the target for project execution could look like this: - - <target name="run" depends="Sudoku-impl.jar"> - <exec dir="bin" executable="launcher.exe"> - <arg file="${dist.jar}"/> - </exec> - </target> - - Notice that the overridden target depends on the jar target and not only on - the compile target as the regular run target does. Again, for a list of available - properties which you can use, check the target you are overriding in the - nbproject/build-impl.xml file. - - --> -</project>
--- a/nbproject/build-impl.xml Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1400 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -*** GENERATED FROM project.xml - DO NOT EDIT *** -*** EDIT ../build.xml INSTEAD *** - -For the purpose of easier reading the script -is divided into following sections: - - - initialization - - compilation - - jar - - execution - - debugging - - javadoc - - test compilation - - test execution - - test debugging - - applet - - cleanup - - --> -<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="Sudoku-impl"> - <fail message="Please build using Ant 1.8.0 or higher."> - <condition> - <not> - <antversion atleast="1.8.0"/> - </not> - </condition> - </fail> - <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/> - <!-- - ====================== - INITIALIZATION SECTION - ====================== - --> - <target name="-pre-init"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="-pre-init" name="-init-private"> - <property file="nbproject/private/config.properties"/> - <property file="nbproject/private/configs/${config}.properties"/> - <property file="nbproject/private/private.properties"/> - </target> - <target depends="-pre-init,-init-private" name="-init-user"> - <property file="${user.properties.file}"/> - <!-- The two properties below are usually overridden --> - <!-- by the active platform. Just a fallback. --> - <property name="default.javac.source" value="1.4"/> - <property name="default.javac.target" value="1.4"/> - </target> - <target depends="-pre-init,-init-private,-init-user" name="-init-project"> - <property file="nbproject/configs/${config}.properties"/> - <property file="nbproject/project.properties"/> - </target> - <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init"> - <available file="${manifest.file}" property="manifest.available"/> - <condition property="splashscreen.available"> - <and> - <not> - <equals arg1="${application.splash}" arg2="" trim="true"/> - </not> - <available file="${application.splash}"/> - </and> - </condition> - <condition property="main.class.available"> - <and> - <isset property="main.class"/> - <not> - <equals arg1="${main.class}" arg2="" trim="true"/> - </not> - </and> - </condition> - <condition property="manifest.available+main.class"> - <and> - <isset property="manifest.available"/> - <isset property="main.class.available"/> - </and> - </condition> - <condition property="do.archive"> - <not> - <istrue value="${jar.archive.disabled}"/> - </not> - </condition> - <condition property="do.mkdist"> - <and> - <isset property="do.archive"/> - <isset property="libs.CopyLibs.classpath"/> - <not> - <istrue value="${mkdist.disabled}"/> - </not> - </and> - </condition> - <condition property="manifest.available+main.class+mkdist.available"> - <and> - <istrue value="${manifest.available+main.class}"/> - <isset property="do.mkdist"/> - </and> - </condition> - <condition property="do.archive+manifest.available"> - <and> - <isset property="manifest.available"/> - <istrue value="${do.archive}"/> - </and> - </condition> - <condition property="do.archive+main.class.available"> - <and> - <isset property="main.class.available"/> - <istrue value="${do.archive}"/> - </and> - </condition> - <condition property="do.archive+splashscreen.available"> - <and> - <isset property="splashscreen.available"/> - <istrue value="${do.archive}"/> - </and> - </condition> - <condition property="do.archive+manifest.available+main.class"> - <and> - <istrue value="${manifest.available+main.class}"/> - <istrue value="${do.archive}"/> - </and> - </condition> - <condition property="manifest.available-mkdist.available"> - <or> - <istrue value="${manifest.available}"/> - <isset property="do.mkdist"/> - </or> - </condition> - <condition property="manifest.available+main.class-mkdist.available"> - <or> - <istrue value="${manifest.available+main.class}"/> - <isset property="do.mkdist"/> - </or> - </condition> - <condition property="have.tests"> - <or> - <available file="${test.src.dir}"/> - </or> - </condition> - <condition property="have.sources"> - <or> - <available file="${src.dir}"/> - </or> - </condition> - <condition property="netbeans.home+have.tests"> - <and> - <isset property="netbeans.home"/> - <isset property="have.tests"/> - </and> - </condition> - <condition property="no.javadoc.preview"> - <and> - <isset property="javadoc.preview"/> - <isfalse value="${javadoc.preview}"/> - </and> - </condition> - <property name="run.jvmargs" value=""/> - <property name="run.jvmargs.ide" value=""/> - <property name="javac.compilerargs" value=""/> - <property name="work.dir" value="${basedir}"/> - <condition property="no.deps"> - <and> - <istrue value="${no.dependencies}"/> - </and> - </condition> - <property name="javac.debug" value="true"/> - <property name="javadoc.preview" value="true"/> - <property name="application.args" value=""/> - <property name="source.encoding" value="${file.encoding}"/> - <property name="runtime.encoding" value="${source.encoding}"/> - <condition property="javadoc.encoding.used" value="${javadoc.encoding}"> - <and> - <isset property="javadoc.encoding"/> - <not> - <equals arg1="${javadoc.encoding}" arg2=""/> - </not> - </and> - </condition> - <property name="javadoc.encoding.used" value="${source.encoding}"/> - <property name="includes" value="**"/> - <property name="excludes" value=""/> - <property name="do.depend" value="false"/> - <condition property="do.depend.true"> - <istrue value="${do.depend}"/> - </condition> - <path id="endorsed.classpath.path" path="${endorsed.classpath}"/> - <condition else="" property="endorsed.classpath.cmd.line.arg" value="-Xbootclasspath/p:'${toString:endorsed.classpath.path}'"> - <length length="0" string="${endorsed.classpath}" when="greater"/> - </condition> - <condition else="false" property="jdkBug6558476"> - <and> - <matches pattern="1\.[56]" string="${java.specification.version}"/> - <not> - <os family="unix"/> - </not> - </and> - </condition> - <property name="javac.fork" value="${jdkBug6558476}"/> - <property name="jar.index" value="false"/> - <property name="jar.index.metainf" value="${jar.index}"/> - <property name="copylibs.rebase" value="true"/> - <available file="${meta.inf.dir}/persistence.xml" property="has.persistence.xml"/> - <condition property="junit.available"> - <or> - <available classname="org.junit.Test" classpath="${run.test.classpath}"/> - <available classname="junit.framework.Test" classpath="${run.test.classpath}"/> - </or> - </condition> - <condition property="testng.available"> - <available classname="org.testng.annotations.Test" classpath="${run.test.classpath}"/> - </condition> - <condition property="junit+testng.available"> - <and> - <istrue value="${junit.available}"/> - <istrue value="${testng.available}"/> - </and> - </condition> - <condition else="testng" property="testng.mode" value="mixed"> - <istrue value="${junit+testng.available}"/> - </condition> - <condition else="" property="testng.debug.mode" value="-mixed"> - <istrue value="${junit+testng.available}"/> - </condition> - </target> - <target name="-post-init"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check"> - <fail unless="src.dir">Must set src.dir</fail> - <fail unless="test.src.dir">Must set test.src.dir</fail> - <fail unless="build.dir">Must set build.dir</fail> - <fail unless="dist.dir">Must set dist.dir</fail> - <fail unless="build.classes.dir">Must set build.classes.dir</fail> - <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail> - <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail> - <fail unless="build.test.results.dir">Must set build.test.results.dir</fail> - <fail unless="build.classes.excludes">Must set build.classes.excludes</fail> - <fail unless="dist.jar">Must set dist.jar</fail> - </target> - <target name="-init-macrodef-property"> - <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1"> - <attribute name="name"/> - <attribute name="value"/> - <sequential> - <property name="@{name}" value="${@{value}}"/> - </sequential> - </macrodef> - </target> - <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors"> - <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${src.dir}" name="srcdir"/> - <attribute default="${build.classes.dir}" name="destdir"/> - <attribute default="${javac.classpath}" name="classpath"/> - <attribute default="${javac.processorpath}" name="processorpath"/> - <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="${javac.debug}" name="debug"/> - <attribute default="${empty.dir}" name="sourcepath"/> - <attribute default="${empty.dir}" name="gensrcdir"/> - <element name="customize" optional="true"/> - <sequential> - <property location="${build.dir}/empty" name="empty.dir"/> - <mkdir dir="${empty.dir}"/> - <mkdir dir="@{apgeneratedsrcdir}"/> - <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}"> - <src> - <dirset dir="@{gensrcdir}" erroronmissingdir="false"> - <include name="*"/> - </dirset> - </src> - <classpath> - <path path="@{classpath}"/> - </classpath> - <compilerarg line="${endorsed.classpath.cmd.line.arg}"/> - <compilerarg line="${javac.compilerargs}"/> - <compilerarg value="-processorpath"/> - <compilerarg path="@{processorpath}:${empty.dir}"/> - <compilerarg line="${ap.processors.internal}"/> - <compilerarg line="${annotation.processing.processor.options}"/> - <compilerarg value="-s"/> - <compilerarg path="@{apgeneratedsrcdir}"/> - <compilerarg line="${ap.proc.none.internal}"/> - <customize/> - </javac> - </sequential> - </macrodef> - </target> - <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal"> - <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${src.dir}" name="srcdir"/> - <attribute default="${build.classes.dir}" name="destdir"/> - <attribute default="${javac.classpath}" name="classpath"/> - <attribute default="${javac.processorpath}" name="processorpath"/> - <attribute default="${build.generated.sources.dir}/ap-source-output" name="apgeneratedsrcdir"/> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="${javac.debug}" name="debug"/> - <attribute default="${empty.dir}" name="sourcepath"/> - <attribute default="${empty.dir}" name="gensrcdir"/> - <element name="customize" optional="true"/> - <sequential> - <property location="${build.dir}/empty" name="empty.dir"/> - <mkdir dir="${empty.dir}"/> - <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" fork="${javac.fork}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" tempdir="${java.io.tmpdir}"> - <src> - <dirset dir="@{gensrcdir}" erroronmissingdir="false"> - <include name="*"/> - </dirset> - </src> - <classpath> - <path path="@{classpath}"/> - </classpath> - <compilerarg line="${endorsed.classpath.cmd.line.arg}"/> - <compilerarg line="${javac.compilerargs}"/> - <customize/> - </javac> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac"> - <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${src.dir}" name="srcdir"/> - <attribute default="${build.classes.dir}" name="destdir"/> - <attribute default="${javac.classpath}" name="classpath"/> - <sequential> - <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}"> - <classpath> - <path path="@{classpath}"/> - </classpath> - </depend> - </sequential> - </macrodef> - <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${build.classes.dir}" name="destdir"/> - <sequential> - <fail unless="javac.includes">Must set javac.includes</fail> - <pathconvert pathsep="${line.separator}" property="javac.includes.binary"> - <path> - <filelist dir="@{destdir}" files="${javac.includes}"/> - </path> - <globmapper from="*.java" to="*.class"/> - </pathconvert> - <tempfile deleteonexit="true" property="javac.includesfile.binary"/> - <echo file="${javac.includesfile.binary}" message="${javac.includes.binary}"/> - <delete> - <files includesfile="${javac.includesfile.binary}"/> - </delete> - <delete> - <fileset file="${javac.includesfile.binary}"/> - </delete> - </sequential> - </macrodef> - </target> - <target if="${junit.available}" name="-init-macrodef-junit-init"> - <condition else="false" property="nb.junit.batch" value="true"> - <and> - <istrue value="${junit.available}"/> - <not> - <isset property="test.method"/> - </not> - </and> - </condition> - <condition else="false" property="nb.junit.single" value="true"> - <and> - <istrue value="${junit.available}"/> - <isset property="test.method"/> - </and> - </condition> - </target> - <target if="${nb.junit.single}" name="-init-macrodef-junit-single" unless="${nb.junit.batch}"> - <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element name="customize" optional="true"/> - <sequential> - <property name="junit.forkmode" value="perTest"/> - <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}"> - <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/> - <syspropertyset> - <propertyref prefix="test-sys-prop."/> - <mapper from="test-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <formatter type="brief" usefile="false"/> - <formatter type="xml"/> - <jvmarg value="-ea"/> - <customize/> - </junit> - </sequential> - </macrodef> - </target> - <target if="${nb.junit.batch}" name="-init-macrodef-junit-batch" unless="${nb.junit.single}"> - <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element name="customize" optional="true"/> - <sequential> - <property name="junit.forkmode" value="perTest"/> - <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}"> - <batchtest todir="${build.test.results.dir}"> - <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}"> - <filename name="@{testincludes}"/> - </fileset> - </batchtest> - <syspropertyset> - <propertyref prefix="test-sys-prop."/> - <mapper from="test-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <formatter type="brief" usefile="false"/> - <formatter type="xml"/> - <jvmarg value="-ea"/> - <customize/> - </junit> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-junit-init,-init-macrodef-junit-single, -init-macrodef-junit-batch" if="${junit.available}" name="-init-macrodef-junit"/> - <target if="${testng.available}" name="-init-macrodef-testng"> - <macrodef name="testng" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element name="customize" optional="true"/> - <sequential> - <condition else="" property="testng.methods.arg" value="@{testincludes}.@{testmethods}"> - <isset property="test.method"/> - </condition> - <union id="test.set"> - <fileset dir="${test.src.dir}" excludes="@{excludes},**/*.xml,${excludes}" includes="@{includes}"> - <filename name="@{testincludes}"/> - </fileset> - </union> - <taskdef classname="org.testng.TestNGAntTask" classpath="${run.test.classpath}" name="testng"/> - <testng classfilesetref="test.set" failureProperty="tests.failed" methods="${testng.methods.arg}" mode="${testng.mode}" outputdir="${build.test.results.dir}" suitename="Sudoku" testname="TestNG tests" workingDir="${work.dir}"> - <xmlfileset dir="${build.test.classes.dir}" includes="@{testincludes}"/> - <propertyset> - <propertyref prefix="test-sys-prop."/> - <mapper from="test-sys-prop.*" to="*" type="glob"/> - </propertyset> - <customize/> - </testng> - </sequential> - </macrodef> - </target> - <target name="-init-macrodef-test-impl"> - <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element implicit="true" name="customize" optional="true"/> - <sequential> - <echo>No tests executed.</echo> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-junit" if="${junit.available}" name="-init-macrodef-junit-impl"> - <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element implicit="true" name="customize" optional="true"/> - <sequential> - <j2seproject3:junit excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> - <customize/> - </j2seproject3:junit> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-testng" if="${testng.available}" name="-init-macrodef-testng-impl"> - <macrodef name="test-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element implicit="true" name="customize" optional="true"/> - <sequential> - <j2seproject3:testng excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> - <customize/> - </j2seproject3:testng> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-test-impl,-init-macrodef-junit-impl,-init-macrodef-testng-impl" name="-init-macrodef-test"> - <macrodef name="test" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <sequential> - <j2seproject3:test-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> - <customize> - <classpath> - <path path="${run.test.classpath}"/> - </classpath> - <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> - <jvmarg line="${run.jvmargs}"/> - <jvmarg line="${run.jvmargs.ide}"/> - </customize> - </j2seproject3:test-impl> - </sequential> - </macrodef> - </target> - <target if="${junit.available}" name="-init-macrodef-junit-debug" unless="${nb.junit.batch}"> - <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element name="customize" optional="true"/> - <sequential> - <property name="junit.forkmode" value="perTest"/> - <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}"> - <test methods="@{testmethods}" name="@{testincludes}" todir="${build.test.results.dir}"/> - <syspropertyset> - <propertyref prefix="test-sys-prop."/> - <mapper from="test-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <formatter type="brief" usefile="false"/> - <formatter type="xml"/> - <jvmarg value="-ea"/> - <jvmarg line="${debug-args-line}"/> - <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/> - <customize/> - </junit> - </sequential> - </macrodef> - </target> - <target if="${nb.junit.batch}" name="-init-macrodef-junit-debug-batch"> - <macrodef name="junit-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element name="customize" optional="true"/> - <sequential> - <property name="junit.forkmode" value="perTest"/> - <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" forkmode="${junit.forkmode}" showoutput="true" tempdir="${build.dir}"> - <batchtest todir="${build.test.results.dir}"> - <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}"> - <filename name="@{testincludes}"/> - </fileset> - </batchtest> - <syspropertyset> - <propertyref prefix="test-sys-prop."/> - <mapper from="test-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <formatter type="brief" usefile="false"/> - <formatter type="xml"/> - <jvmarg value="-ea"/> - <jvmarg line="${debug-args-line}"/> - <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/> - <customize/> - </junit> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-junit-debug,-init-macrodef-junit-debug-batch" if="${junit.available}" name="-init-macrodef-junit-debug-impl"> - <macrodef name="test-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <element implicit="true" name="customize" optional="true"/> - <sequential> - <j2seproject3:junit-debug excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> - <customize/> - </j2seproject3:junit-debug> - </sequential> - </macrodef> - </target> - <target if="${testng.available}" name="-init-macrodef-testng-debug"> - <macrodef name="testng-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${main.class}" name="testClass"/> - <attribute default="" name="testMethod"/> - <element name="customize2" optional="true"/> - <sequential> - <condition else="-testclass @{testClass}" property="test.class.or.method" value="-methods @{testClass}.@{testMethod}"> - <isset property="test.method"/> - </condition> - <condition else="-suitename Sudoku -testname @{testClass} ${test.class.or.method}" property="testng.cmd.args" value="@{testClass}"> - <matches pattern=".*\.xml" string="@{testClass}"/> - </condition> - <delete dir="${build.test.results.dir}" quiet="true"/> - <mkdir dir="${build.test.results.dir}"/> - <j2seproject3:debug classname="org.testng.TestNG" classpath="${debug.test.classpath}"> - <customize> - <customize2/> - <jvmarg value="-ea"/> - <arg line="${testng.debug.mode}"/> - <arg line="-d ${build.test.results.dir}"/> - <arg line="-listener org.testng.reporters.VerboseReporter"/> - <arg line="${testng.cmd.args}"/> - </customize> - </j2seproject3:debug> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-testng-debug" if="${testng.available}" name="-init-macrodef-testng-debug-impl"> - <macrodef name="testng-debug-impl" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${main.class}" name="testClass"/> - <attribute default="" name="testMethod"/> - <element implicit="true" name="customize2" optional="true"/> - <sequential> - <j2seproject3:testng-debug testClass="@{testClass}" testMethod="@{testMethod}"> - <customize2/> - </j2seproject3:testng-debug> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-junit-debug-impl" if="${junit.available}" name="-init-macrodef-test-debug-junit"> - <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <attribute default="${main.class}" name="testClass"/> - <attribute default="" name="testMethod"/> - <sequential> - <j2seproject3:test-debug-impl excludes="@{excludes}" includes="@{includes}" testincludes="@{testincludes}" testmethods="@{testmethods}"> - <customize> - <classpath> - <path path="${run.test.classpath}"/> - </classpath> - <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> - <jvmarg line="${run.jvmargs}"/> - <jvmarg line="${run.jvmargs.ide}"/> - </customize> - </j2seproject3:test-debug-impl> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-testng-debug-impl" if="${testng.available}" name="-init-macrodef-test-debug-testng"> - <macrodef name="test-debug" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${includes}" name="includes"/> - <attribute default="${excludes}" name="excludes"/> - <attribute default="**" name="testincludes"/> - <attribute default="" name="testmethods"/> - <attribute default="${main.class}" name="testClass"/> - <attribute default="" name="testMethod"/> - <sequential> - <j2seproject3:testng-debug-impl testClass="@{testClass}" testMethod="@{testMethod}"> - <customize2> - <syspropertyset> - <propertyref prefix="test-sys-prop."/> - <mapper from="test-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - </customize2> - </j2seproject3:testng-debug-impl> - </sequential> - </macrodef> - </target> - <target depends="-init-macrodef-test-debug-junit,-init-macrodef-test-debug-testng" name="-init-macrodef-test-debug"/> - <!-- - pre NB7.2 profiling section; consider it deprecated - --> - <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile, -profile-init-check" if="profiler.info.jvmargs.agent" name="profile-init"/> - <target if="profiler.info.jvmargs.agent" name="-profile-pre-init"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target if="profiler.info.jvmargs.agent" name="-profile-post-init"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target if="profiler.info.jvmargs.agent" name="-profile-init-macrodef-profile"> - <macrodef name="resolve"> - <attribute name="name"/> - <attribute name="value"/> - <sequential> - <property name="@{name}" value="${env.@{value}}"/> - </sequential> - </macrodef> - <macrodef name="profile"> - <attribute default="${main.class}" name="classname"/> - <element name="customize" optional="true"/> - <sequential> - <property environment="env"/> - <resolve name="profiler.current.path" value="${profiler.info.pathvar}"/> - <java classname="@{classname}" dir="${profiler.info.dir}" fork="true" jvm="${profiler.info.jvm}"> - <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> - <jvmarg value="${profiler.info.jvmargs.agent}"/> - <jvmarg line="${profiler.info.jvmargs}"/> - <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/> - <arg line="${application.args}"/> - <classpath> - <path path="${run.classpath}"/> - </classpath> - <syspropertyset> - <propertyref prefix="run-sys-prop."/> - <mapper from="run-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <customize/> - </java> - </sequential> - </macrodef> - </target> - <target depends="-profile-pre-init, init, -profile-post-init, -profile-init-macrodef-profile" if="profiler.info.jvmargs.agent" name="-profile-init-check"> - <fail unless="profiler.info.jvm">Must set JVM to use for profiling in profiler.info.jvm</fail> - <fail unless="profiler.info.jvmargs.agent">Must set profiler agent JVM arguments in profiler.info.jvmargs.agent</fail> - </target> - <!-- - end of pre NB7.2 profiling section - --> - <target depends="-init-debug-args" name="-init-macrodef-nbjpda"> - <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1"> - <attribute default="${main.class}" name="name"/> - <attribute default="${debug.classpath}" name="classpath"/> - <attribute default="" name="stopclassname"/> - <sequential> - <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}"> - <classpath> - <path path="@{classpath}"/> - </classpath> - </nbjpdastart> - </sequential> - </macrodef> - <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1"> - <attribute default="${build.classes.dir}" name="dir"/> - <sequential> - <nbjpdareload> - <fileset dir="@{dir}" includes="${fix.classes}"> - <include name="${fix.includes}*.class"/> - </fileset> - </nbjpdareload> - </sequential> - </macrodef> - </target> - <target name="-init-debug-args"> - <property name="version-output" value="java version "${ant.java.version}"/> - <condition property="have-jdk-older-than-1.4"> - <or> - <contains string="${version-output}" substring="java version "1.0"/> - <contains string="${version-output}" substring="java version "1.1"/> - <contains string="${version-output}" substring="java version "1.2"/> - <contains string="${version-output}" substring="java version "1.3"/> - </or> - </condition> - <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none"> - <istrue value="${have-jdk-older-than-1.4}"/> - </condition> - <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem"> - <os family="windows"/> - </condition> - <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}"> - <isset property="debug.transport"/> - </condition> - </target> - <target depends="-init-debug-args" name="-init-macrodef-debug"> - <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${main.class}" name="classname"/> - <attribute default="${debug.classpath}" name="classpath"/> - <element name="customize" optional="true"/> - <sequential> - <java classname="@{classname}" dir="${work.dir}" fork="true"> - <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> - <jvmarg line="${debug-args-line}"/> - <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/> - <jvmarg value="-Dfile.encoding=${runtime.encoding}"/> - <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/> - <jvmarg line="${run.jvmargs}"/> - <jvmarg line="${run.jvmargs.ide}"/> - <classpath> - <path path="@{classpath}"/> - </classpath> - <syspropertyset> - <propertyref prefix="run-sys-prop."/> - <mapper from="run-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <customize/> - </java> - </sequential> - </macrodef> - </target> - <target name="-init-macrodef-java"> - <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1"> - <attribute default="${main.class}" name="classname"/> - <attribute default="${run.classpath}" name="classpath"/> - <attribute default="jvm" name="jvm"/> - <element name="customize" optional="true"/> - <sequential> - <java classname="@{classname}" dir="${work.dir}" fork="true"> - <jvmarg line="${endorsed.classpath.cmd.line.arg}"/> - <jvmarg value="-Dfile.encoding=${runtime.encoding}"/> - <redirector errorencoding="${runtime.encoding}" inputencoding="${runtime.encoding}" outputencoding="${runtime.encoding}"/> - <jvmarg line="${run.jvmargs}"/> - <jvmarg line="${run.jvmargs.ide}"/> - <classpath> - <path path="@{classpath}"/> - </classpath> - <syspropertyset> - <propertyref prefix="run-sys-prop."/> - <mapper from="run-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <customize/> - </java> - </sequential> - </macrodef> - </target> - <target name="-init-macrodef-copylibs"> - <macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3"> - <attribute default="${manifest.file}" name="manifest"/> - <element name="customize" optional="true"/> - <sequential> - <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> - <pathconvert property="run.classpath.without.build.classes.dir"> - <path path="${run.classpath}"/> - <map from="${build.classes.dir.resolved}" to=""/> - </pathconvert> - <pathconvert pathsep=" " property="jar.classpath"> - <path path="${run.classpath.without.build.classes.dir}"/> - <chainedmapper> - <flattenmapper/> - <filtermapper> - <replacestring from=" " to="%20"/> - </filtermapper> - <globmapper from="*" to="lib/*"/> - </chainedmapper> - </pathconvert> - <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/> - <copylibs compress="${jar.compress}" index="${jar.index}" indexMetaInf="${jar.index.metainf}" jarfile="${dist.jar}" manifest="@{manifest}" rebase="${copylibs.rebase}" runtimeclasspath="${run.classpath.without.build.classes.dir}"> - <fileset dir="${build.classes.dir}"/> - <manifest> - <attribute name="Class-Path" value="${jar.classpath}"/> - <customize/> - </manifest> - </copylibs> - </sequential> - </macrodef> - </target> - <target name="-init-presetdef-jar"> - <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1"> - <jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}"> - <j2seproject1:fileset dir="${build.classes.dir}"/> - </jar> - </presetdef> - </target> - <target name="-init-ap-cmdline-properties"> - <property name="annotation.processing.enabled" value="true"/> - <property name="annotation.processing.processors.list" value=""/> - <property name="annotation.processing.processor.options" value=""/> - <property name="annotation.processing.run.all.processors" value="true"/> - <property name="javac.processorpath" value="${javac.classpath}"/> - <property name="javac.test.processorpath" value="${javac.test.classpath}"/> - <condition property="ap.supported.internal" value="true"> - <not> - <matches pattern="1\.[0-5](\..*)?" string="${javac.source}"/> - </not> - </condition> - </target> - <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-ap-cmdline-supported"> - <condition else="" property="ap.processors.internal" value="-processor ${annotation.processing.processors.list}"> - <isfalse value="${annotation.processing.run.all.processors}"/> - </condition> - <condition else="" property="ap.proc.none.internal" value="-proc:none"> - <isfalse value="${annotation.processing.enabled}"/> - </condition> - </target> - <target depends="-init-ap-cmdline-properties,-init-ap-cmdline-supported" name="-init-ap-cmdline"> - <property name="ap.cmd.line.internal" value=""/> - </target> - <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-test,-init-macrodef-test-debug,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar,-init-ap-cmdline" name="init"/> - <!-- - =================== - COMPILATION SECTION - =================== - --> - <target name="-deps-jar-init" unless="built-jar.properties"> - <property location="${build.dir}/built-jar.properties" name="built-jar.properties"/> - <delete file="${built-jar.properties}" quiet="true"/> - </target> - <target if="already.built.jar.${basedir}" name="-warn-already-built-jar"> - <echo level="warn" message="Cycle detected: Sudoku was already built"/> - </target> - <target depends="init,-deps-jar-init" name="deps-jar" unless="no.deps"> - <mkdir dir="${build.dir}"/> - <touch file="${built-jar.properties}" verbose="false"/> - <property file="${built-jar.properties}" prefix="already.built.jar."/> - <antcall target="-warn-already-built-jar"/> - <propertyfile file="${built-jar.properties}"> - <entry key="${basedir}" value=""/> - </propertyfile> - </target> - <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/> - <target depends="init" name="-check-automatic-build"> - <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/> - </target> - <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build"> - <antcall target="clean"/> - </target> - <target depends="init,deps-jar" name="-pre-pre-compile"> - <mkdir dir="${build.classes.dir}"/> - </target> - <target name="-pre-compile"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target if="do.depend.true" name="-compile-depend"> - <pathconvert property="build.generated.subdirs"> - <dirset dir="${build.generated.sources.dir}" erroronmissingdir="false"> - <include name="*"/> - </dirset> - </pathconvert> - <j2seproject3:depend srcdir="${src.dir}:${build.generated.subdirs}"/> - </target> - <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile"> - <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/> - <copy todir="${build.classes.dir}"> - <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> - </copy> - </target> - <target if="has.persistence.xml" name="-copy-persistence-xml"> - <mkdir dir="${build.classes.dir}/META-INF"/> - <copy todir="${build.classes.dir}/META-INF"> - <fileset dir="${meta.inf.dir}" includes="persistence.xml"/> - </copy> - </target> - <target name="-post-compile"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/> - <target name="-pre-compile-single"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single"> - <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> - <j2seproject3:force-recompile/> - <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.dir}"/> - </target> - <target name="-post-compile-single"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/> - <!-- - ==================== - JAR BUILDING SECTION - ==================== - --> - <target depends="init" name="-pre-pre-jar"> - <dirname file="${dist.jar}" property="dist.jar.dir"/> - <mkdir dir="${dist.jar.dir}"/> - </target> - <target name="-pre-jar"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive" name="-do-jar-without-manifest" unless="manifest.available-mkdist.available"> - <j2seproject1:jar/> - </target> - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class-mkdist.available"> - <j2seproject1:jar manifest="${manifest.file}"/> - </target> - <target depends="init,compile,-pre-pre-jar,-pre-jar" if="do.archive+manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available"> - <j2seproject1:jar manifest="${manifest.file}"> - <j2seproject1:manifest> - <j2seproject1:attribute name="Main-Class" value="${main.class}"/> - </j2seproject1:manifest> - </j2seproject1:jar> - <echo level="info">To run this application from the command line without Ant, try:</echo> - <property location="${build.classes.dir}" name="build.classes.dir.resolved"/> - <property location="${dist.jar}" name="dist.jar.resolved"/> - <pathconvert property="run.classpath.with.dist.jar"> - <path path="${run.classpath}"/> - <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/> - </pathconvert> - <echo level="info">java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo> - </target> - <target depends="init" if="do.archive" name="-do-jar-with-libraries-create-manifest" unless="manifest.available"> - <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/> - <touch file="${tmp.manifest.file}" verbose="false"/> - </target> - <target depends="init" if="do.archive+manifest.available" name="-do-jar-with-libraries-copy-manifest"> - <tempfile deleteonexit="true" destdir="${build.dir}" property="tmp.manifest.file"/> - <copy file="${manifest.file}" tofile="${tmp.manifest.file}"/> - </target> - <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+main.class.available" name="-do-jar-with-libraries-set-main"> - <manifest file="${tmp.manifest.file}" mode="update"> - <attribute name="Main-Class" value="${main.class}"/> - </manifest> - </target> - <target depends="init,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest" if="do.archive+splashscreen.available" name="-do-jar-with-libraries-set-splashscreen"> - <basename file="${application.splash}" property="splashscreen.basename"/> - <mkdir dir="${build.classes.dir}/META-INF"/> - <copy failonerror="false" file="${application.splash}" todir="${build.classes.dir}/META-INF"/> - <manifest file="${tmp.manifest.file}" mode="update"> - <attribute name="SplashScreen-Image" value="META-INF/${splashscreen.basename}"/> - </manifest> - </target> - <target depends="init,-init-macrodef-copylibs,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen" if="do.mkdist" name="-do-jar-with-libraries-pack"> - <j2seproject3:copylibs manifest="${tmp.manifest.file}"/> - <echo level="info">To run this application from the command line without Ant, try:</echo> - <property location="${dist.jar}" name="dist.jar.resolved"/> - <echo level="info">java -jar "${dist.jar.resolved}"</echo> - </target> - <target depends="-do-jar-with-libraries-pack" if="do.archive" name="-do-jar-with-libraries-delete-manifest"> - <delete> - <fileset file="${tmp.manifest.file}"/> - </delete> - </target> - <target depends="init,compile,-pre-pre-jar,-pre-jar,-do-jar-with-libraries-create-manifest,-do-jar-with-libraries-copy-manifest,-do-jar-with-libraries-set-main,-do-jar-with-libraries-set-splashscreen,-do-jar-with-libraries-pack,-do-jar-with-libraries-delete-manifest" name="-do-jar-with-libraries"/> - <target name="-post-jar"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/> - <!-- - ================= - EXECUTION SECTION - ================= - --> - <target depends="init,compile" description="Run a main class." name="run"> - <j2seproject1:java> - <customize> - <arg line="${application.args}"/> - </customize> - </j2seproject1:java> - </target> - <target name="-do-not-recompile"> - <property name="javac.includes.binary" value=""/> - </target> - <target depends="init,compile-single" name="run-single"> - <fail unless="run.class">Must select one file in the IDE or set run.class</fail> - <j2seproject1:java classname="${run.class}"/> - </target> - <target depends="init,compile-test-single" name="run-test-with-main"> - <fail unless="run.class">Must select one file in the IDE or set run.class</fail> - <j2seproject1:java classname="${run.class}" classpath="${run.test.classpath}"/> - </target> - <!-- - ================= - DEBUGGING SECTION - ================= - --> - <target depends="init" if="netbeans.home" name="-debug-start-debugger"> - <j2seproject1:nbjpdastart name="${debug.class}"/> - </target> - <target depends="init" if="netbeans.home" name="-debug-start-debugger-main-test"> - <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${debug.class}"/> - </target> - <target depends="init,compile" name="-debug-start-debuggee"> - <j2seproject3:debug> - <customize> - <arg line="${application.args}"/> - </customize> - </j2seproject3:debug> - </target> - <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/> - <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto"> - <j2seproject1:nbjpdastart stopclassname="${main.class}"/> - </target> - <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/> - <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single"> - <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> - <j2seproject3:debug classname="${debug.class}"/> - </target> - <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/> - <target depends="init,compile-test-single" if="netbeans.home" name="-debug-start-debuggee-main-test"> - <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail> - <j2seproject3:debug classname="${debug.class}" classpath="${debug.test.classpath}"/> - </target> - <target depends="init,compile-test-single,-debug-start-debugger-main-test,-debug-start-debuggee-main-test" if="netbeans.home" name="debug-test-with-main"/> - <target depends="init" name="-pre-debug-fix"> - <fail unless="fix.includes">Must set fix.includes</fail> - <property name="javac.includes" value="${fix.includes}.java"/> - </target> - <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix"> - <j2seproject1:nbjpdareload/> - </target> - <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/> - <!-- - ================= - PROFILING SECTION - ================= - --> - <!-- - pre NB7.2 profiler integration - --> - <target depends="profile-init,compile" description="Profile a project in the IDE." if="profiler.info.jvmargs.agent" name="-profile-pre72"> - <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> - <nbprofiledirect> - <classpath> - <path path="${run.classpath}"/> - </classpath> - </nbprofiledirect> - <profile/> - </target> - <target depends="profile-init,compile-single" description="Profile a selected class in the IDE." if="profiler.info.jvmargs.agent" name="-profile-single-pre72"> - <fail unless="profile.class">Must select one file in the IDE or set profile.class</fail> - <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> - <nbprofiledirect> - <classpath> - <path path="${run.classpath}"/> - </classpath> - </nbprofiledirect> - <profile classname="${profile.class}"/> - </target> - <target depends="profile-init,compile-single" if="profiler.info.jvmargs.agent" name="-profile-applet-pre72"> - <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> - <nbprofiledirect> - <classpath> - <path path="${run.classpath}"/> - </classpath> - </nbprofiledirect> - <profile classname="sun.applet.AppletViewer"> - <customize> - <arg value="${applet.url}"/> - </customize> - </profile> - </target> - <target depends="profile-init,compile-test-single" if="profiler.info.jvmargs.agent" name="-profile-test-single-pre72"> - <fail unless="netbeans.home">This target only works when run from inside the NetBeans IDE.</fail> - <nbprofiledirect> - <classpath> - <path path="${run.test.classpath}"/> - </classpath> - </nbprofiledirect> - <junit dir="${profiler.info.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" jvm="${profiler.info.jvm}" showoutput="true"> - <env key="${profiler.info.pathvar}" path="${profiler.info.agentpath}:${profiler.current.path}"/> - <jvmarg value="${profiler.info.jvmargs.agent}"/> - <jvmarg line="${profiler.info.jvmargs}"/> - <test name="${profile.class}"/> - <classpath> - <path path="${run.test.classpath}"/> - </classpath> - <syspropertyset> - <propertyref prefix="test-sys-prop."/> - <mapper from="test-sys-prop.*" to="*" type="glob"/> - </syspropertyset> - <formatter type="brief" usefile="false"/> - <formatter type="xml"/> - </junit> - </target> - <!-- - end of pre NB72 profiling section - --> - <target if="netbeans.home" name="-profile-check"> - <condition property="profiler.configured"> - <or> - <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-agentpath:"/> - <contains casesensitive="true" string="${run.jvmargs.ide}" substring="-javaagent:"/> - </or> - </condition> - </target> - <target depends="-profile-check,-profile-pre72" description="Profile a project in the IDE." if="profiler.configured" name="profile" unless="profiler.info.jvmargs.agent"> - <startprofiler/> - <antcall target="run"/> - </target> - <target depends="-profile-check,-profile-single-pre72" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-single" unless="profiler.info.jvmargs.agent"> - <fail unless="run.class">Must select one file in the IDE or set run.class</fail> - <startprofiler/> - <antcall target="run-single"/> - </target> - <target depends="-profile-test-single-pre72" description="Profile a selected test in the IDE." name="profile-test-single"/> - <target depends="-profile-check" description="Profile a selected test in the IDE." if="profiler.configured" name="profile-test" unless="profiler.info.jvmargs"> - <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> - <startprofiler/> - <antcall target="test-single"/> - </target> - <target depends="-profile-check" description="Profile a selected class in the IDE." if="profiler.configured" name="profile-test-with-main"> - <fail unless="run.class">Must select one file in the IDE or set run.class</fail> - <startprofiler/> - <antcal target="run-test-with-main"/> - </target> - <target depends="-profile-check,-profile-applet-pre72" if="profiler.configured" name="profile-applet" unless="profiler.info.jvmargs.agent"> - <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> - <startprofiler/> - <antcall target="run-applet"/> - </target> - <!-- - =============== - JAVADOC SECTION - =============== - --> - <target depends="init" if="have.sources" name="-javadoc-build"> - <mkdir dir="${dist.javadoc.dir}"/> - <condition else="" property="javadoc.endorsed.classpath.cmd.line.arg" value="-J${endorsed.classpath.cmd.line.arg}"> - <and> - <isset property="endorsed.classpath.cmd.line.arg"/> - <not> - <equals arg1="${endorsed.classpath.cmd.line.arg}" arg2=""/> - </not> - </and> - </condition> - <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> - <classpath> - <path path="${javac.classpath}"/> - </classpath> - <fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}"> - <filename name="**/*.java"/> - </fileset> - <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false"> - <include name="**/*.java"/> - <exclude name="*.java"/> - </fileset> - <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/> - </javadoc> - <copy todir="${dist.javadoc.dir}"> - <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}"> - <filename name="**/doc-files/**"/> - </fileset> - <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false"> - <include name="**/doc-files/**"/> - </fileset> - </copy> - </target> - <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview"> - <nbbrowse file="${dist.javadoc.dir}/index.html"/> - </target> - <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/> - <!-- - ========================= - TEST COMPILATION SECTION - ========================= - --> - <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test"> - <mkdir dir="${build.test.classes.dir}"/> - </target> - <target name="-pre-compile-test"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target if="do.depend.true" name="-compile-test-depend"> - <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/> - </target> - <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test"> - <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" processorpath="${javac.test.processorpath}" srcdir="${test.src.dir}"/> - <copy todir="${build.test.classes.dir}"> - <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> - </copy> - </target> - <target name="-post-compile-test"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/> - <target name="-pre-compile-test-single"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,deps-jar,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single"> - <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail> - <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/> - <j2seproject3:javac apgeneratedsrcdir="${build.test.classes.dir}" classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" processorpath="${javac.test.processorpath}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/> - <copy todir="${build.test.classes.dir}"> - <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/> - </copy> - </target> - <target name="-post-compile-test-single"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/> - <!-- - ======================= - TEST EXECUTION SECTION - ======================= - --> - <target depends="init" if="have.tests" name="-pre-test-run"> - <mkdir dir="${build.test.results.dir}"/> - </target> - <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run"> - <j2seproject3:test testincludes="**/*Test.java"/> - </target> - <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run"> - <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> - </target> - <target depends="init" if="have.tests" name="test-report"/> - <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/> - <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/> - <target depends="init" if="have.tests" name="-pre-test-run-single"> - <mkdir dir="${build.test.results.dir}"/> - </target> - <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single"> - <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail> - <j2seproject3:test excludes="" includes="${test.includes}" testincludes="${test.includes}"/> - </target> - <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single"> - <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> - </target> - <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/> - <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single-method"> - <fail unless="test.class">Must select some files in the IDE or set test.class</fail> - <fail unless="test.method">Must select some method in the IDE or set test.method</fail> - <j2seproject3:test excludes="" includes="${javac.includes}" testincludes="${test.class}" testmethods="${test.method}"/> - </target> - <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method" if="have.tests" name="-post-test-run-single-method"> - <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> - </target> - <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single-method,-post-test-run-single-method" description="Run single unit test." name="test-single-method"/> - <!-- - ======================= - TEST DEBUGGING SECTION - ======================= - --> - <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test"> - <fail unless="test.class">Must select one file in the IDE or set test.class</fail> - <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testincludes="${javac.includes}"/> - </target> - <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-debug-start-debuggee-test-method"> - <fail unless="test.class">Must select one file in the IDE or set test.class</fail> - <fail unless="test.method">Must select some method in the IDE or set test.method</fail> - <j2seproject3:test-debug excludes="" includes="${javac.includes}" testClass="${test.class}" testMethod="${test.method}" testincludes="${test.class}" testmethods="${test.method}"/> - </target> - <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test"> - <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/> - </target> - <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/> - <target depends="init,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test-method" name="debug-test-method"/> - <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test"> - <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/> - </target> - <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/> - <!-- - ========================= - APPLET EXECUTION SECTION - ========================= - --> - <target depends="init,compile-single" name="run-applet"> - <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> - <j2seproject1:java classname="sun.applet.AppletViewer"> - <customize> - <arg value="${applet.url}"/> - </customize> - </j2seproject1:java> - </target> - <!-- - ========================= - APPLET DEBUGGING SECTION - ========================= - --> - <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet"> - <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail> - <j2seproject3:debug classname="sun.applet.AppletViewer"> - <customize> - <arg value="${applet.url}"/> - </customize> - </j2seproject3:debug> - </target> - <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/> - <!-- - =============== - CLEANUP SECTION - =============== - --> - <target name="-deps-clean-init" unless="built-clean.properties"> - <property location="${build.dir}/built-clean.properties" name="built-clean.properties"/> - <delete file="${built-clean.properties}" quiet="true"/> - </target> - <target if="already.built.clean.${basedir}" name="-warn-already-built-clean"> - <echo level="warn" message="Cycle detected: Sudoku was already built"/> - </target> - <target depends="init,-deps-clean-init" name="deps-clean" unless="no.deps"> - <mkdir dir="${build.dir}"/> - <touch file="${built-clean.properties}" verbose="false"/> - <property file="${built-clean.properties}" prefix="already.built.clean."/> - <antcall target="-warn-already-built-clean"/> - <propertyfile file="${built-clean.properties}"> - <entry key="${basedir}" value=""/> - </propertyfile> - </target> - <target depends="init" name="-do-clean"> - <delete dir="${build.dir}"/> - <delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/> - </target> - <target name="-post-clean"> - <!-- Empty placeholder for easier customization. --> - <!-- You can override this target in the ../build.xml file. --> - </target> - <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/> - <target name="-check-call-dep"> - <property file="${call.built.properties}" prefix="already.built."/> - <condition property="should.call.dep"> - <and> - <not> - <isset property="already.built.${call.subproject}"/> - </not> - <available file="${call.script}"/> - </and> - </condition> - </target> - <target depends="-check-call-dep" if="should.call.dep" name="-maybe-call-dep"> - <ant antfile="${call.script}" inheritall="false" target="${call.target}"> - <propertyset> - <propertyref prefix="transfer."/> - <mapper from="transfer.*" to="*" type="glob"/> - </propertyset> - </ant> - </target> -</project>
--- a/nbproject/genfiles.properties Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=7c7a460d -build.xml.script.CRC32=0dfebe00 -build.xml.stylesheet.CRC32=28e38971@1.53.1.46 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=7c7a460d -nbproject/build-impl.xml.script.CRC32=2bd010ed -nbproject/build-impl.xml.stylesheet.CRC32=6ddba6b6@1.53.1.46
--- a/nbproject/project.properties Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -annotation.processing.enabled=true -annotation.processing.enabled.in.editor=false -annotation.processing.processor.options= -annotation.processing.processors.list= -annotation.processing.run.all.processors=true -annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -build.classes.dir=${build.dir}/classes -build.classes.excludes=**/*.java,**/*.form -# This directory is removed when the project is cleaned: -build.dir=build -build.generated.dir=${build.dir}/generated -build.generated.sources.dir=${build.dir}/generated-sources -# Only compile against the classpath explicitly listed here: -build.sysclasspath=ignore -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -# Uncomment to specify the preferred debugger connection transport: -#debug.transport=dt_socket -debug.classpath=\ - ${run.classpath} -debug.test.classpath=\ - ${run.test.classpath} -# This directory is removed when the project is cleaned: -dist.dir=dist -dist.jar=${dist.dir}/Sudoku.jar -dist.javadoc.dir=${dist.dir}/javadoc -excludes= -includes=** -jar.compress=false -javac.classpath= -# Space-separated list of extra javac options -javac.compilerargs= -javac.deprecation=false -javac.processorpath=\ - ${javac.classpath} -javac.source=1.7 -javac.target=1.7 -javac.test.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -javac.test.processorpath=\ - ${javac.test.classpath} -javadoc.additionalparam= -javadoc.author=false -javadoc.encoding=${source.encoding} -javadoc.noindex=false -javadoc.nonavbar=false -javadoc.notree=false -javadoc.private=false -javadoc.splitindex=true -javadoc.use=true -javadoc.version=false -javadoc.windowtitle= -main.class=de.uapcore.sudoku.Sudoku -manifest.file=manifest.mf -meta.inf.dir=${src.dir}/META-INF -mkdist.disabled=false -platform.active=default_platform -run.classpath=\ - ${javac.classpath}:\ - ${build.classes.dir} -# Space-separated list of JVM arguments used when running the project. -# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. -# To set system properties for unit tests define test-sys-prop.name=value: -run.jvmargs= -run.test.classpath=\ - ${javac.test.classpath}:\ - ${build.test.classes.dir} -source.encoding=UTF-8 -src.dir=src -test.src.dir=test
--- a/nbproject/project.xml Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://www.netbeans.org/ns/project/1"> - <type>org.netbeans.modules.java.j2seproject</type> - <configuration> - <data xmlns="http://www.netbeans.org/ns/j2se-project/3"> - <name>Sudoku</name> - <source-roots> - <root id="src.dir"/> - </source-roots> - <test-roots> - <root id="test.src.dir"/> - </test-roots> - </data> - </configuration> -</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pom.xml Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,35 @@ +<project> + <modelVersion>4.0.0</modelVersion> + + <groupId>de.uapcore</groupId> + <artifactId>sudoku</artifactId> + <version>1.0</version> + + <build> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <version>3.0.2</version> + <configuration> + <archive> + <manifest> + <mainClass> + de.uapcore.sudoku.Sudoku + </mainClass> + </manifest> + </archive> + </configuration> + </plugin> + </plugins> + </build> +</project> +
--- a/src/de/uapcore/sudoku/ActionHandler.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.IOException; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; - -/** - * - * @author mike - */ -public final class ActionHandler implements ActionListener { - - public static final String SAVE = "save"; - public static final String CHECK = "check"; - public static final String SOLVE = "solve"; - - public static final String NEW = "new"; - public static final String OPEN = "open"; - public static final String SAVE_AS = "save as"; - public static final String QUIT = "quit"; - public static final String ABOUT = "about"; - - private Field field; - private Solver solver; - private DocumentHandler doc; - - public ActionHandler(Field f) { - field = f; - solver = new Solver(); - doc = new DocumentHandler(); - } - - private boolean chooseSaveFilename() { - JFileChooser fc = new JFileChooser("."); - fc.setMultiSelectionEnabled(false); - if (fc.showSaveDialog(field) == JFileChooser.APPROVE_OPTION) { - File f = fc.getSelectedFile(); - if (f.exists()) { - int result = JOptionPane.showConfirmDialog(field, - "Bereits existierende Datei überschreiben?", "Sudoku", - JOptionPane.YES_NO_OPTION); - if (result == JOptionPane.YES_OPTION) { - doc.setFilename(f.getAbsolutePath()); - return true; - } else { - return false; - } - } else { - doc.setFilename(f.getAbsolutePath()); - return true; - } - } else { - return false; - } - } - - private void open() { - JFileChooser fc = new JFileChooser("."); - fc.setMultiSelectionEnabled(false); - if (fc.showOpenDialog(field) == JFileChooser.APPROVE_OPTION) { - File f = fc.getSelectedFile(); - doc.setFilename(f.getAbsolutePath()); - try { - doc.load(field); - } catch (IOException e) { - JOptionPane.showMessageDialog(field, - "Datei konnte nicht geladen werden: "+e.getMessage(), - "Sudoku", JOptionPane.ERROR_MESSAGE); - } - } - } - - private boolean save(boolean rename) { - if (!doc.isFilenameSet() || rename) { - if (!chooseSaveFilename()) { - return false; - } - } - if (solver.check(field)) { - field.setAllCellsModified(false); - try { - doc.save(field); - } catch (IOException e) { - JOptionPane.showMessageDialog(field, - "Datei konnte nicht gespeichert werden: "+e.getMessage(), - "Sudoku", JOptionPane.ERROR_MESSAGE); - } - return true; - } else { - JOptionPane.showMessageDialog(field, - "Das Feld kann mit Fehlern nicht gespeichert werden!", - "Sudoku", JOptionPane.ERROR_MESSAGE); - return false; - } - } - - private void check() { - if (solver.check(field)) { - JOptionPane.showMessageDialog(field, "Überprüfung erfolgreich!", - "Sudoku", JOptionPane.INFORMATION_MESSAGE); - } else { - JOptionPane.showMessageDialog(field, "Das Feld enthält Fehler!", - "Sudoku", JOptionPane.WARNING_MESSAGE); - } - } - - private void solve() { - if (!solver.check(field) || !solver.solve(field)) { - JOptionPane.showMessageDialog(field, "Das Feld ist nicht lösbar!", - "Sudoku", JOptionPane.WARNING_MESSAGE); - } - } - - private boolean saveUnsaved() { - boolean proceed = false; - if (field.isAnyCellModified()) { - int result = JOptionPane.showConfirmDialog(field, - "Das Feld ist ungespeichert - jetzt speichern?", - "Sudoku", JOptionPane.YES_NO_CANCEL_OPTION); - if (result == JOptionPane.YES_OPTION) { - if (save(false)) { - proceed = true; - } - } else if (result == JOptionPane.NO_OPTION) { - proceed = true; - } - } else { - proceed = true; - } - - return proceed; - } - - @Override - public void actionPerformed(ActionEvent e) { - switch (e.getActionCommand()) { - case NEW: - if (saveUnsaved()) { - doc.clearFilename(); - field.clear(); - } - break; - case OPEN: - open(); - break; - case SAVE: - save(false); - break; - case SAVE_AS: - save(true); - break; - case CHECK: - check(); - break; - case SOLVE: - solve(); - break; - case QUIT: - if (saveUnsaved()) { - System.exit(0); - } - break; - case ABOUT: - JOptionPane.showMessageDialog(field, - "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de"+ - "\nPublished under the BSD License", - "Sudoku", JOptionPane.INFORMATION_MESSAGE); - break; - default: - throw new UnsupportedOperationException( - "unknown action: "+e.getActionCommand()); - } - } - -}
--- a/src/de/uapcore/sudoku/ButtonPanel.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import javax.swing.JButton; -import javax.swing.JPanel; - -/** - * - * @author mike - */ -public final class ButtonPanel extends JPanel { - - private JButton save, check, solve; - - public ButtonPanel(ActionHandler l) { - setLayout(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(10, 10, 10, 10); - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - - c.gridx = 0; - c.gridy = 0; - save = new JButton("Speichern"); - add(save, c); - c.gridx++; - check = new JButton("Prüfen"); - add(check, c); - solve = new JButton("Lösen"); - c.gridx++; - add(solve, c); - - save.setActionCommand(ActionHandler.SAVE); - save.addActionListener(l); - check.setActionCommand(ActionHandler.CHECK); - check.addActionListener(l); - solve.setActionCommand(ActionHandler.SOLVE); - solve.addActionListener(l); - - setBackground(Color.WHITE); - } -}
--- a/src/de/uapcore/sudoku/DocumentHandler.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * - * @author mike - */ -public class DocumentHandler { - - private String filename; - - public void load(Field field) throws IOException { - if (!isFilenameSet()) { - throw new IOException("no filename supplied"); - } - int row = 0; - try (BufferedReader in = new BufferedReader( - new InputStreamReader(new FileInputStream(filename)))) { - Pattern pat = Pattern.compile("^\\s*(?:[1-9_] ){8}[1-9_]\\s*$"); - String line; - while ((line = in.readLine()) != null) { - if (line.matches("^\\s*$")) { - continue; - } - Matcher m = pat.matcher(line); - if (m.matches()) { - String c[] = line.trim().split(" "); - if (c.length != 9) { - break; - } - for (int i = 0 ; i < 9 ; i++) { - field.setCellValue(i, row, - c[i].equals("_") ? 0 : Integer.valueOf(c[i])); - } - row++; - } else { - break; - } - } - if (row != 9) { - throw new IOException("Kein Sudoku-Feld enthalten!"); - } - } - field.setAllCellsModified(false); - } - - public void save(Field field) throws IOException { - if (!isFilenameSet()) { - throw new IOException("no filename supplied"); - } - - try (BufferedWriter out = new BufferedWriter( - new OutputStreamWriter(new FileOutputStream(filename)))) { - for (int i = 0 ; i < 9 ; i++) { - int[] row = field.getRow(i); - for (int j = 0 ; j < 9 ; j++) { - out.append(row[j] > 0 ? Character.forDigit(row[j], 10):'_'); - out.append(j == 8 ? '\n': ' '); - } - } - } - } - - public void setFilename(String filename) { - this.filename = filename; - } - - public void clearFilename() { - filename = null; - } - - public boolean isFilenameSet() { - return filename != null; - } -}
--- a/src/de/uapcore/sudoku/Field.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import java.awt.Color; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.image.BufferedImage; -import javax.swing.JPanel; - -/** - * - * @author mike - */ -public final class Field extends JPanel { - private SudokuTextField[][] cells; - - public Field() { - setBackground(Color.WHITE); - - setLayout(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(5, 5, 5, 5); - - cells = new SudokuTextField[9][9]; - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - cells[x][y] = new SudokuTextField(); - c.gridx = x; - c.gridy = y; - add(cells[x][y], c); - } - } - } - - @Override - public void paint(Graphics graphics) { - final int w = getWidth(); - final int h = getHeight(); - final int cw = w / 9; - final int ch = h / 9; - - BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); - Graphics2D g = img.createGraphics(); - g.setBackground(Color.WHITE); - g.clearRect(0, 0, w, h); - - g.setColor(Color.BLACK); - g.drawRect(1, 1, w-2, h-2); - g.drawRect(2, 2, w-4, h-4); - for (int x = cw ; x < w ; x += cw) { - for (int y = ch ; y < h ; y += ch) { - g.drawLine(x, 2, x, h-2); - g.drawLine(2, y, w-2, y); - if ((x / cw) % 3 == 0) { - g.drawLine(x+1, 2, x+1, h-2); - } - if ((y / ch) % 3 == 0) { - g.drawLine(2, y+1, w-2, y+1); - } - } - } - - graphics.drawImage(img, 0, 0, this); - super.paintChildren(graphics); - } - - public boolean isCellEmpty(int x, int y) { - return getCellValue(x, y) == 0; - } - - public int getCellValue(int x, int y) { - return cells[x][y].getValue(); - } - - public void setCellValue(int x, int y, int v) { - cells[x][y].setValue(v); - } - - public void clearCellValue(int x, int y) { - setCellValue(x, y, 0); - } - - public void setCellModified(int x, int y, boolean modified) { - cells[x][y].setModified(modified); - } - - public void setAllCellsModified(boolean modified) { - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - cells[x][y].setModified(modified); - } - } - } - - public boolean isAnyCellModified() { - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - if (cells[x][y].isModified()) { - return true; - } - } - } - return false; - } - - public void clear() { - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - cells[x][y].setValue(0); - } - } - } - - public int[][] getSquare(int x, int y) { - if (x < 0 || x > 2 || y < 0 || y > 2) { - throw new IllegalArgumentException("Invalid square coordinates"); - } - int[][] square = new int[3][3]; - - for (int u = 0 ; u < 3 ; u++) { - for (int v = 0 ; v < 3 ; v++) { - square[u][v] = getCellValue(3*x+u, 3*y+v); - } - } - - return square; - } - - public int[] getRow(int y) { - if (y < 0 || y > 8) { - throw new IllegalArgumentException("Invalid row number"); - } - int row[] = new int[9]; - - for (int x = 0 ; x < 9 ; x++) { - row[x] = getCellValue(x, y); - } - - return row; - } - - public int[] getColumn(int x) { - if (x < 0 || x > 8) { - throw new IllegalArgumentException("Invalid column number"); - } - int column[] = new int[9]; - - for (int y = 0 ; y < 9 ; y++) { - column[y] = getCellValue(x, y); - } - - return column; - } -}
--- a/src/de/uapcore/sudoku/MainMenu.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.KeyStroke; - -/** - * - * @author mike - */ -public class MainMenu { - - private ActionHandler handler; - private JMenuBar menuBar; - - public MainMenu(ActionHandler h) { - handler = h; - menuBar = new JMenuBar(); - menuBar.add(createMenu("Datei", 'd', - createMenuItem("Neu", 'n', "control N", ActionHandler.NEW), - createMenuItem("Öffnen", 'f', "control O", ActionHandler.OPEN), - createMenuItem("Speichern", 's', "control S", ActionHandler.SAVE), - createMenuItem("Speichern als...", 'a', ActionHandler.SAVE_AS), - createSeparator(), - createMenuItem("Prüfen", 'p', "control P", ActionHandler.CHECK), - createMenuItem("Lösen", 'l', "control L", ActionHandler.SOLVE), - createSeparator(), - createMenuItem("Beenden", 'e', ActionHandler.QUIT) - )); - menuBar.add(createMenu("Help", 'h', - createMenuItem("Über...", 'b', "F1", ActionHandler.ABOUT) - )); - } - - private JMenuItem createSeparator() { - // Return null, the createMenu method knows how to handle it - return null; - } - - private JMenu createMenu(String caption, char mnemonic, JMenuItem...items) { - JMenu menu = new JMenu(caption); - menu.setMnemonic(mnemonic); - for (JMenuItem item : items) { - if (item == null) { - menu.addSeparator(); - } else { - menu.add(item); - } - } - return menu; - } - - private JMenuItem createMenuItem(String caption, char mnemonic, - String command) { - return createMenuItem(caption, mnemonic, null, command); - } - - private JMenuItem createMenuItem(String caption, char mnemonic, - String stroke, String command) { - JMenuItem item = new JMenuItem(caption); - item.setMnemonic(mnemonic); - if (stroke != null) { - item.setAccelerator(KeyStroke.getKeyStroke(stroke)); - } - item.setActionCommand(command); - item.addActionListener(handler); - - return item; - } - - public JMenuBar getMenuBar() { - return menuBar; - } -}
--- a/src/de/uapcore/sudoku/Solver.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,227 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author mike - */ -public final class Solver { - - public Solver() { - } - - private Integer fillInCandidate(Field f, List<Integer>[][] candidates, int x, int y) { - Integer c = candidates[x][y].remove(0); - f.setCellValue(x, y, c); - f.setCellModified(x, y, true); - for (int i = 0 ; i < 9 ; i++) { - candidates[x][i].remove(c); - candidates[i][y].remove(c); - } - for (int i = 0 ; i < 3 ; i++) { - for (int j = 0 ; j < 3 ; j++) { - candidates[x-x%3+i][y-y%3+j].remove(c); - } - } - return c; - } - - private void makeBackup(List<Integer>[][] candidates, List<Integer>[][] candidatesBackup) { - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - candidatesBackup[x][y] = new ArrayList<>(9); - candidatesBackup[x][y].addAll(candidates[x][y]); - } - } - } - - private void makeBackup(Field f, int[][] fieldBackup) { - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - fieldBackup[x][y] = f.getCellValue(x, y); - } - } - } - - private void restoreBackup(Field f, int[][] fieldBackup) { - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - f.setCellValue(x, y, fieldBackup[x][y]); - } - } - } - - private void restoreBackup(List<Integer>[][] candidates, List<Integer>[][] candidatesBackup) { - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - candidates[x][y].clear(); - candidates[x][y].addAll(candidatesBackup[x][y]); - } - } - } - - private boolean solve(Field f, List<Integer>[][] candidates) { - - // Make backup - List<Integer>[][] candidatesBackup = new List[9][9]; - int[][] fieldBackup = new int[9][9]; - makeBackup(candidates, candidatesBackup); - makeBackup(f, fieldBackup); - - // Fill in distinct solutions - boolean fillDistinct; - do { - fillDistinct = false; - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - if (f.isCellEmpty(x, y) && candidates[x][y].size() == 1) { - fillInCandidate(f, candidates, x, y); - fillDistinct = true; - } - } - } - } while (fillDistinct); - - // Try out remaining candidates - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - if (f.isCellEmpty(x, y)) { - while (candidates[x][y].size() > 0) { - List<Integer>[][] cb = new List[9][9]; - makeBackup(candidates, cb); - Integer c = fillInCandidate(f, candidates, x, y); - if (solve(f, candidates)) { - break; - } else { - f.clearCellValue(x, y); - restoreBackup(candidates, cb); - // Remove current candidate anyway - candidates[x][y].remove(c); - } - } - } - if (f.isCellEmpty(x, y)) { - restoreBackup(f, fieldBackup); - restoreBackup(candidates, candidatesBackup); - return false; - } - } - } - - return true; - } - - public boolean solve(Field f) { - - // Calculate initial candidates - List<Integer> candidates[][] = new List[9][9]; - for (int x = 0 ; x < 9 ; x++) { - for (int y = 0 ; y < 9 ; y++) { - candidates[x][y] = new ArrayList<>(9); - if (f.getCellValue(x, y) == 0) { - // All numbers are candidates - for (int c = 1 ; c <= 9 ; c++) { - candidates[x][y].add(c); - } - // Remove row duplicates - int[] line = f.getRow(y); - for (Integer c : line) { - candidates[x][y].remove(c); - } - // Remove column duplicates - line = f.getColumn(x); - for (Integer c : line) { - candidates[x][y].remove(c); - } - // Remove square duplicates - int[][] square = f.getSquare(x/3, y/3); - for (int[] sq : square) { - for (Integer c : sq) { - candidates[x][y].remove(c); - } - } - } - } - } - - // Backtrack - return solve(f, candidates); - } - - public boolean check(Field f) { - int line[]; - for (int i = 0 ; i < 9 ; i++) { - line = f.getRow(i); - if (!valid(line)) { - return false; - } - line = f.getColumn(i); - if (!valid(line)) { - return false; - } - } - - int square[][]; - for (int x = 0 ; x < 3 ; x++) { - for (int y = 0 ; y < 3 ; y++) { - square = f.getSquare(x, y); - if (!valid(square)) { - return false; - } - } - } - - return true; - } - - private boolean valid(int[] line) { - int numbers[]; - numbers = new int[9]; - for (int i = 0 ; i < 9 ; i++) { - int l = line[i]-1; - if (l >= 0) { - if ((++numbers[l]) > 1) { - return false; - } - } - } - - return true; - } - - private boolean valid(int[][] square) { - int[] line = new int[9]; - for (int x = 0 ; x < 3 ; x++) { - System.arraycopy(square[x], 0, line, 3*x, 3); - } - return valid(line); - } -}
--- a/src/de/uapcore/sudoku/Sudoku.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import java.awt.Color; -import java.awt.Container; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import javax.swing.JFrame; - -/** - * - * @author mike - */ -public final class Sudoku extends JFrame { - - public Sudoku() { - super("Sudoku"); - - Field f = new Field(); - ActionHandler h = new ActionHandler(f); - setJMenuBar(new MainMenu(h).getMenuBar()); - - Container content = getContentPane(); - - content.setLayout(new GridBagLayout()); - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(20, 20, 20, 20); - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridx = 0; c.gridy = 0; - content.add(f, c); - c.gridy++; - content.add(new ButtonPanel(h), c); - - pack(); - content.setBackground(Color.WHITE); - setLocationByPlatform(true); - setDefaultCloseOperation(EXIT_ON_CLOSE); - } - - /** - * @param args the command line arguments - */ - public static void main(String[] args) { - new Sudoku().setVisible(true); - } -}
--- a/src/de/uapcore/sudoku/SudokuTextField.java Fri Feb 01 10:18:47 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/* - * Copyright 2013 Mike Becker. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package de.uapcore.sudoku; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import javax.swing.JTextField; - -/** - * - * @author mike - */ -public final class SudokuTextField extends JTextField { - - private boolean modified; - - public SudokuTextField() { - setBorder(null); - setBackground(Color.WHITE); - - setFont(new Font("Dialog", Font.PLAIN, 18)); - setHorizontalAlignment(JTextField.CENTER); - - Dimension dim = new Dimension(40,40); - setPreferredSize(dim); - setMinimumSize(dim); - setMaximumSize(dim); - - addKeyListener(new KeyAdapter() { - private void handle(KeyEvent e) { - char c = e.getKeyChar(); - if (!e.isAltDown() && !e.isControlDown() && - !Character.isISOControl(c)) { - // Perform clean input check - if (getText().length() > 0 && getSelectedText() == null) { - if (c != KeyEvent.CHAR_UNDEFINED) { - e.consume(); - } - } else { - if (c < '1' || c > '9') { - e.consume(); - } else { - setModified(true); - } - } - } else { - // We can still be tricked by hotkeys, so do it the hard way - if (!getText().matches("^[1-9]$")) { - setText(""); - } - } - } - - @Override - public void keyPressed(KeyEvent e) { - handle(e); - } - - @Override - public void keyTyped(KeyEvent e) { - handle(e); - } - - @Override - public void keyReleased(KeyEvent e) { - handle(e); - } - - }); - addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - selectAll(); - } - @Override - public void focusLost(FocusEvent e) { - select(0, 0); - } - }); - } - - public int getValue() { - if (getText().length() > 0) { - return Integer.valueOf(getText()); - } else { - return 0; - } - } - - public void setValue(int v) { - if (v == 0) { - setText(""); - } else if (v < 10) { - setText(String.valueOf(v)); - } else { - throw new IllegalArgumentException( - "Sudoku numbers must be in range 0-9 (0 means 'not set')"); - } - } - - public void setModified(boolean modified) { - this.modified = modified; - setForeground(modified?Color.BLUE:Color.BLACK); - } - - public boolean isModified() { - return modified; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/ActionHandler.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,203 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; + +/** + * + * @author mike + */ +public final class ActionHandler implements ActionListener { + + public static final String SAVE = "save"; + public static final String CHECK = "check"; + public static final String SOLVE = "solve"; + + public static final String NEW = "new"; + public static final String OPEN = "open"; + public static final String SAVE_AS = "save as"; + public static final String QUIT = "quit"; + public static final String ABOUT = "about"; + + private Field field; + private Solver solver; + private DocumentHandler doc; + + public ActionHandler(Field f) { + field = f; + solver = new Solver(); + doc = new DocumentHandler(); + } + + private boolean chooseSaveFilename() { + JFileChooser fc = new JFileChooser("."); + fc.setMultiSelectionEnabled(false); + if (fc.showSaveDialog(field) == JFileChooser.APPROVE_OPTION) { + File f = fc.getSelectedFile(); + if (f.exists()) { + int result = JOptionPane.showConfirmDialog(field, + "Bereits existierende Datei überschreiben?", "Sudoku", + JOptionPane.YES_NO_OPTION); + if (result == JOptionPane.YES_OPTION) { + doc.setFilename(f.getAbsolutePath()); + return true; + } else { + return false; + } + } else { + doc.setFilename(f.getAbsolutePath()); + return true; + } + } else { + return false; + } + } + + private void open() { + JFileChooser fc = new JFileChooser("."); + fc.setMultiSelectionEnabled(false); + if (fc.showOpenDialog(field) == JFileChooser.APPROVE_OPTION) { + File f = fc.getSelectedFile(); + doc.setFilename(f.getAbsolutePath()); + try { + doc.load(field); + } catch (IOException e) { + JOptionPane.showMessageDialog(field, + "Datei konnte nicht geladen werden: "+e.getMessage(), + "Sudoku", JOptionPane.ERROR_MESSAGE); + } + } + } + + private boolean save(boolean rename) { + if (!doc.isFilenameSet() || rename) { + if (!chooseSaveFilename()) { + return false; + } + } + if (solver.check(field)) { + field.setAllCellsModified(false); + try { + doc.save(field); + } catch (IOException e) { + JOptionPane.showMessageDialog(field, + "Datei konnte nicht gespeichert werden: "+e.getMessage(), + "Sudoku", JOptionPane.ERROR_MESSAGE); + } + return true; + } else { + JOptionPane.showMessageDialog(field, + "Das Feld kann mit Fehlern nicht gespeichert werden!", + "Sudoku", JOptionPane.ERROR_MESSAGE); + return false; + } + } + + private void check() { + if (solver.check(field)) { + JOptionPane.showMessageDialog(field, "Überprüfung erfolgreich!", + "Sudoku", JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog(field, "Das Feld enthält Fehler!", + "Sudoku", JOptionPane.WARNING_MESSAGE); + } + } + + private void solve() { + if (!solver.check(field) || !solver.solve(field)) { + JOptionPane.showMessageDialog(field, "Das Feld ist nicht lösbar!", + "Sudoku", JOptionPane.WARNING_MESSAGE); + } + } + + private boolean saveUnsaved() { + boolean proceed = false; + if (field.isAnyCellModified()) { + int result = JOptionPane.showConfirmDialog(field, + "Das Feld ist ungespeichert - jetzt speichern?", + "Sudoku", JOptionPane.YES_NO_CANCEL_OPTION); + if (result == JOptionPane.YES_OPTION) { + if (save(false)) { + proceed = true; + } + } else if (result == JOptionPane.NO_OPTION) { + proceed = true; + } + } else { + proceed = true; + } + + return proceed; + } + + @Override + public void actionPerformed(ActionEvent e) { + switch (e.getActionCommand()) { + case NEW: + if (saveUnsaved()) { + doc.clearFilename(); + field.clear(); + } + break; + case OPEN: + open(); + break; + case SAVE: + save(false); + break; + case SAVE_AS: + save(true); + break; + case CHECK: + check(); + break; + case SOLVE: + solve(); + break; + case QUIT: + if (saveUnsaved()) { + System.exit(0); + } + break; + case ABOUT: + JOptionPane.showMessageDialog(field, + "Sudoku - Copyright (c) 2013 Mike Becker\nwww.uap-core.de"+ + "\nPublished under the BSD License", + "Sudoku", JOptionPane.INFORMATION_MESSAGE); + break; + default: + throw new UnsupportedOperationException( + "unknown action: "+e.getActionCommand()); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/ButtonPanel.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,68 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import javax.swing.*; +import java.awt.*; + +/** + * + * @author mike + */ +public final class ButtonPanel extends JPanel { + + private JButton save, check, solve; + + public ButtonPanel(ActionHandler l) { + setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(10, 10, 10, 10); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + + c.gridx = 0; + c.gridy = 0; + save = new JButton("Speichern"); + add(save, c); + c.gridx++; + check = new JButton("Prüfen"); + add(check, c); + solve = new JButton("Lösen"); + c.gridx++; + add(solve, c); + + save.setActionCommand(ActionHandler.SAVE); + save.addActionListener(l); + check.setActionCommand(ActionHandler.CHECK); + check.addActionListener(l); + solve.setActionCommand(ActionHandler.SOLVE); + solve.addActionListener(l); + + setBackground(Color.WHITE); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/DocumentHandler.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import java.io.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author mike + */ +public class DocumentHandler { + + private String filename; + + public void load(Field field) throws IOException { + if (!isFilenameSet()) { + throw new IOException("no filename supplied"); + } + int row = 0; + try (BufferedReader in = new BufferedReader( + new InputStreamReader(new FileInputStream(filename)))) { + Pattern pat = Pattern.compile("^\\s*(?:[1-9_] ){8}[1-9_]\\s*$"); + String line; + while ((line = in.readLine()) != null) { + if (line.matches("^\\s*$")) { + continue; + } + Matcher m = pat.matcher(line); + if (m.matches()) { + String c[] = line.trim().split(" "); + if (c.length != 9) { + break; + } + for (int i = 0 ; i < 9 ; i++) { + field.setCellValue(i, row, + c[i].equals("_") ? 0 : Integer.valueOf(c[i])); + } + row++; + } else { + break; + } + } + if (row != 9) { + throw new IOException("Kein Sudoku-Feld enthalten!"); + } + } + field.setAllCellsModified(false); + } + + public void save(Field field) throws IOException { + if (!isFilenameSet()) { + throw new IOException("no filename supplied"); + } + + try (BufferedWriter out = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(filename)))) { + for (int i = 0 ; i < 9 ; i++) { + int[] row = field.getRow(i); + for (int j = 0 ; j < 9 ; j++) { + out.append(row[j] > 0 ? Character.forDigit(row[j], 10):'_'); + out.append(j == 8 ? '\n': ' '); + } + } + } + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public void clearFilename() { + filename = null; + } + + public boolean isFilenameSet() { + return filename != null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/Field.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,177 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import javax.swing.*; +import java.awt.*; +import java.awt.image.BufferedImage; + +/** + * + * @author mike + */ +public final class Field extends JPanel { + private SudokuTextField[][] cells; + + public Field() { + setBackground(Color.WHITE); + + setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(5, 5, 5, 5); + + cells = new SudokuTextField[9][9]; + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + cells[x][y] = new SudokuTextField(); + c.gridx = x; + c.gridy = y; + add(cells[x][y], c); + } + } + } + + @Override + public void paint(Graphics graphics) { + final int w = getWidth(); + final int h = getHeight(); + final int cw = w / 9; + final int ch = h / 9; + + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics2D g = img.createGraphics(); + g.setBackground(Color.WHITE); + g.clearRect(0, 0, w, h); + + g.setColor(Color.BLACK); + g.drawRect(1, 1, w-2, h-2); + g.drawRect(2, 2, w-4, h-4); + for (int x = cw ; x < w ; x += cw) { + for (int y = ch ; y < h ; y += ch) { + g.drawLine(x, 2, x, h-2); + g.drawLine(2, y, w-2, y); + if ((x / cw) % 3 == 0) { + g.drawLine(x+1, 2, x+1, h-2); + } + if ((y / ch) % 3 == 0) { + g.drawLine(2, y+1, w-2, y+1); + } + } + } + + graphics.drawImage(img, 0, 0, this); + super.paintChildren(graphics); + } + + public boolean isCellEmpty(int x, int y) { + return getCellValue(x, y) == 0; + } + + public int getCellValue(int x, int y) { + return cells[x][y].getValue(); + } + + public void setCellValue(int x, int y, int v) { + cells[x][y].setValue(v); + } + + public void clearCellValue(int x, int y) { + setCellValue(x, y, 0); + } + + public void setCellModified(int x, int y, boolean modified) { + cells[x][y].setModified(modified); + } + + public void setAllCellsModified(boolean modified) { + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + cells[x][y].setModified(modified); + } + } + } + + public boolean isAnyCellModified() { + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + if (cells[x][y].isModified()) { + return true; + } + } + } + return false; + } + + public void clear() { + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + cells[x][y].setValue(0); + } + } + } + + public int[][] getSquare(int x, int y) { + if (x < 0 || x > 2 || y < 0 || y > 2) { + throw new IllegalArgumentException("Invalid square coordinates"); + } + int[][] square = new int[3][3]; + + for (int u = 0 ; u < 3 ; u++) { + for (int v = 0 ; v < 3 ; v++) { + square[u][v] = getCellValue(3*x+u, 3*y+v); + } + } + + return square; + } + + public int[] getRow(int y) { + if (y < 0 || y > 8) { + throw new IllegalArgumentException("Invalid row number"); + } + int row[] = new int[9]; + + for (int x = 0 ; x < 9 ; x++) { + row[x] = getCellValue(x, y); + } + + return row; + } + + public int[] getColumn(int x) { + if (x < 0 || x > 8) { + throw new IllegalArgumentException("Invalid column number"); + } + int column[] = new int[9]; + + for (int y = 0 ; y < 9 ; y++) { + column[y] = getCellValue(x, y); + } + + return column; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/MainMenu.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,98 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import javax.swing.*; + +/** + * + * @author mike + */ +public class MainMenu { + + private ActionHandler handler; + private JMenuBar menuBar; + + public MainMenu(ActionHandler h) { + handler = h; + menuBar = new JMenuBar(); + menuBar.add(createMenu("Datei", 'd', + createMenuItem("Neu", 'n', "control N", ActionHandler.NEW), + createMenuItem("Öffnen", 'f', "control O", ActionHandler.OPEN), + createMenuItem("Speichern", 's', "control S", ActionHandler.SAVE), + createMenuItem("Speichern als...", 'a', ActionHandler.SAVE_AS), + createSeparator(), + createMenuItem("Prüfen", 'p', "control P", ActionHandler.CHECK), + createMenuItem("Lösen", 'l', "control L", ActionHandler.SOLVE), + createSeparator(), + createMenuItem("Beenden", 'e', ActionHandler.QUIT) + )); + menuBar.add(createMenu("Help", 'h', + createMenuItem("Über...", 'b', "F1", ActionHandler.ABOUT) + )); + } + + private JMenuItem createSeparator() { + // Return null, the createMenu method knows how to handle it + return null; + } + + private JMenu createMenu(String caption, char mnemonic, JMenuItem...items) { + JMenu menu = new JMenu(caption); + menu.setMnemonic(mnemonic); + for (JMenuItem item : items) { + if (item == null) { + menu.addSeparator(); + } else { + menu.add(item); + } + } + return menu; + } + + private JMenuItem createMenuItem(String caption, char mnemonic, + String command) { + return createMenuItem(caption, mnemonic, null, command); + } + + private JMenuItem createMenuItem(String caption, char mnemonic, + String stroke, String command) { + JMenuItem item = new JMenuItem(caption); + item.setMnemonic(mnemonic); + if (stroke != null) { + item.setAccelerator(KeyStroke.getKeyStroke(stroke)); + } + item.setActionCommand(command); + item.addActionListener(handler); + + return item; + } + + public JMenuBar getMenuBar() { + return menuBar; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/Solver.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,227 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author mike + */ +public final class Solver { + + public Solver() { + } + + private Integer fillInCandidate(Field f, List<Integer>[][] candidates, int x, int y) { + Integer c = candidates[x][y].remove(0); + f.setCellValue(x, y, c); + f.setCellModified(x, y, true); + for (int i = 0 ; i < 9 ; i++) { + candidates[x][i].remove(c); + candidates[i][y].remove(c); + } + for (int i = 0 ; i < 3 ; i++) { + for (int j = 0 ; j < 3 ; j++) { + candidates[x-x%3+i][y-y%3+j].remove(c); + } + } + return c; + } + + private void makeBackup(List<Integer>[][] candidates, List<Integer>[][] candidatesBackup) { + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + candidatesBackup[x][y] = new ArrayList<>(9); + candidatesBackup[x][y].addAll(candidates[x][y]); + } + } + } + + private void makeBackup(Field f, int[][] fieldBackup) { + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + fieldBackup[x][y] = f.getCellValue(x, y); + } + } + } + + private void restoreBackup(Field f, int[][] fieldBackup) { + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + f.setCellValue(x, y, fieldBackup[x][y]); + } + } + } + + private void restoreBackup(List<Integer>[][] candidates, List<Integer>[][] candidatesBackup) { + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + candidates[x][y].clear(); + candidates[x][y].addAll(candidatesBackup[x][y]); + } + } + } + + private boolean solve(Field f, List<Integer>[][] candidates) { + + // Make backup + List<Integer>[][] candidatesBackup = new List[9][9]; + int[][] fieldBackup = new int[9][9]; + makeBackup(candidates, candidatesBackup); + makeBackup(f, fieldBackup); + + // Fill in distinct solutions + boolean fillDistinct; + do { + fillDistinct = false; + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + if (f.isCellEmpty(x, y) && candidates[x][y].size() == 1) { + fillInCandidate(f, candidates, x, y); + fillDistinct = true; + } + } + } + } while (fillDistinct); + + // Try out remaining candidates + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + if (f.isCellEmpty(x, y)) { + while (candidates[x][y].size() > 0) { + List<Integer>[][] cb = new List[9][9]; + makeBackup(candidates, cb); + Integer c = fillInCandidate(f, candidates, x, y); + if (solve(f, candidates)) { + break; + } else { + f.clearCellValue(x, y); + restoreBackup(candidates, cb); + // Remove current candidate anyway + candidates[x][y].remove(c); + } + } + } + if (f.isCellEmpty(x, y)) { + restoreBackup(f, fieldBackup); + restoreBackup(candidates, candidatesBackup); + return false; + } + } + } + + return true; + } + + public boolean solve(Field f) { + + // Calculate initial candidates + List<Integer> candidates[][] = new List[9][9]; + for (int x = 0 ; x < 9 ; x++) { + for (int y = 0 ; y < 9 ; y++) { + candidates[x][y] = new ArrayList<>(9); + if (f.getCellValue(x, y) == 0) { + // All numbers are candidates + for (int c = 1 ; c <= 9 ; c++) { + candidates[x][y].add(c); + } + // Remove row duplicates + int[] line = f.getRow(y); + for (Integer c : line) { + candidates[x][y].remove(c); + } + // Remove column duplicates + line = f.getColumn(x); + for (Integer c : line) { + candidates[x][y].remove(c); + } + // Remove square duplicates + int[][] square = f.getSquare(x/3, y/3); + for (int[] sq : square) { + for (Integer c : sq) { + candidates[x][y].remove(c); + } + } + } + } + } + + // Backtrack + return solve(f, candidates); + } + + public boolean check(Field f) { + int line[]; + for (int i = 0 ; i < 9 ; i++) { + line = f.getRow(i); + if (!valid(line)) { + return false; + } + line = f.getColumn(i); + if (!valid(line)) { + return false; + } + } + + int square[][]; + for (int x = 0 ; x < 3 ; x++) { + for (int y = 0 ; y < 3 ; y++) { + square = f.getSquare(x, y); + if (!valid(square)) { + return false; + } + } + } + + return true; + } + + private boolean valid(int[] line) { + int numbers[]; + numbers = new int[9]; + for (int i = 0 ; i < 9 ; i++) { + int l = line[i]-1; + if (l >= 0) { + if ((++numbers[l]) > 1) { + return false; + } + } + } + + return true; + } + + private boolean valid(int[][] square) { + int[] line = new int[9]; + for (int x = 0 ; x < 3 ; x++) { + System.arraycopy(square[x], 0, line, 3*x, 3); + } + return valid(line); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/Sudoku.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import javax.swing.*; +import java.awt.*; + +/** + * + * @author mike + */ +public final class Sudoku extends JFrame { + + public Sudoku() { + super("Sudoku"); + + Field f = new Field(); + ActionHandler h = new ActionHandler(f); + setJMenuBar(new MainMenu(h).getMenuBar()); + + Container content = getContentPane(); + + content.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(20, 20, 20, 20); + c.fill = GridBagConstraints.HORIZONTAL; + + c.gridx = 0; c.gridy = 0; + content.add(f, c); + c.gridy++; + content.add(new ButtonPanel(h), c); + + pack(); + content.setBackground(Color.WHITE); + setLocationByPlatform(true); + setDefaultCloseOperation(EXIT_ON_CLOSE); + } + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + new Sudoku().setVisible(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/de/uapcore/sudoku/SudokuTextField.java Sat Jul 25 14:01:28 2020 +0200 @@ -0,0 +1,136 @@ +/* + * Copyright 2013 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package de.uapcore.sudoku; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * + * @author mike + */ +public final class SudokuTextField extends JTextField { + + private boolean modified; + + public SudokuTextField() { + setBorder(null); + setBackground(Color.WHITE); + + setFont(new Font("Dialog", Font.PLAIN, 18)); + setHorizontalAlignment(JTextField.CENTER); + + Dimension dim = new Dimension(40,40); + setPreferredSize(dim); + setMinimumSize(dim); + setMaximumSize(dim); + + addKeyListener(new KeyAdapter() { + private void handle(KeyEvent e) { + char c = e.getKeyChar(); + if (!e.isAltDown() && !e.isControlDown() && + !Character.isISOControl(c)) { + // Perform clean input check + if (getText().length() > 0 && getSelectedText() == null) { + if (c != KeyEvent.CHAR_UNDEFINED) { + e.consume(); + } + } else { + if (c < '1' || c > '9') { + e.consume(); + } else { + setModified(true); + } + } + } else { + // We can still be tricked by hotkeys, so do it the hard way + if (!getText().matches("^[1-9]$")) { + setText(""); + } + } + } + + @Override + public void keyPressed(KeyEvent e) { + handle(e); + } + + @Override + public void keyTyped(KeyEvent e) { + handle(e); + } + + @Override + public void keyReleased(KeyEvent e) { + handle(e); + } + + }); + addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + selectAll(); + } + @Override + public void focusLost(FocusEvent e) { + select(0, 0); + } + }); + } + + public int getValue() { + if (getText().length() > 0) { + return Integer.valueOf(getText()); + } else { + return 0; + } + } + + public void setValue(int v) { + if (v == 0) { + setText(""); + } else if (v < 10) { + setText(String.valueOf(v)); + } else { + throw new IllegalArgumentException( + "Sudoku numbers must be in range 0-9 (0 means 'not set')"); + } + } + + public void setModified(boolean modified) { + this.modified = modified; + setForeground(modified?Color.BLUE:Color.BLACK); + } + + public boolean isModified() { + return modified; + } +}