A memo when fumbling and developing using JavaFX

Preface

It's just a memo, so it's a matter of trial and error and dirty things. Even so, if I think of "mandokuse", I look for a way that seems easier to do.

That's why basically it's not about what is written here is correct or incorrect, and the order is not in order. This is my trial order. You shouldn't try to get anything from here because it's messed up. If you're still looking for something, it's probably better to look for it in the table of contents. (Can I search within the page?)

I don't look at it very much because it's a break from the work, but when I get advice or something, I'm happy while crying.

Since the content of the article is stray, it may be a separate article for each item when it is over (undecided)

What you are trying to make

Things that can be solved by Sudoku. At school free assignment. Place squares and various buttons on the screen drawn by FX. It is operated by manual input and button operation by the user.

I'm a newcomer, so I don't display an error window. Let sout or serr vomit.

Environment and others

Java (8) ... has been learned to some extent (inexperienced) Try using JavaFX (8), FXML. As an IDE, instructor Onunume's intelliJ IDEA (ver.3.2) It seems that the UI has changed a little with the recent addition of Appde. The refactoring function was too strong, and it was itchy in various places when I used eclipse.

Walls, coping, research

Stumble on unfamiliar JavaFX.

About some simple correspondence

--The fx: id specified in FXML gets angry if you do not specify @ FXML immediately before in Controller. If you don't attach it in delimiter units, you will get angry. --If you pass the array y to the array x like x = y (tentative name), it will be passed by reference value (described later). x and y are names that refer to the same object. --If you want to treat it as another new object, use the clone method and set x = y.clone (). --This problem compares the reference value of an object with connecting another object containing the same string of type String with the conditional operator == (that is, str == new String (str)). Reminds me that false is returned for this. However, the String type itself seems to have some special specifications, so should we handle it with care? --In Sudoku, in addition to rows and columns, 3x3 subRegions also prohibit duplication. I wrote a formula to follow this 3x3 group in order.

for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) {
  int idev3= i/3 , jdev3= j/3 ;

  int x= idev3 * 3 + jdev3 ,
      y= i % 3 * 3 + j % 3 ;

  subRegion[x][y] = cell[i][j]
//Since the inverse function becomes a similar expression (I forgot the name),[i][j]When[x][y]Even if it is reversed, it serves the purpose.
//  subRegion[i][j] = cell[x][y];
}

--About length of the two-dimensional array x = new Object [i] [j]. --x.length is ʻi --x [0] .length is j. However, if ʻi == 0, it throws ʻArrayIndexOutOfBoundsException.

I want to display 9x9 input in JavaFX

This is indispensable because it is to solve Sudoku.

When I was in junior high school, I was studying experientially at school with the tentative name Decimal BASIC, and when I tried to make Sudoku by playing, I entered 9 numbers (0 blanks) and 9 lines as standard input (? ), But I died because of the troublesome manual input. Since it is an array, there is no .contains (object). I used to say "Alcanar" in for.

I'm planning to input only here and solve it in another class, so in the coding around FX, an array is fine.

However, in the first place, it became ayashi from that side, such as whether an array can be used for FX input. (Especially when using FXML. Speaking of complicated data exchange ...)

Extract the array data inside FXML as an array

create array of Label using FXML in JavaFX - StackOverflaw

If you prepare an ArrayList with fx: id =" myfxid " in FXML, insert the element data into it, and call it like @FXML ArrayList myfxid; on the Controller side, the contents will also be included. It can be read.

But if you want to create 81 TextFields, you have to prepare 81 by hand (copy and fine modification) on FXML or duplicate on sceneBuilder. It's annoying.

Embed TextField in TableView

(YouTube) JavaFX TableView | Adding TextField in tableView Cell

Working with Oracle Official JavaFX UI Components TextView is embedded in the case of. It seems that it is necessary to put a setter or getter in a class that makes a row for each TableColumn name, so I can not think of a simplified way to write it, so the path

Added from Controller etc. to the existing FXML layout (primaryStage?)

It was hard to find this way. Or rather, it came out when I searched for another matter.

At first, I thought "I should write it in start as before", so Parent root = FXMLLoader.load (getClass (). GetResource ("Example.fxml ")); After that, I tried to play with it from root.getChildren (). (I didn't know if I could play with it like this)

I was told by the IDE that it was no good. Isn't the name "root.getChildrenUnmodifiable ()" that you can't change? Like that. From the Oracle Sensei API Reference, it's just read-only. It returns data.

However, there was salvation.

I saw the @Override initialize (/ * abbreviation * /) method in the second half of the video "Embed TextField in TableView" one level above. Because.

If you inherit public class Controller implements Initializable {}, you can inherit the ʻinitialize` method and initialize the FX display in it (?).

It's a little old About the format of JavaFX Controller in Tatsuno Otoshigo's Diary There is also a description in.

In the above video, the description process of fx that was written in ʻApplicationClass.start` in the official case was written in the initialize method.

Is it possible to rewrite the contents by manipulating the thing with fx: id set in FXML with Controller?

About execution order

When this happens, it is the order of execution that is of concern. What is called an "initializer" may follow a strange execution order, so check it with the scope. So I prepared ↓

TestApp.java


/*import festival*/
public class TestApp extends Application {
  public static void main(String[] args) { launch(args); }

  @Override
  public void start(Stage primaryStage) throws IOException {
    System.out.println("set fxml 2 Parent root");
    Parent root = FXMLLoader.load(getClass().getResource("Test.fxml"));

    System.out.println("set root 2 scene");
    Scene scene =new Scene(root);

    System.out.println("set scene 2 primaryStage");
    primaryStage.setScene(scene);

    System.out.println("primaryStage.show");
    primaryStage.show();
  }
}

Test.fxml


<?xml version="1.0" encoding="UTF-8"?>
<!--?import storm-->
<AnchorPane prefHeight="100.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/8.0.172-ea" 
xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
   <children> <!--Children's storm--> </children>
</AnchorPane>

Controller.java


/*import full*/
public class Controller implements Initializable {
  @Override
  public void initialize(URL location, ResourceBundle resources) {
    System.out.println("initializerCalled");
  }
}

I don't know if it's okay to throw ʻIOE`, but it looks like this. The standard output of the execution result is ↓

set fxml 2 Parent root
initializerCalled
set root 2 scene
set scene 2 primaryStage
primaryStage.show

Process finished with exit code 0

In short Start from Test.main and start from launch (understanding around here is ambiguous) By the way, read fxml by saying FXMLLoader.load (fxml file), and read "(load)". When fxml is read, the Controler.java specified by fx: controller is read and "(fxml)" ʻThe initialize method` is executed" (/ fxml) "(/ load) And that's it! (What does it mean)

It is not possible to write directly to the Parent root taken out by FXMLLoader.load written in the upper part (the beginning of the existing FXML ~~ section), but it is initialized from the Controller specified in the fxml file when it is loaded. If you can do that, it looks like this. I've realized what I want to do, so I'm sorry.

I wonder if the specification of @FXML is to" give me information if there is something with such an ID "to fxml that is trying to read itself (Controller) when it is read.

I wrote the php code with echo in the for statement of php and made it like an array (\ $ _ val.1, \ $ _ val2 ... "\ $ _ val". \ $ _ I), but this one I like it because it can be described more intuitively.

Finally (9x9 input field)

Prepare a GridPane with ID as a container on the FXML side, In Controller.initialize, I will define the TextField (array) that fits inside.

As an idea, it was raised as a question to teratail [JavaFX] How to arrange images in a grid [GUI] The questioner's code was very helpful. (As an aside, the answer I received may be that the way of thinking about objects is awkward. It's a different story if you can do something like imageView.clone (), but there is no such method ... Well, it's a pretty old article, and the FXML description and internal specifications may be different. )

Code below

In Controller class



//Prepared in advance with FXML. The XY coordinates to be placed and the Grid Line Visible are specified on the FXML side.
  @FXML GridPane inputGrid;

//I'd like to make a thick ruled line later, so make it easy to change.
  Double cellSize=30.0;

  @Override
  public void initialize(URL location, ResourceBundle resources) {

  //Number of matrices in the table
    int hnum = 9;    int vnum = 9;

  //The part that requires input
    TextField[][] cellValues = new TextField[vnum][hnum];
        //Each will be given later in new, but memory (pointer)(Ah)) If you don't give it, you will vomit.

    for (int i = 0; i < hnum; i++) {
      for (int j = 0; j < vnum; j++) {

        cellValues[i][j] = new TextField("");
        //If you do not call the constructor and pass the instance object, it will spit out after all

    //PrefW on the TextView side/If you specify H, GridPane will resize it accordingly.
    //W on the Grid Pane side/H to USE_COMPUTED_Let's set it to SIZE.
        cellValues[i][j].setPrefWidth(cellSize);
        cellValues[i][j].setPrefHeight(cellSize);
//Postscript:I found a setPrefSize method that can set Width and Height at the same time.
//The bottom works as the same function as the top two lines
//      cellValues[i][j].setPrefSize(cellSize,cellSize);


    //Put the coordinate values on the GridPane into the TextView options
        GridPane.setConstraints(cellValues[i][j], i, j);
    //Specify as a child
        inputGrid.getChildren().add(cellValues[j][i]);
//Postscript:The above two lines found the add method being executed internally.
//Is it due to the difference in version? Below is a description example
//      inputGrid.add(cellValues[clmIndx][rowIndx],clmIndx,rowIndx);


      }//for j/
    }//for i/
  }// initialize/

As far as the search operation is performed, it seems that it is necessary to set various properties (positioning) etc. with the "setProperty" method one by one in order to improve the appearance without using FXML. If you describe such a setting related to appearance, the start method of ʻApplication.java` that describes start seems to be long.

In other words Let FXML (or sceneBuilder) take care of the appearance. When an ID is generated comprehensively or when a computer's specialty is repeatedly described, the Controller is set to ʻInitializable and described in the ʻinitialize method.

Not limited to this case, when creating a GUI application with JavaFX using a database or file that manages resources prepared in some predetermined format, I wonder if such a method should be taken. Or.

Ruled line display

The border is "GridLineVisible" in the GridPane property, but stackOverflow respondent somewhere pointed out. According to what I was saying, "[It is written for debugging in the api document](https://docs.oracle.com/javase/jp/8/javafx/api/javafx/scene/layout/GridPane.html# gridLinesVisibleProperty) Don't use it. "

Instead, the css method was introduced, but I want to make the 3x3 group easier to see, so a little ... If so, it may be a story that you can make GridPane with 3x3 and nest GridPane (3x3), but that is also troublesome.

In the end, although I defined and used a constant called CELL_SIZE, it became quite dirty.

Controller


  private void showRuler(Group group) {
    for (int i = 0; i <= 3; i++) {
      Line hline=new Line(CELL_SIZE*3*i,0,CELL_SIZE*3*i,CELL_SIZE*9);
      Line vline=new Line(0,CELL_SIZE*3*i,CELL_SIZE*9,CELL_SIZE*3*i);
      hline.setStrokeWidth(1.5);
      vline.setStrokeWidth(1.5);

      group.getChildren().addAll(hline,vline);
    }
  }

The group argument specifies the Group that includes the GridPane that draws the ruled line. If you specify the coordinate position of the calling group in FXML, you do not need to specify layoutX or layoutY on this side.

Drawing with Line itself feels dirty, and I have no intention of responding to scaling. Make something like SimpleTableView. (If you want to do it, you can do it.)

Add input constraints

It is a problem if the input value is an integer value, especially if it is not a single digit. I want to allow only 0 to be entered as 1 to 9 and treat it as blank.

It seems that there are various ways to do it. It seems that it is better to use it properly according to the purpose. [input] What is the recommended way to create a numeric TextField in JavaFX? Yutchi's blog --I tried to input only the numbers from 0 to 9 in TextField

This was also helpful when dealing with regular expressions such as Formatter and Pattern. [Qiita --Basics of regular expressions @sea_ship](https://qiita.com/sea_ship/items/7c8811b5cf37d700adc4#1-%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F% BE% E3% 81% AE% E5% 9F% BA% E6% 9C% AC% E3% 81% AB% E3% 81% A4% E3% 81% 84% E3% 81% A6)

I chose to add a changed Listener that intuitively (?) Tweaks with an if statement. Try making the beap sound.

The following is in for (i) for (j) where TextField is placed in GridPane in Controller class

Controller.setInputGrid()


  TextField textField=new TextField("");

// add NumbersOnlyLimitation for the TextField
  textField.textProperty().addListener((observable, oldValue, newValue) -> {
    String str;
//    System.out.println(newValue);  //for debug
    if(newValue.matches("[0-9]?")){            // 0~When 9 is 1 character or 0 character
//Accept as normal
      str=newValue;
    }else if(newValue.matches("[0-9]{2}")) {   // 0~When 9 is 2 characters
//Accept new input as normal and discard old value
      str=String.valueOf(newValue.charAt(1));
    }else{                                     //other than that
      Toolkit.getDefaultToolkit().beep();      //Peron(Error sound)
//No change if the previous value is normal. Other than that""
      str=oldValue.matches("[0-9]") ? oldValue : "" ; 
    }
    textField.setText(str); //I wrote str because it was troublesome to write this one by one
  });

  textField.setPrefSize(CELL_SIZE, CELL_SIZE);
  textField.setAlignment(Pos.CENTER);
  textField.setFont(Font.font("", FontWeight.BOLD,-1.0)); //I wanted to make it a Bold symbol, but it doesn't get much fat...

  cellValues[clmIndx][rowIndx]=textField;
//property is also included in object(?)So this is cool.
//Or rather, I was really angry when I tried to make a Listener as an array

  inputGrid.add(cellValues[clmIndx][rowIndx], clmIndx, rowIndx);

At first, when ! NewValue.matches ("[^ 0-9] + "), it was replaced with "" (ambiguous)

Also, if you set " [0-9] " in matches, 0 characters, that is, "" will not be accepted. The first thing that came to my mind was, "There was a regular expression in the backspace, so let's do it when it's entered!" Perhaps in a way that no one would try, some of the writing was left in the code, but I made it like newValue.charAt (1) ==" \ b ", but this guy wants to mass-produce Nullpo. As it goes up, the standard output turns bright red.

I tried an experiment by outputting newValue to the standard output with a glue like "What's in it if it's not \ b?" (sout remains in the comment) When backspaced, "" after backspace becomes newValue, so charAt (1) seems to spit out a nullpo.

Example of input and output when sout is done in the above state Reproduce blank lines

input: a1b23\b8d
output:
a

1
1b
1
12
2
23
3

8
8d
8

\ b is backspace and blank lines are as reproduced. By the way, if you copy and paste an arbitrary character string, all but one or two half-width numbers will be beaped and only the last number entered will be entered. Even if I copy and paste the character string "" (nothing), beap sounds a little.

Input constraints-is this okay?

With this method, 81 ChangeListener objects are created, and I feel that there is a lot of waste ... I wonder if it can be shared by making it a single method.

So, it was ↓

Controller.setInputGrid()



//StringProperty Bean hash and TextField Map
    HashMap<Integer,TextField> hashMap=new HashMap<Integer, TextField>(81,1f);

    ChangeListener<String> cl=new ChangeListener<String>() {
      @Override
      public void changed(ObservableValue<? extends String> observable, String oV, String nV) {
        String str;
        if(nV.matches("[0-9]?")){ /*Omission*/ str=FILLED_VALUE }

//Dirty cast rarely seen this century
        StringProperty sp=(StringProperty)observable;
//    System.out.println(sp.getBean());
        hashMap.get(sp.getBean().hashCode()).setText(str);
      }
    };
    
    for (int clmIndx = 0; clmIndx < columnSize; clmIndx++) {
      for (int rowIndx = 0; rowIndx < RowSize; rowIndx++) {
        TextField textField=new TextField("");
        if(hashMap.containsKey(textField.textProperty().getBean().hashCode())) {
//Sorry error output. If you don't like hash collisions, you can just store the bean as it is ()
          System.err.println("textField.textProperty().getBean() Duplicated");
        }
        hashMap.put(textField.textProperty().getBean().hashCode(), textField);

//     System.out.println(textField.textProperty().getBean());

//  add NumbersOnlyLimitation for the TextField
        textField.textProperty().addListener(cl);

I'm not sure which one has better memory usage than the original code. Or rather, it's definitely shit in terms of readability.

Prepare a container that accepts input

We will define a class that processes the input data into a form that is easy to handle. By enriching this as it is, I would like to simplify the description in the class that handles the data.

What I especially want to do is Prepare a "reader" class that reads cells on the table for each [row / column / 3x3 subregion] That is.

If you want to manage whether or not the number already exists in each group, prepare a thing to read 27 groups of 9 columns, 9 rows, and 9 squares (hereinafter referred to as "region") from the table. I should give it.

Also, when actually solving, for example, "If there are n numbers that can only fit in the same n places in that region, those numbers will not fit in other places", so-called "joseki" I also want to incorporate it. (Although I think this will be implemented in the method on the solving side.)

I would like to further subdivide and prepare a list of "numbers that can be entered in each" and "numbers that cannot be entered" in each cell.

I defined it casually, but from here on,

"Cell" is each cell that should contain one number when solving Sudoku. "Region" is a group of numbers in a cell that are subject to duplication prohibition restrictions. Regions are further divided into "row Regions", "column Regions", and "3x3 subRegions". (The processing content is the same.) "Table" is a collection of all cells

Will be written. However, the table may be referred to as "Board" without notice. This is because we called it this way when we started development.

In manipulating shared data

In Java, pointers in C language are called "reference variables" or "reference values".

I want to make each region store the reference value so that it can be processed with only the data group of the cell for one table. In other words, I want to change the data of cells existing in the table by the operation from the region.

The following is an image diagram that does not connect

Cell Region image

Pass by value? Pass by reference? Evaluation strategy? what is that.

At this point, I was wondering, "Can Java process data like pointers?", So I looked at various things. I can't say it's passed by reference anymore This article was very helpful. I even read the last slide of "Winter 2018, which can't be called by reference anymore-material". "The theory of" passing by reference "! ?? I think I could understand it (I think (very anxious)) by the example in the section of "" or "pass by value" which was repeated 5 times on the slide.

I also read Java "pass by reference" problem summary @acevif and summarized it in my own way.

--Java methods only pass by value --A reference variable that handles Java objects (ʻObject obj; ʻobj) is a reference value for referencing an object. ――Behaves as if it were the reference destination itself. (You can create ʻobj.method ()instead ofreference of (obj) .method ().) ――It feels a little disgusting, but if you don't do this, you will need to write a format to retrieve the reference destination as shown above. Like "*" in " * pointer == object"in C language. --If you give a method argument that is not a primitive but is held by a reference variable, you can use a method that should be called "pass by reference value" to "** reference value that can be referenced" I'm handing it over. ... Excuse me. ** Passing the reference value "in" **. [^ 1] --One by one to understand "(tentative name) passing by reference value". Asmethod (arg) {} main () {method (val)} --In "pass by value", a duplicate of the value prepared as an actual argument is passed to the formal argument and processing is performed. --ʻArg is prepared with the same value as val, but things are different. --Changing the value indicated by ʻargdoes not change the value indicated byval. --In "pass by reference", the value itself prepared as an actual argument is passed to the formal argument and processed. --ʻArg is treated as exactly the same thing as val. --If you change the value indicated by ʻarg, the value indicated by val also changes. --In "(tentative name) pass by reference value", a copy of the reference value prepared as an actual argument is passed to the formal argument and processing is performed. --ʻArg is prepared with the same reference value as val, but the thing is different. --Changing the reference value indicated by ʻargdoes not change the reference value indicated byval. --However, since the reference value for referencing the object is passed, <br /> "" _object_ "pointed to by the reference value" indicated by "ʻarg" and "reference value indicated by val The "object" "pointed to by matches, and the
object itself can be modified. --This makes ʻargthe object pointed to by the reference value indicated byval, unless you update the reference value indicated by ʻarg (that is, the reference value pointing to the object pointed to by the reference value indicated by val). Can be handled. ――Due to the above-mentioned "behaves as if it is the reference destination itself" property, the appearance of the description seems to be passed by reference. --If you write in C language, you can operate ** val by operating ** arg.

If so, try writing it like C.

Color syntax is Java


private void method(ArrayList<String> **arg){
    *arg = new ArrayList<String>();
    **arg.add("PHP");
}

ArrayList<String> **list = new ArrayList<String>(); //I feel a little uncomfortable here
**list.add("Java");
method(list);
System.out.println(**list);    // [Java]

It's a description that feels like fighting in two languages, so it included a very unpleasant writing style, but intuitively this is the case.

[^ 1]: To be honest, the Japanese word "I'm handing it over" was awesome. When translating English, I can only say that such a translation is correct because I use "by" which can only be translated with "de". The original text is "call by reference or pass by reference". (Java "pass by reference" problem summary @acevif). It's quite a bit off topic, but after looking up the etymology of by and hit, it turned from "periphery" to "near", In turn, it is called "side" and "secondary".

Another detailed analogy or information

The teacher I was teaching said earlier in the Java class, "In Java, we basically don't use the word pointer, but all variables other than primitive types, that is, reference types. I feel like I now understand the meaning of the word "because it's a pointer".

If you pass the actual argument ʻint * val to the formal argument ʻint * arg, In C language notation, the pointer variable ʻarg can change * valby changing the destination* arg pointed to by the pointer. If you change the pointer of ʻarg in the function, Since ʻarg! = Valis set,* val is not changed even if * arg` is changed. Like.

In any case, I feel that I understand the meaning of the word "passing by value" from the article owner's conclusion "value" called "reference value".

You have to read the wikipedia article on "evaluation strategy" mentioned in the story properly. (It's also in English)

By the way, before reading these articles, I used the pointer of ** primitive type ** int array int [] [] cell, for example cell [i] [j], to rowRegion [i] .get (j). ) Died trying to fit. Or rather, I didn't realize that there wasn't enough information at all. When I tried to write a problem as an article here, I first thought "I want to handle something like a pointer", and started with "What is a Java pointer?" And encountered the above article. It feels like ...

... Since one element of an array of primitive type things is just a primitive type, I was trying to do something unreasonable in Java, which only passes by value. Well, I think it can be done by creating a simple class that has an int type as a member.

The story before that

My poor grace before I knew about passing prices.

  1. Create a "static Table class" and a "Region class that inherits ArrayList " in the Board class, and prepare a "static int [] [] type cell field" in the Table class. , Try to create a method to return "a Region object with cell [i] [j] in it" in the Board class.
  2. In order to make it easier to operate the cell, if you enter ij like the coordinates (x, y), to make it easier to operate the cell, the method to operate the int i, j field and cell is added to the ** Table class. Start writing inside. ** **
  3. At the stage of trying to fit the Table object in the Region object, it becomes "!!?", And in a hurry, create a PosXY class and put it in the Table class.
  4. I notice that a method with a considerable number of calls is not good at new ArrayList <> () every time it is called.
  5. I wonder if I can somehow make each element of cell [] [] look like a pointer.
  6. Start to describe the following from "[#Prepare a container that accepts input](#Prepare a container that accepts input)" to escape from reality.
  7. No, make a class. Teka int [] [] What is a cell? Create a Cell class ← Now here

...........^q^) so

I will design the Cell class.

Preface to the design description of each class

I wrote it at the beginning, and if you read the contents, you will understand it, and since you should have written it in the profile, you can understand it,

I'm a beginner of crunchy. No matter what you do, I think it will be a poor one, so please forgive me. (Comments such as criticism and improvement measures are welcome.) Even beginners of the same class should not use this as a reference. Even if you use it as a reference, let's get the opinion of the educator.

Cell class design

As a premise, Cell is viewed as one of the rows that are arranged like a table. Therefore, the factory method limits the instantiation to output only in a two-dimensional array. The output cell object and the name as a cell are ** cell **, We named multiple clusters of cells (Cell [] []) ** cells set **.

In addition, I decided to express the action of putting a number in a cell, that is, assigning a number to value and confirming it, as "filling". In English it is Fill. Even if you actually do Sudoku, you would say something like "fill in 3 here".

Below is a summary that is as rough as possible.

--Field --Pos pos: A Pos class object that indicates its position on the cells set. To briefly explain the Pos class, it has row numbers and column numbers as fields, and is responsible for limiting processing for them and processing using row numbers and column numbers used when using 3x3 subRegions. --ʻInt value: The number buried in the cell. Blank is 0 --boolean [10] possible: Stores whether or not the number corresponding to the element number may be filled in this cell. That is, if there is a possibility that 5 will be in the cell, possible [5] == true --Constructor --All private makeup. Have them called from the factory. The arguments are the initial values of Pos and value. It also initializes possible. --static method --Factory (2 types): Returns a two-dimensional array of Cells. This time, I made one that converts an int two-dimensional array to a cells set and one that duplicates the cells set. I knew that the reference destination would not change even if I cloned the array, so I became "serious". --makeCellArray: Argument is an int 2D array. Returns a set of cells that has been assigned arguments to values. --cloneCells: The argument is a set of cells. Returns a duplicate of a set of cells that can be manipulated as a separate object in the same state. --Method -- deny (int): Record numerical information that is unlikely to be buried in the cell in possible --ʻIsBecome (int arg) : Returns whether arg can be filled in the cell. Getter of the real possible [arg] --ʻIsFilled () : Returns whether the cell is filled. Since the blank is 0, value == 0 is returned. --tryFill (int arg)`: Attempt to fill arg in cell. Do not fill if not possible. If arg can be put in the cell, or if arg is already filled, true is returned. --Other getters and setters. Use private access as needed.

To write it together,

―― ʻint value that saves the value in the cell, the method tryFill that fills it, and ʻis Filled that asks" Is this cell filled? " --A method that saves boolean [10] possible and" I can't enter this number "in possible to save the data of numbers that are unlikely to enter the cell deny and" Can I enter this number? To the possible method ʻisBecome` --Other methods and constructors that instantiate

Is it like that? As I'm writing this, I'm wondering if it's not necessary to have the row number and column number in the cell itself, but why not? I wonder if it is not necessary if it is assumed that it is called by cells [i] [j] as an element of the array. For me, it would be nice if there was a HashMap that had two types of keys. If you specify only one key, an Iteratable "row list" will appear.

Postscript (19/02/01) I decided to let the Table class catch the object instead of the array. After all, I thought that the memory relationship was not good. See the Table class for details.

Copy constructor does not copy field boolean[]

When using IDEA, warnings and suggestions are displayed on the scroll bar. The red ones are the kind of things that usually cause compilation errors, and they won't compile unless you fix them. The yellow ones are "Use only in this method, isn't it private?" Or "I'm giving this field value, but I don't use it!" Or "The conditional expression of this if statement is always true, but I don't need it." There are a lot of things like that, but this time I'm going to take care of these as well.

There was something that could not be overlooked (headline) in it.

The actual sentence was "" possible "" instead of "boolean []". IDEA will increase the information by pressing more, so if you look at the contents of more,

Reports copy constructors that dont copy all fields in the class. Fields with the modifier transient are considered unnecessary to copy

Hmm? e? I know you're saying something about possible without transients, The first line is "There is a field that has not been copied", and the second line is "If you add transient, it is considered as something that does not need to be copied"? Wake Wakame.

I will show you the part where the declaration or warning was issued

Cell


//Various omissions

private boolean[] possible = new boolean[10];

private Cell(@NotNull Pos pos, int value) {

//  initialize pos
  this.pos = pos;

//  initialize Value
  setValue(value);

//  initialize possible[]
  if (value <0 | 9< value) {
    System.err.println("Cell constructor : out of range(==[0,9]) value");
    System.err.println("                     where pos points > "+pos.getStringIJ());
  } else if (isFilled()) {
    possible[value] = true;
  } else {
    for (int i = 0; i < possible.length; i++) {
      possible[i] = true;
    }
  }
}

private Cell(@NotNull Cell cell){     // Copy constructor does not copy field "possible"
  this(cell.getPos(),cell.getValue());
}

The warning text was inconsistent and I was in a hatena state, so I experimented.

Inside the Cell class



  public static void main(String[] args) { //Main solid writing in the class

    int[][] x={{0}};                      //Create values with only one element for testing
    Cell[][] cell1= makeCellArray(x);     //By the way, 9x9 constraints are done in the Board class.
    cell[0][0].deny(2);                   //This operation is possible[2]Has become false

    Cell[][] cell2=cloneCells(cell1);      //The constructor called by cloneCells is Cell(Cell cell)。...A little complicated

    System.out.println("cell1");
    for (boolean t:cell1[0][0].possible){  //Ask foreach to extract all the contents of the possible array.
      System.out.print(" "+( t?1:0 ));     //A casual ternary operator. Make true false the same output as C language
    }

    System.out.println(); //new line

    for (boolean t:cell2[0][0].possible){  //possible is private access, but it is cool because it is in the same class
      System.out.print(" "+( t?1:0 ));
    }
    System.out.println();
    System.out.println("cell2");
  }

Output


cell1
 1 1 0 1 1 1 1 1 1 1
 1 1 1 1 1 1 1 1 1 1
cell2

Ahhhhhh! !! !! !! !! !! Ah ~ ===== ~ = ~ == ~ = ~ =! !! !! !!

That's it. Uninitialized boolean is false. Over there. The constructor side is doing the job of initializing possible with value as 0, but the information that "2 does not enter" is not passed. (I noticed while writing this article.)

I've sealed the cell's clone method, but not the field's clone! That's why I decided to pass possible.clone. ... I don't have to call the constructor ...

... rewritten.


Well, but the story doesn't end here. It was transient that I was interested in passing. Nanikore

For the time being, when I set possible to transient and executed the code before modification, cell2.possible [2] became false (!!!!!!) What is this?

Investigate and m (I'm a little tired of writing articles, investigating, coding, etc., so I'll play the game. I won't disappear. I'll continue tomorrow)

Postscript (19/01/13) You'll forget it if you throw it in a circle later () todo writing

// todo: transient

Postscript (19/02/01) Until it was completed (melting), I squeezed it without any output here, so the following is like the trajectory up to that point.

Region class

Since I have added various extra functions, I will explain only the main method used in the completed (provisional) state. `Before, I used to say" I like arrays, "but it ended up being an ArrayList. ``

Region.java


public boolean valueFill(int value) {
  boolean changed = false;
  for (int i = 0; i < CellLength; i++) {
      changed |= get(i).deny(value);
    }
  }
  return changed;
}

When region.get (index) .tryFill (value) == true (In other words: if you succeed in filling ** value ** in the ** index ** th cell in the region) Another cells(: = indexOf (cells [i])! =** index) in the same region cannot be filled with ** value, so By having this method called in the class that will hold the region Let's make sure that ** _ value _ ** is cell.deny (value) in cells other than cell automatically, Method made with the intention ** return ** Boolean value that the update occurred as a result of this method call (whether the return value of cell.deny is true)

Table class

Created by inheriting java.util.HashMap. Store data with pos as key and cell as value. It has a getEmptyCells method that returns a list of unfilled cells.

Board class

A class that has a Table in the field and a Region array (9 in each of rows, columns, and subs, for a total of 27), and integrates and operates them. The size that you only have to new this when making a duplicate. Create a duplicate by passing a board object to the constructor. I wrote it to exclude the anxiety factor when I want to make a deep copy.

In addition, we have prepared a method to perform Cell :: tryFill and Region :: valueFill, and will use it as a "method to fill the value" from the NPS class described later.

NumberPlaceSolver class

I wrote it as a class that executes a group of algorithms to actually solve Sudoku. As a field

--Int value to provide safety when recursion is too much when performing "temporary placement" processing with recursive processing ("depth" of recursive processing) --Constant that limits the depth (82) --Board class instance

have.

I wrote an "Algorithm" class that stores methods as an inner class. WANT todo: Processing such as executing all methods written in a place like "method list"

For now, only "temporary placement" is implemented. When temporarily placing, a new instance of NumberPlaceSolver is to be created with the location and value of the temporarily placed cell and the "current status (this)" as arguments.


The story that was in the wrong order

At first, I thought I was thinking, "Let's make it from the user side!"

Make a screen display, make an NPS class, and ... let's make a Cell class! (← !?)

Because it became, it became a design with a lot of unnecessary methods and waste. Also, it was the original purpose I gave up the implementation of "Temporarily place multiple threads at the same time and deny each one. Furthermore, by making a static table deny, multiple values can be deny at the same time" (? ), So the direction was quite different from what I expected. For the time being, it was completed so that it could be solved, but if it was not filled more than half, it would take a long time, so I would like to improve it.

Recommended Posts

A memo when fumbling and developing using JavaFX
A memorandum when trying to create a GUI using JavaFX
[Personal memo] Writing a file using BufferedWriter
[Rails] [Memo] When to add = to <%%> and when not
Output using methods and constants Learning memo
[Personal memo] Reading a file using BufferedReader
A memo to simply create a form using only HTML and CSS in Rails 6
When using a list in Java, java.awt.List comes out and an error occurs
A simple rock-paper-scissors game with JavaFX and SceneBuilder
When performing a full outer join without using a full outer join
A memo when building a Rails 5.2 development environment using Docker Desktop + WSL2 on Windows 10 Home
JavaFX and HiDPI
A memo when "I do not get a certificate error with a self-signed certificate using Java's Keytool"
Create a portfolio app using Java and Spring Boot
Display a loading image in JavaFX and then display another image
How to convert A to a and a to A using AND and OR in Java
A memorandum when installing Docker and building a Linux container
A memo to check when you try to use Lombok
A memo when the incoming number acquisition using Broadcast Receiver does not work on Android 9/10