Package gnonograms.utils

Source Code of gnonograms.utils.GameLoader

/* GameLoader class for gnonograms-java
* Loads puzzles from file.
* Copyright (C) 2012  Jeremy Wootten
*
  This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*  Author:
*  Jeremy Wootten <jeremwootten@gmail.com>
*/
package gnonograms.utils;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.awt.Component;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.util.Scanner;
import java.util.NoSuchElementException;

import static java.lang.System.out;

import gnonograms.app.Resource;

public class GameLoader extends JFileChooser {
  //private static final long serialVersionUID = 1;
  public int rows=0;
  public int cols=0;
  public String[] rowClues;
  public String[] colClues;
  public String state="";
  public String name="";
  public String author="";
  public String date="";
  public String score="";
  public String license="";
  public boolean validGame=false;
  public boolean hasDimensions=false;
  public boolean hasRowClues=false;
  public boolean hasColumnClues=false;
  public boolean hasSolution=false;
  public boolean hasWorking=false;
  public boolean hasState=false;
  public String[] solution;
  public String[] working;
  private String[] headings;
  private String[] bodies;
  private Scanner dataStream;
  private int result, headingCount;

  public GameLoader(Component parent, String puzzleDirectoryPath) {
    super(puzzleDirectoryPath);
    this.setFileSelectionMode(FILES_ONLY);
    this.setFileFilter(new FileNameExtensionFilter("Gnonogram Puzzles","gno"));
    this.setDialogTitle("Choose a puzzle");
    result=this.showOpenDialog(parent);
  }

  public int getResult(){return this.result;}
  public String getFileName(){return getName(getSelectedFile());}

  public void openDataInputStream() throws FileNotFoundException{
    dataStream= new Scanner(new FileReader(getSelectedFile()));
  }

  public void close(){dataStream.close();}

  public void parseGameFile() throws IOException, NoSuchElementException, Exception {
    state="SOLVING";//by default, the game enters solving mode after loading puzzle
    headingCount=-1;
    String nextToken="";
    headings=new String[10];
    bodies=new String[10];
    dataStream.useDelimiter("\\]");
    while (nextToken!=null){
      try {nextToken=dataStream.next();}
      catch (Exception e){break;}
      if(nextToken.startsWith("[")){
        headingCount++;
        headings[headingCount]=nextToken.substring(1);
        dataStream.useDelimiter("\\[");
      } else {
        bodies[headingCount]=nextToken.substring(2);
        dataStream.useDelimiter("\\]");
      }
    }
    parseGnonogramHeadingsAndBodies();
    validGame=(hasDimensions && ((hasColumnClues && hasRowClues) || hasSolution));
  }

  private boolean parseGnonogramHeadingsAndBodies() throws Exception {
    int headingID;
    for (int i=0;i<=headingCount;i++){
      headingID=headingToInt(headings[i]);
      switch (headingID)  {
        case 1:
          getGnonogramDimensions(bodies[i]); break;
        case 2 :
          getGnonogramClues(bodies[i],false); break;
        case 3 :
          getGnonogramClues(bodies[i],true); break;
        case 4 :
          getGnonogramCellstateArray(bodies[i],true); break;
        case 5:
          getGnonogramCellstateArray(bodies[i],false); break;
        case 6:
          getGnonogramState(bodies[i]); break;
        case 7:
          getGameDescription(bodies[i]); break;
        case 8:
          get_game_license(bodies[i]); break;
        default :
          out.println("Unrecognised heading");
          break;
      }
    }
    return false;
  }

  //required older Java version
  private int headingToInt(String heading){
      if (heading==null||heading.length()<3) return -1;
      if (heading.length()>3) heading=heading.substring(0,3).toUpperCase();
      if (heading.compareTo("DIM")==0) return 1;
      if (heading.compareTo("ROW")==0) return 2;
      if (heading.compareTo("COL")==0) return 3;
      if (heading.compareTo("SOL")==0) return 4;
      if (heading.compareTo("WOR")==0) return 5;
      if (heading.compareTo("STA")==0) return 6;
      if (heading.compareTo("DES")==0) return 7;
      if (heading.compareTo("LIC")==0) return 8;
      return 0;
  }

  private void getGnonogramDimensions(String body) throws NumberFormatException, Exception{
    String[] s=splitString(body,"\n",2,3);
    rows=new Integer(s[0]);
    cols=new Integer(s[1]);
    if (rows<1 || cols<1 || rows>Resource.MAXIMUM_GRID_SIZE || cols> Resource.MAXIMUM_GRID_SIZE) {
      throw new Exception("Dimensions out of range:"+rows+","+cols);
    }
    else hasDimensions=true;
  }

  private void getGnonogramClues(String body, boolean isColumn) throws Exception{
    String[] s=splitString(body,"\n",isColumn?cols:rows,isColumn?cols:rows);
    String[] arr=new String[s.length];
    for (int i=0; i< s.length; i++){
      arr[i]=parseGnonogramClue(s[i],isColumn);
    }
    if (isColumn){
        colClues=arr;
        hasColumnClues=true;
    }
    else{
        rowClues=arr;
        hasRowClues=true;
    }
  }
  private String parseGnonogramClue(String line, boolean isColumn) throws NumberFormatException, Exception {
    String[] sa=splitString(line,"[\\D\\n]",1,isColumn?rows:cols); //split on non-digit or EOL
    int b, zero_count=0;
    int maxblock=isColumn?rows:cols;
    StringBuilder sb=new StringBuilder(200);
    for (int i=0; i<sa.length; i++){
      // ignore extraneous non-digits (allow one zero)
      try{b=new Integer(sa[i]);}
      catch (NumberFormatException e){continue;}
      if (b<0||b>maxblock) throw new Exception("Invalid block size in clue");
      if (b==0 && zero_count>0) continue;
      else zero_count++;
      if(i>0)sb.append(Resource.BLOCKSEPARATOR);
      sb.append(sa[i]);
    }
    return sb.toString();
  }

  private void getGnonogramCellstateArray(String body, boolean is_solution) throws Exception{
    String[] s=splitString(body,"\n",rows,110);
    if (s.length!=rows) throw new Exception("Wrong number of rows in solution or working grid");
    for (int i=0; i<s.length;i++){
      int[] arr = Utils.cellStateArrayFromString(s[i]);
      if (arr.length!=cols) throw new Exception("Too few columns in grid");
      if (is_solution){
        for (int c=0;c<cols;c++){
          if(arr[c]!=Resource.CELLSTATE_EMPTY && arr[c]!=Resource.CELLSTATE_FILLED) throw new Exception("Invalid cell state"+arr[c]);
    } } }
    if (is_solution){ solution=s; hasSolution=true;}
    else{working=s;hasWorking=true;}
  }

  private void getGnonogramState(String body)throws Exception{
    String[] s = splitString(body,"\n",1,3);
    state=s[0];
    if (state.contains("SETTING")) state="SETTING";
    else state="SOLVING";
  }

  private void getGameDescription(String body) throws Exception{
    String[] s = splitString(body,"\n",1,10);
    if (s.length>=1) this.name=convertHtml(s[0]);
    if (s.length>=2) this.author=convertHtml(s[1]);
    if (s.length>=3) this.date=s[2];
    if (s.length>=4) this.score=s[3];
  }
 
  //This is needed to cope with some characters
  private String convertHtml(String s){return s;} //TODO complete stub

  private void get_game_license(String body) throws Exception{
    String[] s = splitString(body,"\n",1,2);
      if (s[0].length()>50)license=s[0].substring(0,50);
      else license=s[0];
  }

  private String[] splitString(String body, String delimiter, int minTokens, int maxTokens) throws Exception {
    if (body==null) throw new Exception("Null string to split");
    String[] s = Utils.removeBlankLines(body.split(delimiter,maxTokens));
    if (s.length<minTokens) throw new Exception("Too few tokens");
    return s;
  }

}
TOP

Related Classes of gnonograms.utils.GameLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.