Reputation: 1371
We are trying to achieve this layout the row of dice are TextFields that are populated with one of the letters that is on a side of the dice when the Random Button is clicked
We have a Target TextField that is made up of duh TextFields.
When the user drags one of the dice to a Target the Target is populated.
The issue is the relationship of the Source to Target is 1 to 1 and the user has no idea in advance where the source needs to be placed.
Next we tried to use a Button to represent the dice and drag and drop the Button to the newPane which is an AnchorPane. When we try to add the second button we get an error trying to add duplicate children to pane
The questions are
1. Can we have a one to many relationship of Source to Targets?
If so how do we code this ? It looks like if possible a unreal lines of code
How to overcome the issues with using the newPane concept?
OR is there a better way to design this?
We know we can click the Button and build a word and add it to a ListView NOT what we want.
We will post the code to use the Button to the newPane it works but when we duplicate this code for the second Button we get the error as noted above
@Override
public void initialize(URL url, ResourceBundle rb) {
// Add mouse event handlers for the source
btnOK.setOnMousePressed((MouseEvent event) -> {
btnOK.setMouseTransparent(true);
event.setDragDetect(true);
});
btnOK.setOnMouseReleased((MouseEvent event) -> {
btnOK.setMouseTransparent(false);
});
btnOK.setOnMouseDragged((MouseEvent event) -> {
event.setDragDetect(false);
});
btnOK.setOnDragDetected((MouseEvent event) -> {
btnOK.startFullDrag();
});
// Add mouse event handlers for the target
// =======================================
newPane.setOnMouseDragEntered((MouseDragEvent event) -> {
});
btnOK.setOnMouseDragEntered((MouseDragEvent event) -> {
});
newPane.setOnMouseDragOver((MouseDragEvent event) -> {
});
newPane.setOnMouseDragReleased((MouseDragEvent event) -> {
System.out.println(event.getX());
System.out.println(event.getY());
double h = event.getX();
double v = event.getY();
newPane.getChildren().add(btnOK);
btnOK.setLayoutX(h);
btnOK.setLayoutY(v);
t1.setText(s1.getText());
t1.setStyle("-fx-background-color: lightblue;");
//newPane.getChildren().add(s1);
});
tosswordPane.setOnMouseDragExited((MouseDragEvent event) -> {
});
}
Here is a screen shot of the layout we are trying to achieve
Upvotes: 0
Views: 276
Reputation: 1371
Original question involved using a mouse drag and drop to mimic the manual playing of Toss Word.
This drag and drop method did not work very well so here is the new method
This game was a product of Krack Games copy write date of 1948 and was written by Adie E. Giessow.
Toss Word has 14 dice the letters on the dice are as follows.
d1 = "GHDCEI"; d2 = "IKLHIG"; d3 = "TARSMV"; d4 = "EYIUAO"; d5 = "SABODY";
d6 = "BACEFD"; d7 = "MNKLIT"; d8 = "LMONIP"; d9 = "IEOHRF"; d10 = "MEORSN";
d11 = "EAXWYZ"; d12 = "SEAUWT"; d13 = "UNSHOT"; d14 = "PROSTQ";
Toss Word Rules
Players take turns rolling the letter dice and forming words from the resulting letters. Words must have a minimum of 3 letters & no proper names. Score one point for each letter used in forming words. Bonus: Use of all 14 letters counts 25, not 14. Bonus: The word "GAME" counts 50 points.
Game Design
We used TextFields to represent the Dice and the Target Playing Board
We use minimal characters for naming these Source (s1) and Target (t1)
We used On Mouse Clicked events to mimic placing the Dice letter on the Target Playing Board
We then used On Mouse Pressed Event to permit removing the Dice letter so as to place in a new position
We use a boolean PLAY = false to inhibit rolling the dice once the game started
To mimic rolling the Dice we use a Random Number Generator a one liner lambda
To select the Dice we place a lambda expression in the initialize(URL url, ResourceBundle rb)
This seems to let the Dice selection process act as a listener
The BIG draw back to the Target Playing Board design is each TextField requires 117 lines of code
We reduce our Target Playing Board to 10 rows by 8 columns so that makes roughly 9360 lines of very redundant code for each TextField on the Playing Board
If someone has a better layout design for the Target Playing Board feel free to comment!
One very neat in line CSS styling declaration was utilized not my creation but found on SO
It prevents the loss of the boarder around the TextField when color styling is applied
Here it is t2.setStyle("-fx-control-inner-background:lightblue")
We will post a code snippet of the random number generator and the selection of the Dice
We will post the complete code for one Playing Board interaction
Rolling the Dice
@FXML
private void onRandom() throws NoSuchFieldException{
//new Random().ints(7, 1, 7).forEach(System.out::println);
makeEnabled();
if(PLAY == true){
btnOK.requestFocus();
return;
}
makeVisible();
new Random().ints(1, 1, 7).forEach(ints -> {
int V = ints;
String d1 = "GHDCEI";
String S1 = String.valueOf(d1.charAt(V-1));
s1.setText(S1);
});<br>
Selecting the Dice
@Override
public void initialize(URL url, ResourceBundle rb) {
s1.setOnMouseClicked((MouseEvent )->{
move = s1.getText();
s1.setVisible(false);
PLAY = true;
});
s2.setOnMouseClicked((MouseEvent )->{
move = s2.getText();
s2.setVisible(false);
PLAY = true;
});<br>
Placing and Removing the Letters from the Playing Board
@FXML
private void onMC2(){
if(PLAY == false){
t2.setStyle("-fx-control-inner-background:red");
return;
}
t2.setText(move);
move = "";
btnOK.requestFocus();
if(t2.getText().isEmpty()){
t2.setStyle("-fx-control-inner-background:white");
}else{;
t2.setStyle("-fx-control-inner-background:lightblue");
}
// Code above error traps and places dice on Play Field
// Code below removes the dice to permit moving to alternate target location
t2.setOnMousePressed((MouseEvent event) -> {
if(t2.getText().equals(s1.getText())){
if(!s1.isVisible()){
s1.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s2.getText())){
if(!s2.isVisible()){
s2.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s3.getText())){
if(!s3.isVisible()){
s3.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s4.getText())){
if(!s4.isVisible()){
s4.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s5.getText())){
if(!s5.isVisible()){
s5.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s6.getText())){
if(!s6.isVisible()){
s6.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s7.getText())){
if(!s7.isVisible()){
s7.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s8.getText())){
if(!s8.isVisible()){
s8.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s9.getText())){
if(!s9.isVisible()){
s9.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s10.getText())){
if(!s10.isVisible()){
s10.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s11.getText())){
if(!s11.isVisible()){
s11.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s12.getText())){
if(!s12.isVisible()){
s12.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s13.getText())){
if(!s13.isVisible()){
s13.setVisible(true);
t2.setText("");
return;
}
}
if(t2.getText().equals(s14.getText())){
if(!s14.isVisible()){
s14.setVisible(true);
t2.setText("");
return;
}
}
});
}<br>
At one time we were considering using a process to generate possible words from the results of rolling the dice. Here is the code that generates search combinations from the roll of the dice.
This is then run against a dictionary with a stream
We did not incorporate this in the game it seemed like it defeated the idea of the game
Which was to THINK
Code to Build Search Words
Private Void buildSearchWords(){
String W = "ILRYADIIEMASHT".toLowerCase();
int L = W.length();
ArrayList<String> rearange = new ArrayList<>();
for(int i = 1; i <= L; i++){
String firstLetter = W.substring(0, i);
String endLetter = W.substring(L - (L-i), L);
String endLetterNew = W.substring(L-i);
StringBuilder sb = new StringBuilder(W);
sb.replace(0, i, endLetterNew);
sb.replace(L-i, L, firstLetter);
rearange.add(sb.toString());
}
for(int X = 0; X < rearange.size();X++){
String A = rearange.get(X);
txaInput.appendText(A);
txaInput.appendText(" ");
}
Code to Compare against the Dictionary
List<String> dictionary = Arrays.asList(dictionaryArray);
ArrayList<String> list = new ArrayList<>();
int W = txtMonitor.getText().length();
String newFirstLetter = txtMonitor.getText().substring(0, 1).toLowerCase();
String newEndLetter = txtMonitor.getText().substring(W - 2, W);
}
dictionary.stream().filter(s -> s.startsWith(searchString)
|| s.startsWith(nF, 0)
&& s.length() > 1 && s.length() <= W+3
&& s.endsWith(nE))
.forEach(list :: add);
Upvotes: 1
Reputation: 3235
We can turn this into a two step (dance) process and make it kind of manageable
The manageable part involves reducing the Target TextField to 10 rows by 8 columns
This will mean you only need 80 times 6 lines of code per dice with the total being 6720 lines of code. NOT great but it works copy and paste your heart out
OH at the top of our wild code you will see the hover method which is worthless
It works like this hold the mouse button down and release over the target
We used onMouseReleased in the target area you could use onMouseClicked
@FXML
private void onHover(){
t4.setText(s4.getText());
}
String move;// needs to be global
@Override
public void initialize(URL url, ResourceBundle rb) {
s6.setOnMouseClicked((MouseEvent e)->{
move = s6.getText();
//s6.setVisible(false);
});
t1.setOnMouseReleased((MouseEvent event)->{
if(s6.isVisible()){
t1.setText(move);
s6.setVisible(false);
}
});
t2.setOnMouseReleased((MouseEvent e)->{
if(s6.isVisible()){
t2.setText(move);
s6.setVisible(false);
}
});
Happy Copping and Pasting ha ha
Upvotes: 1