Compare commits
	
		
			34 Commits
		
	
	
		
			1.0.0
			...
			d681f20b90
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d681f20b90 | |||
| ef569e1bcb | |||
| 74ba71d52c | |||
| 
						
						
							
						
						7708654bdb
	
				 | 
					
					
						|||
| 004fe776eb | |||
| 
						
						
							
						
						c2c5ac6e68
	
				 | 
					
					
						|||
| 
						
						
							
						
						0198ba6e56
	
				 | 
					
					
						|||
| 
						 | 
					f5ca09cc67 | ||
| 
						
						
							
						
						1187bedc5b
	
				 | 
					
					
						|||
| 
						
						
							
						
						21fa946011
	
				 | 
					
					
						|||
| 
						
						
							
						
						2827d79556
	
				 | 
					
					
						|||
| 
						 | 
					367ad5921a | ||
| 
						 | 
					fd82088a08 | ||
| 
						
						
							
						
						8e836b1183
	
				 | 
					
					
						|||
| 
						
						
							
						
						44125ce13a
	
				 | 
					
					
						|||
| 
						
						
							
						
						76b44d22cf
	
				 | 
					
					
						|||
| 
						
						
							
						
						d19f9899cf
	
				 | 
					
					
						|||
| 
						 | 
					7e536cf644 | ||
| 
						 | 
					f5c63f9401 | ||
| c72efa8b44 | |||
| 07ab0b898f | |||
| ffaa310dbe | |||
| 7323fa8fb8 | |||
| 543d868bef | |||
| 223a92910e | |||
| 
						 | 
					d25cd93736 | ||
| 
						 | 
					d5fc28d743 | ||
| 
						 | 
					72f36b2fe1 | ||
| 
						 | 
					46f3cb1386 | ||
| 
						 | 
					79a1f939e6 | ||
| 
						 | 
					2592ca511f | ||
| 
						 | 
					3e5e2e01ec | ||
| 
						 | 
					21125ed895 | ||
| 
						 | 
					dddfb6f622 | 
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -41,4 +41,9 @@ bin/
 | 
				
			|||||||
### Mac OS ###
 | 
					### Mac OS ###
 | 
				
			||||||
.DS_Store
 | 
					.DS_Store
 | 
				
			||||||
.idea
 | 
					.idea
 | 
				
			||||||
lib
 | 
					lib
 | 
				
			||||||
 | 
					target
 | 
				
			||||||
 | 
					.mvn
 | 
				
			||||||
 | 
					src/main/resources/META-INF
 | 
				
			||||||
 | 
					mvnw
 | 
				
			||||||
 | 
					mvnw.cmd
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.idea/.gitignore
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,8 +0,0 @@
 | 
				
			|||||||
# Default ignored files
 | 
					 | 
				
			||||||
/shelf/
 | 
					 | 
				
			||||||
/workspace.xml
 | 
					 | 
				
			||||||
# Editor-based HTTP Client requests
 | 
					 | 
				
			||||||
/httpRequests/
 | 
					 | 
				
			||||||
# Datasource local storage ignored files
 | 
					 | 
				
			||||||
/dataSources/
 | 
					 | 
				
			||||||
/dataSources.local.xml
 | 
					 | 
				
			||||||
							
								
								
									
										15
									
								
								.idea/checkstyle-idea.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								.idea/checkstyle-idea.xml
									
									
									
										generated
									
									
									
								
							@@ -1,15 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="CheckStyle-IDEA" serialisationVersion="2">
 | 
					 | 
				
			||||||
    <checkstyleVersion>10.15.0</checkstyleVersion>
 | 
					 | 
				
			||||||
    <scanScope>JavaOnly</scanScope>
 | 
					 | 
				
			||||||
    <option name="thirdPartyClasspath" />
 | 
					 | 
				
			||||||
    <option name="activeLocationIds" />
 | 
					 | 
				
			||||||
    <option name="locations">
 | 
					 | 
				
			||||||
      <list>
 | 
					 | 
				
			||||||
        <ConfigurationLocation id="bundled-sun-checks" type="BUNDLED" scope="All" description="Sun Checks">(bundled)</ConfigurationLocation>
 | 
					 | 
				
			||||||
        <ConfigurationLocation id="bundled-google-checks" type="BUNDLED" scope="All" description="Google Checks">(bundled)</ConfigurationLocation>
 | 
					 | 
				
			||||||
      </list>
 | 
					 | 
				
			||||||
    </option>
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										16
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								.idea/gradle.xml
									
									
									
										generated
									
									
									
								
							@@ -1,16 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="GradleMigrationSettings" migrationVersion="1" />
 | 
					 | 
				
			||||||
  <component name="GradleSettings">
 | 
					 | 
				
			||||||
    <option name="linkedExternalProjectsSettings">
 | 
					 | 
				
			||||||
      <GradleProjectSettings>
 | 
					 | 
				
			||||||
        <option name="externalProjectPath" value="$PROJECT_DIR$" />
 | 
					 | 
				
			||||||
        <option name="modules">
 | 
					 | 
				
			||||||
          <set>
 | 
					 | 
				
			||||||
            <option value="$PROJECT_DIR$" />
 | 
					 | 
				
			||||||
          </set>
 | 
					 | 
				
			||||||
        </option>
 | 
					 | 
				
			||||||
      </GradleProjectSettings>
 | 
					 | 
				
			||||||
    </option>
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										204
									
								
								.idea/intellij-javadocs-4.0.1.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										204
									
								
								.idea/intellij-javadocs-4.0.1.xml
									
									
									
										generated
									
									
									
								
							@@ -1,204 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="JavaDocConfiguration">
 | 
					 | 
				
			||||||
    <GENERAL>
 | 
					 | 
				
			||||||
      <MODE>UPDATE</MODE>
 | 
					 | 
				
			||||||
      <OVERRIDDEN_METHODS>false</OVERRIDDEN_METHODS>
 | 
					 | 
				
			||||||
      <SPLITTED_CLASS_NAME>true</SPLITTED_CLASS_NAME>
 | 
					 | 
				
			||||||
      <LEVELS>
 | 
					 | 
				
			||||||
        <LEVEL>METHOD</LEVEL>
 | 
					 | 
				
			||||||
        <LEVEL>TYPE</LEVEL>
 | 
					 | 
				
			||||||
        <LEVEL>FIELD</LEVEL>
 | 
					 | 
				
			||||||
      </LEVELS>
 | 
					 | 
				
			||||||
      <VISIBILITIES>
 | 
					 | 
				
			||||||
        <VISIBILITY>DEFAULT</VISIBILITY>
 | 
					 | 
				
			||||||
        <VISIBILITY>PROTECTED</VISIBILITY>
 | 
					 | 
				
			||||||
        <VISIBILITY>PUBLIC</VISIBILITY>
 | 
					 | 
				
			||||||
      </VISIBILITIES>
 | 
					 | 
				
			||||||
    </GENERAL>
 | 
					 | 
				
			||||||
    <TEMPLATES>
 | 
					 | 
				
			||||||
      <CLASSES>
 | 
					 | 
				
			||||||
        <CLASS>
 | 
					 | 
				
			||||||
          <KEY>^.*(public|protected|private)*.+interface\s+\w+.*</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * The interface ${name}.\n
 | 
					 | 
				
			||||||
<#if element.typeParameters?has_content>        * \n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.typeParameters as typeParameter>
 | 
					 | 
				
			||||||
        * @param <${typeParameter.name}> the type parameter\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </CLASS>
 | 
					 | 
				
			||||||
        <CLASS>
 | 
					 | 
				
			||||||
          <KEY>^.*(public|protected|private)*.+enum\s+\w+.*</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * The enum ${name}.\n
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </CLASS>
 | 
					 | 
				
			||||||
        <CLASS>
 | 
					 | 
				
			||||||
          <KEY>^.*(public|protected|private)*.+class\s+\w+.*</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * The type ${name}.\n
 | 
					 | 
				
			||||||
<#if element.typeParameters?has_content>        * \n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.typeParameters as typeParameter>
 | 
					 | 
				
			||||||
        * @param <${typeParameter.name}> the type parameter\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </CLASS>
 | 
					 | 
				
			||||||
        <CLASS>
 | 
					 | 
				
			||||||
          <KEY>.+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * The type ${name}.\n
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </CLASS>
 | 
					 | 
				
			||||||
      </CLASSES>
 | 
					 | 
				
			||||||
      <CONSTRUCTORS>
 | 
					 | 
				
			||||||
        <CONSTRUCTOR>
 | 
					 | 
				
			||||||
          <KEY>.+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * Instantiates a new ${name}.\n
 | 
					 | 
				
			||||||
<#if element.parameterList.parameters?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.parameterList.parameters as parameter>
 | 
					 | 
				
			||||||
         * @param ${parameter.name} the ${paramNames[parameter.name]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
<#if element.throwsList.referenceElements?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.throwsList.referenceElements as exception>
 | 
					 | 
				
			||||||
         * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </CONSTRUCTOR>
 | 
					 | 
				
			||||||
      </CONSTRUCTORS>
 | 
					 | 
				
			||||||
      <METHODS>
 | 
					 | 
				
			||||||
        <METHOD>
 | 
					 | 
				
			||||||
          <KEY>^.*(public|protected|private)*\s*.*(\w(\s*<.+>)*)+\s+get\w+\s*\(.*\).+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * Gets ${partName}.\n
 | 
					 | 
				
			||||||
<#if element.typeParameters?has_content>         * \n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.typeParameters as typeParameter>
 | 
					 | 
				
			||||||
         * @param <${typeParameter.name}> the type parameter\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
<#if element.parameterList.parameters?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.parameterList.parameters as parameter>
 | 
					 | 
				
			||||||
         * @param ${parameter.name} the ${paramNames[parameter.name]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
<#if isNotVoid>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
         * @return the ${partName}\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#if element.throwsList.referenceElements?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.throwsList.referenceElements as exception>
 | 
					 | 
				
			||||||
         * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </METHOD>
 | 
					 | 
				
			||||||
        <METHOD>
 | 
					 | 
				
			||||||
          <KEY>^.*(public|protected|private)*\s*.*(void|\w(\s*<.+>)*)+\s+set\w+\s*\(.*\).+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * Sets ${partName}.\n
 | 
					 | 
				
			||||||
<#if element.typeParameters?has_content>         * \n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.typeParameters as typeParameter>
 | 
					 | 
				
			||||||
         * @param <${typeParameter.name}> the type parameter\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
<#if element.parameterList.parameters?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.parameterList.parameters as parameter>
 | 
					 | 
				
			||||||
         * @param ${parameter.name} the ${paramNames[parameter.name]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
<#if isNotVoid>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
         * @return the ${partName}\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#if element.throwsList.referenceElements?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.throwsList.referenceElements as exception>
 | 
					 | 
				
			||||||
         * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </METHOD>
 | 
					 | 
				
			||||||
        <METHOD>
 | 
					 | 
				
			||||||
          <KEY>^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * The entry point of application.\n
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     <#if element.parameterList.parameters?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
     * @param ${element.parameterList.parameters[0].name} the input arguments\n
 | 
					 | 
				
			||||||
<#if element.throwsList.referenceElements?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.throwsList.referenceElements as exception>
 | 
					 | 
				
			||||||
         * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </METHOD>
 | 
					 | 
				
			||||||
        <METHOD>
 | 
					 | 
				
			||||||
          <KEY>.+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * ${name}<#if isNotVoid> ${return}</#if>.\n
 | 
					 | 
				
			||||||
<#if element.typeParameters?has_content>         * \n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.typeParameters as typeParameter>
 | 
					 | 
				
			||||||
         * @param <${typeParameter.name}> the type parameter\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
<#if element.parameterList.parameters?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.parameterList.parameters as parameter>
 | 
					 | 
				
			||||||
         * @param ${parameter.name} the ${paramNames[parameter.name]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
<#if isNotVoid>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
         * @return the ${return}\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#if element.throwsList.referenceElements?has_content>
 | 
					 | 
				
			||||||
         *\n
 | 
					 | 
				
			||||||
</#if>
 | 
					 | 
				
			||||||
<#list element.throwsList.referenceElements as exception>
 | 
					 | 
				
			||||||
         * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n
 | 
					 | 
				
			||||||
</#list>
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </METHOD>
 | 
					 | 
				
			||||||
      </METHODS>
 | 
					 | 
				
			||||||
      <FIELDS>
 | 
					 | 
				
			||||||
        <FIELD>
 | 
					 | 
				
			||||||
          <KEY>^.*(public|protected|private)*.+static.*(\w\s\w)+.+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
 * The constant ${element.getName()}.\n
 | 
					 | 
				
			||||||
 */</VALUE>
 | 
					 | 
				
			||||||
        </FIELD>
 | 
					 | 
				
			||||||
        <FIELD>
 | 
					 | 
				
			||||||
          <KEY>^.*(public|protected|private)*.*(\w\s\w)+.+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
    <#if element.parent.isInterface()>
 | 
					 | 
				
			||||||
        * The constant ${element.getName()}.\n
 | 
					 | 
				
			||||||
<#else>
 | 
					 | 
				
			||||||
        * The ${name}.\n
 | 
					 | 
				
			||||||
</#if> */</VALUE>
 | 
					 | 
				
			||||||
        </FIELD>
 | 
					 | 
				
			||||||
        <FIELD>
 | 
					 | 
				
			||||||
          <KEY>.+</KEY>
 | 
					 | 
				
			||||||
          <VALUE>/**\n
 | 
					 | 
				
			||||||
    <#if element.parent.isEnum()>
 | 
					 | 
				
			||||||
        *${name} ${typeName}.\n
 | 
					 | 
				
			||||||
<#else>
 | 
					 | 
				
			||||||
        * The ${name}.\n
 | 
					 | 
				
			||||||
</#if>*/</VALUE>
 | 
					 | 
				
			||||||
        </FIELD>
 | 
					 | 
				
			||||||
      </FIELDS>
 | 
					 | 
				
			||||||
    </TEMPLATES>
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										17
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										17
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							@@ -1,17 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="ExternalStorageConfigurationManager" enabled="true" />
 | 
					 | 
				
			||||||
  <component name="FrameworkDetectionExcludesConfiguration">
 | 
					 | 
				
			||||||
    <file type="web" url="file://$PROJECT_DIR$" />
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
  <component name="MavenProjectsManager">
 | 
					 | 
				
			||||||
    <option name="originalFiles">
 | 
					 | 
				
			||||||
      <list>
 | 
					 | 
				
			||||||
        <option value="$PROJECT_DIR$/pom.xml" />
 | 
					 | 
				
			||||||
      </list>
 | 
					 | 
				
			||||||
    </option>
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
 | 
					 | 
				
			||||||
    <output url="file://$PROJECT_DIR$/out" />
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										124
									
								
								.idea/uiDesigner.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										124
									
								
								.idea/uiDesigner.xml
									
									
									
										generated
									
									
									
								
							@@ -1,124 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="Palette2">
 | 
					 | 
				
			||||||
    <group name="Swing">
 | 
					 | 
				
			||||||
      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
 | 
					 | 
				
			||||||
        <initial-values>
 | 
					 | 
				
			||||||
          <property name="text" value="Button" />
 | 
					 | 
				
			||||||
        </initial-values>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
 | 
					 | 
				
			||||||
        <initial-values>
 | 
					 | 
				
			||||||
          <property name="text" value="RadioButton" />
 | 
					 | 
				
			||||||
        </initial-values>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
 | 
					 | 
				
			||||||
        <initial-values>
 | 
					 | 
				
			||||||
          <property name="text" value="CheckBox" />
 | 
					 | 
				
			||||||
        </initial-values>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
 | 
					 | 
				
			||||||
        <initial-values>
 | 
					 | 
				
			||||||
          <property name="text" value="Label" />
 | 
					 | 
				
			||||||
        </initial-values>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="-1" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="-1" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="-1" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="50" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="50" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="50" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="50" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="50" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="150" height="50" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="200" height="200" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
 | 
					 | 
				
			||||||
          <preferred-size width="200" height="200" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
 | 
					 | 
				
			||||||
          <preferred-size width="-1" height="20" />
 | 
					 | 
				
			||||||
        </default-constraints>
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
 | 
					 | 
				
			||||||
        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
 | 
					 | 
				
			||||||
      </item>
 | 
					 | 
				
			||||||
    </group>
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
								
							@@ -1,6 +0,0 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="VcsDirectoryMappings">
 | 
					 | 
				
			||||||
    <mapping directory="" vcs="Git" />
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										34
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					# Libremines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"named this way because i didn't realise there was another libremines!"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Building
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Requirements:
 | 
				
			||||||
 | 
					- Java 21
 | 
				
			||||||
 | 
					- Maven 3.8.8 or lower
 | 
				
			||||||
 | 
					- GraalVM 21
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Instructions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create the maven wrapper at version 3.8.8. GluonFX does not work with newer versions as of 2024-07-27.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					mvn wrapper:wrapper -Dmaven=3.8.8
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Install dependencies, build and run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					./mvnw dependency:resolve gluonfx:build
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A native binary should be placed at `target/gluonfx/<your architecture>/libremines`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Alternatively, to run using the JVM, use:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					./mvnw javafx:run
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										29
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								pom.xml
									
									
									
									
									
								
							@@ -6,7 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <groupId>com.shr4pnel.minesweeper</groupId>
 | 
					    <groupId>com.shr4pnel.minesweeper</groupId>
 | 
				
			||||||
    <artifactId>libremines</artifactId>
 | 
					    <artifactId>libremines</artifactId>
 | 
				
			||||||
    <version>1.0-SNAPSHOT</version>
 | 
					    <version>1.0</version>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <properties>
 | 
					    <properties>
 | 
				
			||||||
        <maven.compiler.source>21</maven.compiler.source>
 | 
					        <maven.compiler.source>21</maven.compiler.source>
 | 
				
			||||||
@@ -17,12 +17,12 @@
 | 
				
			|||||||
        <dependency>
 | 
					        <dependency>
 | 
				
			||||||
            <groupId>org.openjfx</groupId>
 | 
					            <groupId>org.openjfx</groupId>
 | 
				
			||||||
            <artifactId>javafx-controls</artifactId>
 | 
					            <artifactId>javafx-controls</artifactId>
 | 
				
			||||||
            <version>21.0.3</version>
 | 
					            <version>21.0.4</version>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
        <dependency>
 | 
					        <dependency>
 | 
				
			||||||
            <groupId>org.openjfx</groupId>
 | 
					            <groupId>org.openjfx</groupId>
 | 
				
			||||||
            <artifactId>javafx-fxml</artifactId>
 | 
					            <artifactId>javafx-fxml</artifactId>
 | 
				
			||||||
            <version>21.0.3</version>
 | 
					            <version>21.0.4</version>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
    </dependencies>
 | 
					    </dependencies>
 | 
				
			||||||
    <build>
 | 
					    <build>
 | 
				
			||||||
@@ -35,6 +35,27 @@
 | 
				
			|||||||
                    <mainClass>libremines/com.shr4pnel.minesweeper.Main</mainClass>
 | 
					                    <mainClass>libremines/com.shr4pnel.minesweeper.Main</mainClass>
 | 
				
			||||||
                </configuration>
 | 
					                </configuration>
 | 
				
			||||||
            </plugin>
 | 
					            </plugin>
 | 
				
			||||||
 | 
					            <plugin>
 | 
				
			||||||
 | 
					                <groupId>org.apache.maven.plugins</groupId>
 | 
				
			||||||
 | 
					                <artifactId>maven-compiler-plugin</artifactId>
 | 
				
			||||||
 | 
					                <version>3.13.0</version>
 | 
				
			||||||
 | 
					            </plugin>
 | 
				
			||||||
 | 
					            <plugin>
 | 
				
			||||||
 | 
					                <groupId>com.gluonhq</groupId>
 | 
				
			||||||
 | 
					                <artifactId>gluonfx-maven-plugin</artifactId>
 | 
				
			||||||
 | 
					                <version>1.0.22</version>
 | 
				
			||||||
 | 
					                <configuration>
 | 
				
			||||||
 | 
					                    <mainClass>com.shr4pnel.minesweeper.Main</mainClass>
 | 
				
			||||||
 | 
					                    <reflectionList>
 | 
				
			||||||
 | 
					                        com.shr4pnel.minesweeper.Controller
 | 
				
			||||||
 | 
					                    </reflectionList>
 | 
				
			||||||
 | 
					                </configuration>
 | 
				
			||||||
 | 
					            </plugin>
 | 
				
			||||||
 | 
					            <plugin>
 | 
				
			||||||
 | 
					                <groupId>org.apache.maven.plugins</groupId>
 | 
				
			||||||
 | 
					                <artifactId>maven-wrapper-plugin</artifactId>
 | 
				
			||||||
 | 
					                <version>3.3.1</version>
 | 
				
			||||||
 | 
					            </plugin>
 | 
				
			||||||
        </plugins>
 | 
					        </plugins>
 | 
				
			||||||
    </build>
 | 
					    </build>
 | 
				
			||||||
</project>
 | 
					</project>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,43 +1,167 @@
 | 
				
			|||||||
package com.shr4pnel.minesweeper;
 | 
					package com.shr4pnel.minesweeper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
import java.net.URL;
 | 
					import java.net.URL;
 | 
				
			||||||
import java.util.Timer;
 | 
					import java.util.Timer;
 | 
				
			||||||
import java.util.TimerTask;
 | 
					import java.util.TimerTask;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javafx.event.ActionEvent;
 | 
				
			||||||
 | 
					import javafx.event.EventHandler;
 | 
				
			||||||
import javafx.fxml.FXML;
 | 
					import javafx.fxml.FXML;
 | 
				
			||||||
 | 
					import javafx.fxml.FXMLLoader;
 | 
				
			||||||
import javafx.scene.Node;
 | 
					import javafx.scene.Node;
 | 
				
			||||||
 | 
					import javafx.scene.Parent;
 | 
				
			||||||
 | 
					import javafx.scene.Scene;
 | 
				
			||||||
import javafx.scene.control.Button;
 | 
					import javafx.scene.control.Button;
 | 
				
			||||||
 | 
					import javafx.scene.control.MenuItem;
 | 
				
			||||||
 | 
					import javafx.scene.control.RadioMenuItem;
 | 
				
			||||||
import javafx.scene.image.Image;
 | 
					import javafx.scene.image.Image;
 | 
				
			||||||
import javafx.scene.image.ImageView;
 | 
					import javafx.scene.image.ImageView;
 | 
				
			||||||
import javafx.scene.input.MouseButton;
 | 
					import javafx.scene.input.MouseButton;
 | 
				
			||||||
import javafx.scene.input.MouseEvent;
 | 
					import javafx.scene.input.MouseEvent;
 | 
				
			||||||
import javafx.scene.layout.GridPane;
 | 
					import javafx.scene.layout.GridPane;
 | 
				
			||||||
 | 
					import javafx.stage.Stage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The JavaFX controller for minesweeper.fxml.
 | 
				
			||||||
 | 
					 * Handles all operations performed within the GUI.
 | 
				
			||||||
 | 
					 * @author shrapnelnet admin@shr4pnel.com
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
public class Controller {
 | 
					public class Controller {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The grid within the FXML holding all the tiles.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private GridPane grid;
 | 
					    private GridPane grid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Images within the FXML structure.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private ImageView smiley, time_1, time_2, time_3, bomb_2, bomb_3;
 | 
					    private ImageView smiley, time_1, time_2, time_3, bomb_2, bomb_3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Menu items
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @FXML
 | 
				
			||||||
 | 
					    private RadioMenuItem color, marks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The menu item "about".
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @FXML
 | 
				
			||||||
 | 
					    private MenuItem about;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The underlying 2D array representing where bombs are on the grid.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private Grid gridHandler;
 | 
					    private Grid gridHandler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A wrapper to make operations on the underlying grid easier.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private GridWrapper wrapper;
 | 
					    private GridWrapper wrapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Handles the grid during a game over state preventing further clicking of the grid.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private boolean gameOver = false;
 | 
					    private boolean gameOver = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A variable specifying if the game has been loaded for the first time.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private boolean isFirstLoad = true;
 | 
					    private boolean isFirstLoad = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The game timer.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    static Timer timer = new Timer();
 | 
					    static Timer timer = new Timer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The time that has elapsed since the game started.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private int time = 0;
 | 
					    private int time = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The time the game was started at.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private long startTime;
 | 
					    private long startTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The number of bombs on the grid.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private int bombCount = 99;
 | 
					    private int bombCount = 99;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A 2D array holding all tiles that have previously recursively been expanded.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private boolean[][] expandedTiles;
 | 
					    private boolean[][] expandedTiles;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A boolean that shows if the user has performed their first click on the GridPane.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private boolean isFirstClick = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets important variables on Main class initialization
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private void initialize() {
 | 
					    private void initialize() {
 | 
				
			||||||
 | 
					        setNotYetImplemented(color);
 | 
				
			||||||
 | 
					        setNotYetImplemented(marks);
 | 
				
			||||||
 | 
					        about.setOnAction(this::openAbout);
 | 
				
			||||||
        setupGrid();
 | 
					        setupGrid();
 | 
				
			||||||
        gridHandler = new Grid();
 | 
					        gridHandler = new Grid();
 | 
				
			||||||
        wrapper = gridHandler.grid;
 | 
					        wrapper = gridHandler.grid;
 | 
				
			||||||
        expandedTiles = new boolean[30][16];
 | 
					        expandedTiles = new boolean[30][16];
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Opens the about window when the radiomenuitem is clicked
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param actionEvent The node that the window opens on, on click
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void openAbout(ActionEvent actionEvent) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            Parent root = FXMLLoader.load(getClass().getResource("about.fxml"));
 | 
				
			||||||
 | 
					            Stage stage = new Stage();
 | 
				
			||||||
 | 
					            stage.setTitle("About");
 | 
				
			||||||
 | 
						    stage.setMinWidth(455);
 | 
				
			||||||
 | 
						    stage.setMinHeight(275);
 | 
				
			||||||
 | 
					            stage.setScene(new Scene(root));
 | 
				
			||||||
 | 
					            stage.show();
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            e.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Opens a window if an unimplemented menu item is clicked
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param node The node that the window opens on, on click
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void setNotYetImplemented(RadioMenuItem node) {
 | 
				
			||||||
 | 
					        node.setOnAction(new EventHandler<>() {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void handle(ActionEvent actionEvent) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    Parent root = FXMLLoader.load(getClass().getResource("unimplemented.fxml"));
 | 
				
			||||||
 | 
					                    Stage stage = new Stage();
 | 
				
			||||||
 | 
					                    stage.setTitle("Unimplemented!");
 | 
				
			||||||
 | 
							    stage.setMinHeight(420);
 | 
				
			||||||
 | 
							    stage.setMinWidth(525);
 | 
				
			||||||
 | 
					                    stage.setScene(new Scene(root));
 | 
				
			||||||
 | 
					                    stage.show();
 | 
				
			||||||
 | 
					                } catch (IOException e) {
 | 
				
			||||||
 | 
					                    e.printStackTrace();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Fills the GridPane with blank buttons
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void setupGrid() {
 | 
					    private void setupGrid() {
 | 
				
			||||||
        for (int column = 0; column < 30; ++column) {
 | 
					        for (int column = 0; column < 30; ++column) {
 | 
				
			||||||
            for (int row = 0; row < 16; ++row) {
 | 
					            for (int row = 0; row < 16; ++row) {
 | 
				
			||||||
@@ -47,17 +171,51 @@ public class Controller {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Used during initialization to fill the board
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return A blank button
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private Button createBlankButton() {
 | 
					    private Button createBlankButton() {
 | 
				
			||||||
        Image blank =
 | 
					        Image blank = new Image(String.valueOf(getClass().getResource("img/blank.png")), 16, 16, true, false);
 | 
				
			||||||
            new Image(String.valueOf(getClass().getResource("img/blank.png")), 16, 16, true, true);
 | 
					 | 
				
			||||||
        ImageView blankImage = new ImageView(blank);
 | 
					        ImageView blankImage = new ImageView(blank);
 | 
				
			||||||
        Button blankButton = new Button();
 | 
					        Button blankButton = new Button();
 | 
				
			||||||
        blankButton.setGraphic(blankImage);
 | 
					        blankButton.setGraphic(blankImage);
 | 
				
			||||||
        blankButton.setMinSize(16, 16);
 | 
					        blankButton.setMinSize(16, 16);
 | 
				
			||||||
        blankButton.setOnMouseClicked(this::buttonClicked);
 | 
					        blankButton.setOnMouseClicked(this::buttonClicked);
 | 
				
			||||||
 | 
					        blankButton.setOnMousePressed(this::mouseHeld);
 | 
				
			||||||
 | 
					        blankButton.setOnMouseReleased(this::mouseReleased);
 | 
				
			||||||
        return blankButton;
 | 
					        return blankButton;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Changes smiley face to concerned look when the mouse is held
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param mouseEvent Stub, required by EventHandler interface
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void mouseHeld(MouseEvent mouseEvent) {
 | 
				
			||||||
 | 
					        if (gameOver)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        setImage(smiley, "img/face_ooh.png");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Changes smiley face back to smiling after mouse release
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param mouseEvent Stub, required by EventHandler interface
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void mouseReleased(MouseEvent mouseEvent) {
 | 
				
			||||||
 | 
					        if (gameOver)
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        setImage(smiley, "img/face_smile.png");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Handles the main GridPane being clicked
 | 
				
			||||||
 | 
					     * Identifies the intention of the click (e.g. flag, open tile)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param e The event fired on click
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void buttonClicked(MouseEvent e) {
 | 
					    private void buttonClicked(MouseEvent e) {
 | 
				
			||||||
        if (gameOver) {
 | 
					        if (gameOver) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -78,25 +236,135 @@ public class Controller {
 | 
				
			|||||||
        if (buttonImage.getUrl().contains("flagged.png")) {
 | 
					        if (buttonImage.getUrl().contains("flagged.png")) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					//        if (buttonImage.getUrl().contains("num") && !buttonImage.getUrl().contains("num_0.png")) {
 | 
				
			||||||
 | 
					//            chord(clicked, buttonImage.getUrl());
 | 
				
			||||||
 | 
					//            return;
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
        handlePrimaryClick(clicked, column, row);
 | 
					        handlePrimaryClick(clicked, column, row);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//    private void chord(Button clicked, String clickedURL) {
 | 
				
			||||||
 | 
					//        int column = GridPane.getColumnIndex(clicked);
 | 
				
			||||||
 | 
					//        int row = GridPane.getRowIndex(clicked);
 | 
				
			||||||
 | 
					//        int urlLength = clickedURL.length();
 | 
				
			||||||
 | 
					//        char expectedAdjacentChar = clickedURL.charAt(urlLength-5);
 | 
				
			||||||
 | 
					//        int expectedAdjacent = Integer.parseInt(Character.toString(expectedAdjacentChar));
 | 
				
			||||||
 | 
					//        int actualAdjacent = wrapper.atColumn(column).atRow(row).adjacentBombCount();
 | 
				
			||||||
 | 
					//        if (expectedAdjacent != actualAdjacent) {
 | 
				
			||||||
 | 
					//            return;
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
 | 
					//        // chord logic
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * If the first tile clicked was a bomb, move that bomb to the first available column on row 0 before opening it
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param column The column of the clicked tile
 | 
				
			||||||
 | 
					     * @param row    The row of the clicked tile
 | 
				
			||||||
 | 
					     * @return An array containing the column and row the bomb was moved to
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private int[] setBombIfFirstTileIsBomb(int column, int row) {
 | 
				
			||||||
 | 
					        for (int c = 0; c < 30; ++c) {
 | 
				
			||||||
 | 
					            for (int r = 0; r < 16; ++r) {
 | 
				
			||||||
 | 
					                if (!wrapper.atColumn(c).atRow(r).isBomb()) {
 | 
				
			||||||
 | 
					                    wrapper.setBomb();
 | 
				
			||||||
 | 
					                    wrapper.updateGrid(column, row, c, r);
 | 
				
			||||||
 | 
					                    return new int[]{c, r};
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // this realistically should never happen... sorry!
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Extracts the URL of a given button
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param button A javafx.scene.control.Button object
 | 
				
			||||||
 | 
					     * @return A string representation of the image URL
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String getButtonURL(Button button) {
 | 
				
			||||||
 | 
					        ImageView graphic = (ImageView) button.getGraphic();
 | 
				
			||||||
 | 
					        Image image = graphic.getImage();
 | 
				
			||||||
 | 
					        return image.getUrl();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Iterates through the grid to find all tiles that are either blank or flagged
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return The number of tiles that were blank or flagged
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private int numberOfUnrevealedTiles() {
 | 
				
			||||||
 | 
					        int unrevealedTiles = 0;
 | 
				
			||||||
 | 
					        int column, row;
 | 
				
			||||||
 | 
					        for (column = 0; column < 30; ++column) {
 | 
				
			||||||
 | 
					            for (row = 0; row < 16; ++row) {
 | 
				
			||||||
 | 
					                Button current = (Button) getNodeByRowColumnIndex(row, column);
 | 
				
			||||||
 | 
					                assert current != null;
 | 
				
			||||||
 | 
					                String currentURL = getButtonURL(current);
 | 
				
			||||||
 | 
					                if (currentURL.contains("blank.png") || currentURL.contains("flagged.png")) {
 | 
				
			||||||
 | 
					                    unrevealedTiles++;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return unrevealedTiles;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Checks if the number of unrevealed tiles is equal to 99 (the win condition)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return A boolean representing if the game has been won
 | 
				
			||||||
 | 
					     * @see #numberOfUnrevealedTiles()
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private boolean checkWinCondition() {
 | 
				
			||||||
 | 
					        int unrevealedTiles = numberOfUnrevealedTiles();
 | 
				
			||||||
 | 
					        return unrevealedTiles == 99;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Handles a left mouse click on an unopened tile
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param clicked The button that was clicked
 | 
				
			||||||
 | 
					     * @param column  The column that it was clicked at
 | 
				
			||||||
 | 
					     * @param row     The row that it was clicked at
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void handlePrimaryClick(Button clicked, int column, int row) {
 | 
					    private void handlePrimaryClick(Button clicked, int column, int row) {
 | 
				
			||||||
        if (wrapper.atColumn(column).atRow(row).isBomb()) {
 | 
					        if (wrapper.atColumn(column).atRow(row).isBomb() && !isFirstClick) {
 | 
				
			||||||
            gameOver(clicked);
 | 
					            gameOver(clicked);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if (wrapper.isBomb() && isFirstClick) {
 | 
				
			||||||
 | 
					            int[] chosenColumnAndRow = setBombIfFirstTileIsBomb(column, row);
 | 
				
			||||||
 | 
					            // assertions are evil but i dont care
 | 
				
			||||||
 | 
					            assert chosenColumnAndRow != null;
 | 
				
			||||||
 | 
					            int columnMovedTo = chosenColumnAndRow[0];
 | 
				
			||||||
 | 
					            int rowMovedTo = chosenColumnAndRow[1];
 | 
				
			||||||
 | 
					            wrapper.atColumn(column).atRow(row).switchBomb(columnMovedTo, rowMovedTo);
 | 
				
			||||||
 | 
					            recursiveExpandTiles(column, row);
 | 
				
			||||||
 | 
					            clicked = (Button) getNodeByRowColumnIndex(row, column);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        isFirstClick = false;
 | 
				
			||||||
        int adjacentBombs = wrapper.adjacentBombCount();
 | 
					        int adjacentBombs = wrapper.adjacentBombCount();
 | 
				
			||||||
        setAdjacentCount(clicked, adjacentBombs);
 | 
					        setAdjacentCount(clicked, adjacentBombs);
 | 
				
			||||||
        if (adjacentBombs == 0) {
 | 
					        if (adjacentBombs == 0) {
 | 
				
			||||||
            recursiveExpandTiles(column, row);
 | 
					            recursiveExpandTiles(column, row);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        boolean win = checkWinCondition();
 | 
				
			||||||
 | 
					        if (win) {
 | 
				
			||||||
 | 
					            win();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * If a tile is surrounded by tiles with no adjacent bombs, open all the tiles recursively
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param column The column that was clicked
 | 
				
			||||||
 | 
					     * @param row    The row that was clicked
 | 
				
			||||||
 | 
					     * @see #expandTile(int, int)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void recursiveExpandTiles(int column, int row) {
 | 
					    private void recursiveExpandTiles(int column, int row) {
 | 
				
			||||||
        if (column < 0 || column >= 30 || row < 0 || row >= 16 ||
 | 
					        if (column < 0 || column >= 30 || row < 0 || row >= 16 ||
 | 
				
			||||||
            expandedTiles[column][row] && !wrapper.atColumn(column).atRow(row).isBomb()) {
 | 
					                expandedTiles[column][row] && !wrapper.atColumn(column).atRow(row).isBomb()) {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        expandTile(column, row);
 | 
					        expandTile(column, row);
 | 
				
			||||||
@@ -112,6 +380,12 @@ public class Controller {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Opens a tile, and adds it to an array to prevent overflow
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param column The column of the button to open
 | 
				
			||||||
 | 
					     * @param row    The row of the button to open
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void expandTile(int column, int row) {
 | 
					    private void expandTile(int column, int row) {
 | 
				
			||||||
        Node tile = getNodeByRowColumnIndex(row, column);
 | 
					        Node tile = getNodeByRowColumnIndex(row, column);
 | 
				
			||||||
        if (tile != null) {
 | 
					        if (tile != null) {
 | 
				
			||||||
@@ -127,6 +401,13 @@ public class Controller {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Iterates over the grid and returns the node when it's at the correct child
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param row    The desired row to find
 | 
				
			||||||
 | 
					     * @param column The desired column to find
 | 
				
			||||||
 | 
					     * @return The node at the specified position
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private Node getNodeByRowColumnIndex(int row, int column) {
 | 
					    private Node getNodeByRowColumnIndex(int row, int column) {
 | 
				
			||||||
        for (Node node : grid.getChildren()) {
 | 
					        for (Node node : grid.getChildren()) {
 | 
				
			||||||
            if (GridPane.getRowIndex(node) == row && GridPane.getColumnIndex(node) == column) {
 | 
					            if (GridPane.getRowIndex(node) == row && GridPane.getColumnIndex(node) == column) {
 | 
				
			||||||
@@ -136,8 +417,12 @@ public class Controller {
 | 
				
			|||||||
        return null;
 | 
					        return null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Resets important state variables on restart
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private void reinitialize() {
 | 
					    private void reinitialize() {
 | 
				
			||||||
 | 
					        gameOver = false;
 | 
				
			||||||
        bombCount = 99;
 | 
					        bombCount = 99;
 | 
				
			||||||
        updateBombCounter();
 | 
					        updateBombCounter();
 | 
				
			||||||
        resetTimer();
 | 
					        resetTimer();
 | 
				
			||||||
@@ -145,8 +430,14 @@ public class Controller {
 | 
				
			|||||||
        gridHandler = new Grid();
 | 
					        gridHandler = new Grid();
 | 
				
			||||||
        wrapper = gridHandler.grid;
 | 
					        wrapper = gridHandler.grid;
 | 
				
			||||||
        expandedTiles = new boolean[30][16];
 | 
					        expandedTiles = new boolean[30][16];
 | 
				
			||||||
 | 
					        isFirstClick = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Resets the timer to 0
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @see #reinitialize()
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void resetTimer() {
 | 
					    private void resetTimer() {
 | 
				
			||||||
        URL zeroSecondURL = getClass().getResource("img/0_seconds.png");
 | 
					        URL zeroSecondURL = getClass().getResource("img/0_seconds.png");
 | 
				
			||||||
        time_1.setImage(new Image(String.valueOf(zeroSecondURL)));
 | 
					        time_1.setImage(new Image(String.valueOf(zeroSecondURL)));
 | 
				
			||||||
@@ -157,6 +448,11 @@ public class Controller {
 | 
				
			|||||||
        timer = new Timer();
 | 
					        timer = new Timer();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // todo figure out why createBlankButton errors here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Refills the grid with new blank buttons
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void resetGrid() {
 | 
					    private void resetGrid() {
 | 
				
			||||||
        URL blank = getClass().getResource("img/blank.png");
 | 
					        URL blank = getClass().getResource("img/blank.png");
 | 
				
			||||||
        for (Node node : grid.getChildren()) {
 | 
					        for (Node node : grid.getChildren()) {
 | 
				
			||||||
@@ -165,6 +461,11 @@ public class Controller {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * When a bomb is clicked, change the smiley, set gameOver to true.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param tileClicked The node that was clicked, to set the correct image
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void gameOver(Node tileClicked) {
 | 
					    private void gameOver(Node tileClicked) {
 | 
				
			||||||
        gameOver = true;
 | 
					        gameOver = true;
 | 
				
			||||||
        timer.cancel();
 | 
					        timer.cancel();
 | 
				
			||||||
@@ -173,12 +474,45 @@ public class Controller {
 | 
				
			|||||||
        showAllBombs(GridPane.getColumnIndex(tileClicked), GridPane.getRowIndex(tileClicked));
 | 
					        showAllBombs(GridPane.getColumnIndex(tileClicked), GridPane.getRowIndex(tileClicked));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates a win state, change the smiley.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void win() {
 | 
				
			||||||
 | 
					        gameOver = true;
 | 
				
			||||||
 | 
					        timer.cancel();
 | 
				
			||||||
 | 
					        setImage(smiley, "img/face_win.png");
 | 
				
			||||||
 | 
					        flagAllRemaining();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * After a win, set every bomb tile that is unflagged to flagged.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void flagAllRemaining() {
 | 
				
			||||||
 | 
					        int column, row;
 | 
				
			||||||
 | 
					        for (column = 0; column < 30; ++column) {
 | 
				
			||||||
 | 
					            for (row = 0; row < 16; ++row) {
 | 
				
			||||||
 | 
					                Button current = (Button) getNodeByRowColumnIndex(row, column);
 | 
				
			||||||
 | 
					                assert current != null;
 | 
				
			||||||
 | 
					                String currentURL = getButtonURL(current);
 | 
				
			||||||
 | 
					                boolean tileIsBomb = wrapper.atColumn(column).atRow(row).isBomb();
 | 
				
			||||||
 | 
					                if (currentURL.contains("blank.png") && tileIsBomb) {
 | 
				
			||||||
 | 
					                    setImage(current, "img/bomb_flagged.png");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create a flag on a tile, representing a tile that the user suspects has a bomb behind it.
 | 
				
			||||||
 | 
					     * This prevents the tile being clicked on.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param tileClicked The tile that the user clicks.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void flag(Node tileClicked) {
 | 
					    private void flag(Node tileClicked) {
 | 
				
			||||||
        Button tileAsButton = (Button) tileClicked;
 | 
					        Button tileAsButton = (Button) tileClicked;
 | 
				
			||||||
        ImageView tileGraphic = (ImageView) tileAsButton.getGraphic();
 | 
					        ImageView tileGraphic = (ImageView) tileAsButton.getGraphic();
 | 
				
			||||||
        Image tileGraphicImage = tileGraphic.getImage();
 | 
					        Image tileGraphicImage = tileGraphic.getImage();
 | 
				
			||||||
        if (!tileGraphicImage.getUrl().contains("blank.png") &&
 | 
					        if (!tileGraphicImage.getUrl().contains("blank.png") && !tileGraphicImage.getUrl().contains("flagged.png")) {
 | 
				
			||||||
            !tileGraphicImage.getUrl().contains("flagged.png")) {
 | 
					 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        boolean flagged = tileGraphicImage.getUrl().contains("flagged.png");
 | 
					        boolean flagged = tileGraphicImage.getUrl().contains("flagged.png");
 | 
				
			||||||
@@ -189,22 +523,36 @@ public class Controller {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        bombCount--;
 | 
					        bombCount--;
 | 
				
			||||||
        updateBombCounter();
 | 
					        if (bombCount > 0)
 | 
				
			||||||
 | 
					            updateBombCounter();
 | 
				
			||||||
        setImage((Button) tileClicked, "img/bomb_flagged.png");
 | 
					        setImage((Button) tileClicked, "img/bomb_flagged.png");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * On flag or reinitialization, update the bomb counter to represent the amount of currently flagged tiles
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void updateBombCounter() {
 | 
					    private void updateBombCounter() {
 | 
				
			||||||
        String bombCountString = String.format("%03d", bombCount);
 | 
					        String bombCountString = String.format("%03d", bombCount);
 | 
				
			||||||
        setBombCounterImage(bomb_2, bombCountString.charAt(1));
 | 
					        setBombCounterImage(bomb_2, bombCountString.charAt(1));
 | 
				
			||||||
        setBombCounterImage(bomb_3, bombCountString.charAt(2));
 | 
					        setBombCounterImage(bomb_3, bombCountString.charAt(2));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Used to update the digits of the bomb counter.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param imageView The ImageView representing the counter digit to be changed.
 | 
				
			||||||
 | 
					     * @param digit     The digit the counter should be changed to.
 | 
				
			||||||
 | 
					     * @see #updateBombCounter()
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void setBombCounterImage(ImageView imageView, char digit) {
 | 
					    private void setBombCounterImage(ImageView imageView, char digit) {
 | 
				
			||||||
        URL imageURL = getClass().getResource("img/" + digit + "_seconds.png");
 | 
					        URL imageURL = getClass().getResource("img/" + digit + "_seconds.png");
 | 
				
			||||||
        imageView.setImage(new Image(String.valueOf(imageURL)));
 | 
					        imageView.setImage(new Image(String.valueOf(imageURL)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Starts the timer when the user clicks or flags their first tile.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void scheduleTimer() {
 | 
					    private void scheduleTimer() {
 | 
				
			||||||
        startTime = System.currentTimeMillis();
 | 
					        startTime = System.currentTimeMillis();
 | 
				
			||||||
        TimerTask task = new TimerTask() {
 | 
					        TimerTask task = new TimerTask() {
 | 
				
			||||||
@@ -220,6 +568,11 @@ public class Controller {
 | 
				
			|||||||
        timer.schedule(task, 0, 1000);
 | 
					        timer.schedule(task, 0, 1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Calculates the time since the game started, and passes it on.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @see #setTimerImage(ImageView, char)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void updateTimer() {
 | 
					    private void updateTimer() {
 | 
				
			||||||
        long elapsedTimeMillis = System.currentTimeMillis() - startTime;
 | 
					        long elapsedTimeMillis = System.currentTimeMillis() - startTime;
 | 
				
			||||||
        time = (int) (elapsedTimeMillis / 1000);
 | 
					        time = (int) (elapsedTimeMillis / 1000);
 | 
				
			||||||
@@ -229,47 +582,89 @@ public class Controller {
 | 
				
			|||||||
        setTimerImage(time_3, timeString.charAt(2));
 | 
					        setTimerImage(time_3, timeString.charAt(2));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Updates the timer digits individually based on updateTimer()
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param imageView The ImageView to be updated
 | 
				
			||||||
 | 
					     * @param digit     The digit to update the ImageView with
 | 
				
			||||||
 | 
					     * @see #updateTimer()
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void setTimerImage(ImageView imageView, char digit) {
 | 
					    private void setTimerImage(ImageView imageView, char digit) {
 | 
				
			||||||
        URL imageURL = getClass().getResource("img/" + digit + "_seconds.png");
 | 
					        URL imageURL = getClass().getResource("img/" + digit + "_seconds.png");
 | 
				
			||||||
        imageView.setImage(new Image(String.valueOf(imageURL)));
 | 
					        imageView.setImage(new Image(String.valueOf(imageURL)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * On game over, show every bomb that was left on the grid, as well as every incorrectly flagged bomb.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param clickedColumn The column that caused the game over.
 | 
				
			||||||
 | 
					     * @param clickedRow    The row that caused the game over.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void showAllBombs(int clickedColumn, int clickedRow) {
 | 
					    private void showAllBombs(int clickedColumn, int clickedRow) {
 | 
				
			||||||
        for (Node node : grid.getChildren()) {
 | 
					        for (Node node : grid.getChildren()) {
 | 
				
			||||||
 | 
					            Button b = (Button) node;
 | 
				
			||||||
 | 
					            String buttonURL = ((ImageView) b.getGraphic()).getImage().getUrl();
 | 
				
			||||||
            int column = GridPane.getColumnIndex(node);
 | 
					            int column = GridPane.getColumnIndex(node);
 | 
				
			||||||
            int row = GridPane.getRowIndex(node);
 | 
					            int row = GridPane.getRowIndex(node);
 | 
				
			||||||
            if (!(column == clickedColumn && row == clickedRow) &&
 | 
					            // if the tile isn't the one that was clicked AND the tile is a bomb
 | 
				
			||||||
                wrapper.atColumn(column).atRow(row).isBomb()) {
 | 
					            if (!(column == clickedColumn && row == clickedRow) && wrapper.atColumn(column).atRow(row).isBomb()) {
 | 
				
			||||||
                setImage((Button) node, "img/bomb_revealed.png");
 | 
					                setImage((Button) node, "img/bomb_revealed.png");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (buttonURL.contains("flagged.png") && !wrapper.atColumn(column).atRow(row).isBomb()) {
 | 
				
			||||||
 | 
					                setImage(b, "img/bomb_wrong.png");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets a button's graphic.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param button    The button to change.
 | 
				
			||||||
 | 
					     * @param imagePath A path to an image to change the graphic to.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void setImage(Button button, String imagePath) {
 | 
					    private void setImage(Button button, String imagePath) {
 | 
				
			||||||
        URL imageURL = getClass().getResource(imagePath);
 | 
					        URL imageURL = getClass().getResource(imagePath);
 | 
				
			||||||
        button.setGraphic(new ImageView(new Image(String.valueOf(imageURL), 16, 16, true, false)));
 | 
					        button.setGraphic(new ImageView(new Image(String.valueOf(imageURL), 16, 16, true, false)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Replaces an ImageView's graphic with another.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param imageView The ImageView to change.
 | 
				
			||||||
 | 
					     * @param imagePath A path to an image to change the graphic to.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void setImage(ImageView imageView, String imagePath) {
 | 
					    private void setImage(ImageView imageView, String imagePath) {
 | 
				
			||||||
        URL imageURL = getClass().getResource(imagePath);
 | 
					        URL imageURL = getClass().getResource(imagePath);
 | 
				
			||||||
        imageView.setImage(new Image(String.valueOf(imageURL)));
 | 
					        imageView.setImage(new Image(String.valueOf(imageURL)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Replaces the smiley with a pressed down variant when it is clicked.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private void smileyPressed() {
 | 
					    private void smileyPressed() {
 | 
				
			||||||
        setImage(smiley, "img/face_smile_pressed.png");
 | 
					        setImage(smiley, "img/face_smile_pressed.png");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Releases the smiley from being pressed down, starts reinitialization.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @see #reinitialize()
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    private void smileyReleased() {
 | 
					    private void smileyReleased() {
 | 
				
			||||||
        gameOver = false;
 | 
					 | 
				
			||||||
        setImage(smiley, "img/face_smile.png");
 | 
					        setImage(smiley, "img/face_smile.png");
 | 
				
			||||||
        reinitialize();
 | 
					        reinitialize();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets the graphic of a tile to indicate how many bombs are adjacent to it.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param tileClicked   The tile to update.
 | 
				
			||||||
 | 
					     * @param adjacentBombs The number of bombs adjacent to the tile.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void setAdjacentCount(Node tileClicked, int adjacentBombs) {
 | 
					    private void setAdjacentCount(Node tileClicked, int adjacentBombs) {
 | 
				
			||||||
        Button button = (Button) tileClicked;
 | 
					        Button button = (Button) tileClicked;
 | 
				
			||||||
        URL imageURL = getClass().getResource("img/num_" + adjacentBombs + ".png");
 | 
					        setImage(button, "img/num_" + adjacentBombs + ".png");
 | 
				
			||||||
        button.setGraphic(new ImageView(new Image(String.valueOf(imageURL), 16, 16, true, false)));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,18 +1,31 @@
 | 
				
			|||||||
package com.shr4pnel.minesweeper;
 | 
					package com.shr4pnel.minesweeper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.concurrent.ThreadLocalRandom;
 | 
					import java.util.concurrent.ThreadLocalRandom;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Used to fill the GridWrapper with bombs. Planned to merge into GridWrapper.
 | 
				
			||||||
 | 
					 * @since 1.0.0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
public class Grid {
 | 
					public class Grid {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * An instance of GridWrapper used to check generation of bombs.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    final GridWrapper grid = new GridWrapper();
 | 
					    final GridWrapper grid = new GridWrapper();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Generates the bomb-grid structure on instantiation
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @see #generateBombs(int)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public Grid() {
 | 
					    public Grid() {
 | 
				
			||||||
        // todo fix beginner mode and intermediate!
 | 
					 | 
				
			||||||
        // sorry :3
 | 
					 | 
				
			||||||
        // 99 bombs in expert:
 | 
					 | 
				
			||||||
        generateBombs(99);
 | 
					        generateBombs(99);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Generates a boolean 2D array by randomly selecting a column and row, and setting it to true to represent a bomb.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param bombMax The number of bombs to generate.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private void generateBombs(int bombMax) {
 | 
					    private void generateBombs(int bombMax) {
 | 
				
			||||||
        int i;
 | 
					        int i;
 | 
				
			||||||
        boolean success;
 | 
					        boolean success;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,37 +1,97 @@
 | 
				
			|||||||
package com.shr4pnel.minesweeper;
 | 
					package com.shr4pnel.minesweeper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Simplifies operations on the bomb array. Preventing direct access leads to cleaner code.
 | 
				
			||||||
 | 
					 * @since 1.0.0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
public class GridWrapper {
 | 
					public class GridWrapper {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Number of columns.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private static final int COLUMNS = 30;
 | 
					    private static final int COLUMNS = 30;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Number of rows.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private static final int ROWS = 16;
 | 
					    private static final int ROWS = 16;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A low level 2D array representing the position of bombs.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    final boolean[][] grid = new boolean[COLUMNS][ROWS];
 | 
					    final boolean[][] grid = new boolean[COLUMNS][ROWS];
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Points at a column in grid.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private int currentColumn;
 | 
					    private int currentColumn;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Points at a row in grid.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private int currentRow;
 | 
					    private int currentRow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * On instantiation, initialize currentColumn and currentRow to 0
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public GridWrapper() {
 | 
					    public GridWrapper() {
 | 
				
			||||||
        this.currentColumn = 0;
 | 
					        this.currentColumn = 0;
 | 
				
			||||||
        this.currentRow = 0;
 | 
					        this.currentRow = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets currentColumn to a specified column.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param column The column specified.
 | 
				
			||||||
 | 
					     * @return Current GridWrapper instance.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public GridWrapper atColumn(int column) {
 | 
					    public GridWrapper atColumn(int column) {
 | 
				
			||||||
        this.currentColumn = column;
 | 
					        this.currentColumn = column;
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets currentColumn to a specified column.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param row The row specified.
 | 
				
			||||||
 | 
					     * @return Current GridWrapper instance.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public GridWrapper atRow(int row) {
 | 
					    public GridWrapper atRow(int row) {
 | 
				
			||||||
        this.currentRow = row;
 | 
					        this.currentRow = row;
 | 
				
			||||||
        return this;
 | 
					        return this;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets a bomb in grid at the position specified by currentColumn and currentRow.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public void setBomb() {
 | 
					    public void setBomb() {
 | 
				
			||||||
        if (isValid(currentColumn, currentRow)) {
 | 
					        if (isValid(currentColumn, currentRow)) {
 | 
				
			||||||
            grid[currentColumn][currentRow] = true;
 | 
					            grid[currentColumn][currentRow] = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Switches a bomb from one position to another.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param destinationColumn The new column for the bomb.
 | 
				
			||||||
 | 
					     * @param destinationRow    The new row for the bomb.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public void switchBomb(int destinationColumn, int destinationRow) {
 | 
				
			||||||
 | 
					        if (isValid(currentColumn, currentRow) && isValid(destinationColumn, destinationRow)) {
 | 
				
			||||||
 | 
					            grid[destinationColumn][destinationRow] = true;
 | 
				
			||||||
 | 
					            grid[currentColumn][currentRow] = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Checks if there is a bomb at the specified position.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return The value in grid specified by currentColumn and currentRow.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public boolean isBomb() {
 | 
					    public boolean isBomb() {
 | 
				
			||||||
        return isValid(currentColumn, currentRow) && grid[currentColumn][currentRow];
 | 
					        return isValid(currentColumn, currentRow) && grid[currentColumn][currentRow];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Checks for bombs in every direction from the currentColumn and currentRow.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return The number of adjacent bombs.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public int adjacentBombCount() {
 | 
					    public int adjacentBombCount() {
 | 
				
			||||||
        int count = 0;
 | 
					        int count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,10 +122,40 @@ public class GridWrapper {
 | 
				
			|||||||
        return count;
 | 
					        return count;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // todo use switchBomb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Swaps one bomb with another.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param oldColumn The original column of the bomb.
 | 
				
			||||||
 | 
					     * @param oldRow    The original row of the bomb.
 | 
				
			||||||
 | 
					     * @param newColumn The destination column of the bomb.
 | 
				
			||||||
 | 
					     * @param newRow    The destination row of the bomb.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public void updateGrid(int oldColumn, int oldRow, int newColumn, int newRow) {
 | 
				
			||||||
 | 
					        grid[oldColumn][oldRow] = false;
 | 
				
			||||||
 | 
					        grid[newColumn][newRow] = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Checks if a bomb is at a specified position.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param column The column specified.
 | 
				
			||||||
 | 
					     * @param row    The row specified.
 | 
				
			||||||
 | 
					     * @return A boolean AND representing a valid position and a bomb being present.
 | 
				
			||||||
 | 
					     * @see #isValid(int, int)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private boolean isBombAt(int column, int row) {
 | 
					    private boolean isBombAt(int column, int row) {
 | 
				
			||||||
        return isValid(column, row) && grid[column][row];
 | 
					        return isValid(column, row) && grid[column][row];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Checks if a given column and row is in bounds.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param column The column provided.
 | 
				
			||||||
 | 
					     * @param row    The row provided.
 | 
				
			||||||
 | 
					     * @return A boolean representing the tile being in bounds.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private boolean isValid(int column, int row) {
 | 
					    private boolean isValid(int column, int row) {
 | 
				
			||||||
        return column >= 0 && column < COLUMNS && row >= 0 && row < ROWS;
 | 
					        return column >= 0 && column < COLUMNS && row >= 0 && row < ROWS;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package com.shr4pnel.minesweeper;
 | 
					package com.shr4pnel.minesweeper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.io.IOException;
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javafx.application.Application;
 | 
					import javafx.application.Application;
 | 
				
			||||||
import javafx.fxml.FXML;
 | 
					import javafx.fxml.FXML;
 | 
				
			||||||
import javafx.fxml.FXMLLoader;
 | 
					import javafx.fxml.FXMLLoader;
 | 
				
			||||||
@@ -8,7 +9,17 @@ import javafx.scene.Scene;
 | 
				
			|||||||
import javafx.scene.image.Image;
 | 
					import javafx.scene.image.Image;
 | 
				
			||||||
import javafx.stage.Stage;
 | 
					import javafx.stage.Stage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The application opening point, used to bootstrap JavaFX and open to the GUI.
 | 
				
			||||||
 | 
					 * @since 1.0.0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
public class Main extends Application {
 | 
					public class Main extends Application {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * JavaFX opening method. Creates the stage and bootstraps the application.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param stage The stage object passed in by JavaFX.
 | 
				
			||||||
 | 
					     * @throws IOException If the FXML template or app icon are not found in resources.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void start(Stage stage) throws IOException {
 | 
					    public void start(Stage stage) throws IOException {
 | 
				
			||||||
        Image icon = new Image(String.valueOf(getClass().getResource("winmine.png")));
 | 
					        Image icon = new Image(String.valueOf(getClass().getResource("winmine.png")));
 | 
				
			||||||
@@ -21,10 +32,19 @@ public class Main extends Application {
 | 
				
			|||||||
        stage.show();
 | 
					        stage.show();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Application opening method. Calls the JavaFX start method.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param args Optional commandline parameters, unimplemented.
 | 
				
			||||||
 | 
					     * @see #start(Stage)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public static void main(String[] args) {
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
        launch();
 | 
					        launch();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Cancels the timer on application stop.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    @FXML
 | 
					    @FXML
 | 
				
			||||||
    public void stop() {
 | 
					    public void stop() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,8 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * The main module for the program. Required to launch to JavaFX as well as bundle into a native binary.
 | 
				
			||||||
 | 
					 * @author shrapnelnet admin@shr4pnel.com
 | 
				
			||||||
 | 
					 * @since 1.0.0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
module libremines {
 | 
					module libremines {
 | 
				
			||||||
    requires javafx.controls;
 | 
					    requires javafx.controls;
 | 
				
			||||||
    requires javafx.fxml;
 | 
					    requires javafx.fxml;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								src/main/resources/com/shr4pnel/minesweeper/about.fxml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/resources/com/shr4pnel/minesweeper/about.fxml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<?import javafx.scene.image.*?>
 | 
				
			||||||
 | 
					<?import javafx.scene.layout.*?>
 | 
				
			||||||
 | 
					<?import javafx.scene.text.*?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<AnchorPane prefHeight="225.0" prefWidth="454.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1">
 | 
				
			||||||
 | 
					    <children>
 | 
				
			||||||
 | 
					        <ImageView fitHeight="150.0" fitWidth="200.0" layoutX="146.0" layoutY="31.0" pickOnBounds="true" preserveRatio="true">
 | 
				
			||||||
 | 
					            <image>
 | 
				
			||||||
 | 
					                <Image url="@winmine.png" />
 | 
				
			||||||
 | 
					            </image>
 | 
				
			||||||
 | 
					        </ImageView>
 | 
				
			||||||
 | 
					        <Text layoutY="42.0" strokeType="OUTSIDE" strokeWidth="0.0" text="made with love - shrapnelnet" textAlignment="CENTER" wrappingWidth="454.0">
 | 
				
			||||||
 | 
					            <font>
 | 
				
			||||||
 | 
					                <Font name="Source Code Pro" size="13.0" />
 | 
				
			||||||
 | 
					            </font>
 | 
				
			||||||
 | 
					        </Text>
 | 
				
			||||||
 | 
					        <Text layoutY="183.0" strokeType="OUTSIDE" strokeWidth="0.0" text="greeTz: b4rkod, ping, cockpit, vulon, i330 n' porcupine" textAlignment="CENTER" wrappingWidth="454.0">
 | 
				
			||||||
 | 
					            <font>
 | 
				
			||||||
 | 
					                <Font name="Source Code Pro" size="13.0" />
 | 
				
			||||||
 | 
					            </font>
 | 
				
			||||||
 | 
					        </Text>
 | 
				
			||||||
 | 
					        <Text layoutY="200.0" strokeType="OUTSIDE" strokeWidth="0.0" text="next time make your own!" textAlignment="CENTER" wrappingWidth="454.0">
 | 
				
			||||||
 | 
					            <font>
 | 
				
			||||||
 | 
					                <Font name="Source Code Pro" size="13.0" />
 | 
				
			||||||
 | 
					            </font>
 | 
				
			||||||
 | 
					        </Text>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </children>
 | 
				
			||||||
 | 
					</AnchorPane>
 | 
				
			||||||
							
								
								
									
										4
									
								
								src/main/resources/com/shr4pnel/minesweeper/fix-glow.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/main/resources/com/shr4pnel/minesweeper/fix-glow.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					* {
 | 
				
			||||||
 | 
					    -fx-focus-color: transparent;
 | 
				
			||||||
 | 
					    -fx-faint-focus-color: transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/com/shr4pnel/minesweeper/img/204.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/main/resources/com/shr4pnel/minesweeper/img/204.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 22 KiB  | 
@@ -6,9 +6,9 @@
 | 
				
			|||||||
<?import javafx.scene.layout.*?>
 | 
					<?import javafx.scene.layout.*?>
 | 
				
			||||||
<?import javafx.scene.shape.*?>
 | 
					<?import javafx.scene.shape.*?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="500.0" style="-fx-border-color: black; -fx-border-width: 1px;" xmlns="http://javafx.com/javafx/11.0.14-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.shr4pnel.minesweeper.Controller">
 | 
					<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="350.0" prefWidth="500.0" style="-fx-border-color: black; -fx-border-width: 1px;" stylesheets="@fix-glow.css" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.shr4pnel.minesweeper.Controller">
 | 
				
			||||||
    <children>
 | 
					    <children>
 | 
				
			||||||
        <MenuBar style="-fx-background-color: white;">
 | 
					        <MenuBar prefWidth="498.0" style="-fx-background-color: white;">
 | 
				
			||||||
            <menus>
 | 
					            <menus>
 | 
				
			||||||
                <Menu mnemonicParsing="false" text="Game">
 | 
					                <Menu mnemonicParsing="false" text="Game">
 | 
				
			||||||
                    <items>
 | 
					                    <items>
 | 
				
			||||||
@@ -23,11 +23,11 @@
 | 
				
			|||||||
                                <ToggleGroup fx:id="difficulty" />
 | 
					                                <ToggleGroup fx:id="difficulty" />
 | 
				
			||||||
                            </toggleGroup>
 | 
					                            </toggleGroup>
 | 
				
			||||||
                        </RadioMenuItem>
 | 
					                        </RadioMenuItem>
 | 
				
			||||||
                        <RadioMenuItem mnemonicParsing="false" text="Internmediate" toggleGroup="$difficulty" />
 | 
					                        <RadioMenuItem mnemonicParsing="false" text="Intermediate" toggleGroup="$difficulty" />
 | 
				
			||||||
                        <RadioMenuItem mnemonicParsing="false" selected="true" text="Expert" toggleGroup="$difficulty" />
 | 
					                        <RadioMenuItem mnemonicParsing="false" selected="true" text="Expert" toggleGroup="$difficulty" />
 | 
				
			||||||
                        <SeparatorMenuItem mnemonicParsing="false" />
 | 
					                        <SeparatorMenuItem mnemonicParsing="false" />
 | 
				
			||||||
                        <RadioMenuItem mnemonicParsing="false" selected="true" text="Marks (?)" />
 | 
					                        <RadioMenuItem fx:id="marks" mnemonicParsing="false" selected="true" text="Marks (?)" />
 | 
				
			||||||
                        <RadioMenuItem mnemonicParsing="false" selected="true" text="Color" />
 | 
					                        <RadioMenuItem fx:id="color" mnemonicParsing="false" selected="true" text="Color" />
 | 
				
			||||||
                        <SeparatorMenuItem mnemonicParsing="false" />
 | 
					                        <SeparatorMenuItem mnemonicParsing="false" />
 | 
				
			||||||
                        <MenuItem mnemonicParsing="false" style="-fx-padding-right: 15; -fx-border-insets: 10px; -fx-background-insets: 10px;" text="Best Times..." />
 | 
					                        <MenuItem mnemonicParsing="false" style="-fx-padding-right: 15; -fx-border-insets: 10px; -fx-background-insets: 10px;" text="Best Times..." />
 | 
				
			||||||
                        <SeparatorMenuItem mnemonicParsing="false" />
 | 
					                        <SeparatorMenuItem mnemonicParsing="false" />
 | 
				
			||||||
@@ -36,7 +36,7 @@
 | 
				
			|||||||
                </Menu>
 | 
					                </Menu>
 | 
				
			||||||
                <Menu mnemonicParsing="false" text="Help">
 | 
					                <Menu mnemonicParsing="false" text="Help">
 | 
				
			||||||
                    <items>
 | 
					                    <items>
 | 
				
			||||||
                        <MenuItem mnemonicParsing="false" text="About Minesweeper" />
 | 
					                        <MenuItem fx:id="about" mnemonicParsing="false" text="About Minesweeper" />
 | 
				
			||||||
                    </items>
 | 
					                    </items>
 | 
				
			||||||
                </Menu>
 | 
					                </Menu>
 | 
				
			||||||
            </menus>
 | 
					            </menus>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<?import javafx.scene.image.*?>
 | 
				
			||||||
 | 
					<?import javafx.scene.layout.*?>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="420.0" prefWidth="525.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1">
 | 
				
			||||||
 | 
					   <children>
 | 
				
			||||||
 | 
					      <ImageView fitHeight="420.0" fitWidth="531.0" pickOnBounds="true" preserveRatio="true">
 | 
				
			||||||
 | 
					         <image>
 | 
				
			||||||
 | 
					            <Image url="@img/204.jpg" />
 | 
				
			||||||
 | 
					         </image>
 | 
				
			||||||
 | 
					      </ImageView>
 | 
				
			||||||
 | 
					   </children>
 | 
				
			||||||
 | 
					</Pane>
 | 
				
			||||||
		Reference in New Issue
	
	Block a user