5
\$\begingroup\$
import javax.swing.JOptionPane;

public class DividedBy10v2{

    public static void main( String[] args ){
        int block[][] = new int[3][3];
        int DetermineRow = 0;   // The variable assigned for counting rows
        int DetermineColumn = 0; // The variable assigned for counting columns
        int blockRow,blockColumn;
        int score = 0;
        String inputRow, inputColumn;

        //random a set of number
        int randomSet[] = new int[100];
        for(int i=0;i<randomSet.length;i++){
            randomSet[i] = (int) (Math.random() * 9) + 1;
        }

        int round = 0 ;//for counting the round of the game
        while( true ){
            ++round;

            //print out the title and score
            System.out.println( "-------------------------" );
            System.out.println( "Divided by 10 - Mini Game" );
            System.out.printf( "----  Score:%8d  ----\n\n", score );

            //show game board
            System.out.println( "  0 1 2 " );
            for(DetermineRow=0;DetermineRow<block.length;DetermineRow++){
                System.out.print( DetermineRow + " ");
                for(DetermineColumn=0;DetermineColumn<block.length;DetermineColumn++){
                    if(block[DetermineRow][DetermineColumn]!=0){
                        System.out.print( block[DetermineRow][DetermineRow] + " " );
                    }else{
                        System.out.print( "_ " );
                    }
                }
                System.out.println();
            }


            //display the coming value
            System.out.printf( "Coming value : %d > %d > %d \n\n", randomSet[round], randomSet[(round + 1)], randomSet[(round + 2)] );

            //check over checking
            if(block[0][0]>0&&block[0][1]>0&&block[0][2]>0){
                if(block[1][2]>0&&block[1][1]>0&&block[1][2]>0){
                    if(block[2][0]>0&&block[2][1]>0&&block[2][2]>0){
                        System.out.println( "------  Game Over  ------" );
                        //continue check
                        int ContinueCheck = JOptionPane.showConfirmDialog(null, "Do you want to continue ?", "Continue?", JOptionPane.YES_NO_OPTION);
                        if( ContinueCheck == JOptionPane.YES_OPTION){
                            //initialize the game board
                            for(DetermineRow=0;DetermineRow<block.length;DetermineRow++)
                                for(DetermineColumn=0;DetermineColumn<block.length;DetermineColumn++)
                                block[DetermineRow][DetermineColumn]=0;
                            continue;
                        }else{if(ContinueCheck == JOptionPane.NO_OPTION){
                            System.out.println( "-------------------------" );
                            System.out.println("Good Bye !");
                            break;}
                        }
                    }
                }
            }

            //input value
            while(true){
                inputRow = JOptionPane.showInputDialog( "The number of row you want to put the number" );
                blockRow = Integer.parseInt(inputRow);
                inputColumn = JOptionPane.showInputDialog( "The number of column you want to put the number" );
                blockColumn = Integer.parseInt(inputColumn);
                if(blockRow>=block.length || blockRow<0 || blockColumn>=block.length || blockColumn<0){
                    JOptionPane.showMessageDialog(null , "The block you want to enter the number does not exist." , "Error" , JOptionPane.ERROR_MESSAGE );
                    continue;
                }else{
                    if(block[blockRow][blockColumn]!=0){
                        JOptionPane.showMessageDialog(null , "The block you want to enter the number has been entered an number." , "Error" , JOptionPane.ERROR_MESSAGE );
                        continue;
                    }else{
                        block[blockRow][blockColumn] = randomSet[round];
                        break;
                    }
                }
            }

            //score got check
            int modSumBlock[] = {-1,-1,-1,-1,-1,-1,-1,-1};//to store the remainder of the sum of 3 block
            if(block[0][0] != 0 && block[0][1] != 0 && block[0][2] != 0)
                modSumBlock[0] = (block[0][0] + block[0][1] + block[0][2]) % 10;
            if(block[1][0] != 0 && block[1][1] != 0 && block[1][2] != 0)
                modSumBlock[1] = (block[1][0] + block[1][1] + block[1][2]) % 10;
            if(block[2][0] != 0 && block[2][1] != 0 && block[2][2] != 0)
                modSumBlock[2] = (block[2][0] + block[2][1] + block[2][2]) % 10;
            if(block[0][0] != 0 && block[1][0] != 0 && block[2][0] != 0)
                modSumBlock[3] = (block[0][0] + block[1][0] + block[2][0]) % 10;
            if(block[0][1] != 0 && block[1][1] != 0 && block[2][1] != 0)
                modSumBlock[4] = (block[0][1] + block[1][1] + block[2][1]) % 10;
            if(block[0][2] != 0 && block[1][2] != 0 && block[2][2] != 0)
                modSumBlock[5] = (block[0][2] + block[1][2] + block[2][2]) % 10;
            if(block[0][0] != 0 && block[1][1] != 0 && block[2][2] != 0)
                modSumBlock[6] = (block[0][0] + block[1][1] + block[2][2]) % 10;
            if(block[0][2] != 0 && block[1][1] != 0 && block[2][0] != 0)
                modSumBlock[7] = (block[0][2] + block[1][1] + block[2][0]) % 10;
            //all 'if' is used for checking if all block in the same row/column/diagonal are filled in number

            //counting how many score got and where should be cleared by 8bit (in decimal)
            int scoreCount = 0;
            for(int n=0;n<8;n++){
                if(modSumBlock[n]==0){
                    score += 10;
                    scoreCount += (int) Math.pow(2,n);
                }else{
                    continue;
                }
            }

            //start clear game board
            if(scoreCount>=128){
                block[0][2] = 0;
                block[1][1] = 0;
                block[2][0] = 0;
                scoreCount -= 128;
            }
            if(scoreCount>=64){
                block[0][0] = 0;
                block[1][1] = 0;
                block[2][2] = 0;
                scoreCount -= 64;
            }
            if(scoreCount>=32){
                block[0][2] = 0;
                block[1][2] = 0;
                block[2][2] = 0;
                scoreCount -= 32;
            }
            if(scoreCount>=16){
                block[0][1] = 0;
                block[1][1] = 0;
                block[2][1] = 0;
                scoreCount -= 16;
            }
            if(scoreCount>=8){
                block[0][0] = 0;
                block[1][0] = 0;
                block[2][0] = 0;
                scoreCount -= 8;
            }
            if(scoreCount>=4){
                block[2][0] = 0;
                block[2][1] = 0;
                block[2][2] = 0;
                scoreCount -= 4;
            }
            if(scoreCount>=2){
                block[1][0] = 0;
                block[1][1] = 0;
                block[1][2] = 0;
                scoreCount -= 2;
            }
            if(scoreCount>=1){
                block[0][0] = 0;
                block[0][1] = 0;
                block[0][2] = 0;
                scoreCount -= 1;
            }
        }
    }
}

The above code is a mini-game I made which consists of a 3x3 game board. Integer values range from 1-9 and are generated by the system and stored in an array. If all the values have been used, it will start again from the first element of the array. In each round, the next three coming numbers are shown to player, so the player know the value that is going to put not only in the current round, but also the coming two rounds.

Note that each position in the game board allows only one value. The program should check if the input position is already allocated. If so, player should be prompted to input again. At the end of a round, the system will check the three rows, the three columns and the two diagonals of the game board; if the sum of a set is divisible by 10, the sum can be added to the score and values can be removed from the game board. The empty slot is counted as 0, the game is over when the game board is full.

I want to simplify the code as it looks too messy and complicated. Is there a way to shorten the code using other methods? How do I also allow players to choose from different size of game board (e.g. starting of the game it will ask players if they want to play 3vs3 4vs4 or 5vs5)? You may try compile the code and play the game to see how it works.

\$\endgroup\$
0

1 Answer 1

6
\$\begingroup\$

I think, when I run your program, that the combination of text-console and swing user input leads to a bad experience.

Really, given that you have the GUI input boxes, why do I have to type the row/column that you want entered? Why not present me with a grid of buttons, and I have the number I can add to the grid, and I just click where the number should go?

Doing such a grid would potentially even be easier than the text output you put on the console.

Despite that, I do appreciate that the code is runnable, and works.... until I press the cancel button, at which point the code throws a NumberFormatException.

As for the code style, it seems awfully complicated, with a lot of code repetition and 'magic numbers'. Changing the size of the grid would be very frustrating.... it is all hard-coded in.

So, you should set up a constant, say 'gridsize' and use that in many places:

final int gridsize = 3;

Then you can fix a lot of places where you have magic numbers:

int block[][] = new int[gridsize][gridsize];
....
    randomSet[i] = (int) (Math.random() * gridsize * gridsize) + 1;

and so on.

The Show-Game-Board will become some form of loop:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < gridsize; i++) {
    sb.append(String.format("%4d", i));
}

Also, having variable names with capital-letters is not good java coding convention... The line:

for(DetermineRow=0;DetermineRow<block.length;DetermineRow++){ ....

is very off-putting to Java 'regulars'. For small loops like that, something simple like:

for (int row = 0; row < gridsize; row++) { ...

would be much more understandable. Note that I declared the row variable inside the for loop (int row = 0). This is the normal way to define variables in for loops. It is not essential, but it actually leads to fewer bugs when the loop-variable is contained entirely inside the loop... (i.e. row is not visible outside the loop).

Now, inside that display loop, because you have complicated names, it has made a bug hard to see..... This is your code:

        for(DetermineRow=0;DetermineRow<block.length;DetermineRow++){
            System.out.print( DetermineRow + " ");
            for(DetermineColumn=0;DetermineColumn<block.length;DetermineColumn++){
                if(block[DetermineRow][DetermineColumn]!=0){
                    System.out.print( block[DetermineRow][DetermineRow] + " " );
                }else{
                    System.out.print( "_ " );
                }
            }
            System.out.println();
        }

I will simply rename your variables.... and we can see a bug much more easily:

            for(row=0;row<block.length;row++){
                System.out.print( row + " ");
                for(column=0;column<block.length;column++){
                    if(block[row][column]!=0){
                        System.out.print( block[row][row] + " " );
                    }else{
                        System.out.print( "_ " );
                    }
                }
                System.out.println();
            }

Can you see the bug now?

System.out.print( block[row][row] + " " );

Should be:

System.out.print( block[row][column] + " " );

Similarly, because you have complicated if-statements on the game-check, you have another bug there:

       if(block[0][0]>0&&block[0][1]>0&&block[0][2]>0){
            if(block[1][2]>0&&block[1][1]>0&&block[1][2]>0){
                if(block[2][0]>0&&block[2][1]>0&&block[2][2]>0){

That should, on the second line be a 0 (I have marked the position with a '^'):

       if(block[0][0]>0&&block[0][1]>0&&block[0][2]>0){
            if(block[1][2]>0&&block[1][1]>0&&block[1][2]>0){
                        ^
                if(block[2][0]>0&&block[2][1]>0&&block[2][2]>0){

Using a loop (preferably in a method) would be better:

private static final boolean isComplete(int[][] grid) {
    for (int row = 0; row < grid.length; row++) {
        for (int col = 0; col < grid[row].length; col++) {
            if (grid[row][col] == 0) {
                return false;
            }
        }
    }
    return true; // all celss have values.
}

You can then, instead, call:

        //check over checking
        if(isComplete(block)){
                    int ContinueCheck = JOptionPane.showConfirmDialog(null, "Do you want to continue ?", "Continue?", JOptionPane.YES_NO_OPTION);
                    if( ContinueCheck == JOptionPane.YES_OPTION){
                        ...
                        continue;
                    }else if(ContinueCheck == JOptionPane.NO_OPTION) {
                        System.out.println( "-------------------------" );
                        System.out.println("Good Bye !");
                        break;
                    }
        }    

Note

Note how, at this point I have never referenced the actual size of the grid as being 3...? So all the code I have changed so far will work with a grid of any size....

Then, the final part, is getting the scores..... This part is slightly more challenging, but, can be done with a few loops... first, the int modSumBlock[] = {-1,-1,-1,-1,-1,-1,-1,-1} is another 'magic number' (8), and should be:

int modSumBlock[] = new int[gridsize + gridsize + 2]; // rows, columns, and diagonals

Then your loops are:

for (int row = 0; row < gridsize; row++) {
    modSumBlock[       0 + row] = getRowScore(block, row);
}
for (int col = 0; col < gridsize; col++) {
    modSumBlock[gridsize + col] = getColumnScore(block, col);
}
modSumBlock[gridsize + gridsize]     = getSlashDiagonalScore(block);
modSumBlock[gridsize + gridsize + 1] = getBackslashDiagonalScore(block);

At this point you should have some idea of the other changes you should make....

have fun!

\$\endgroup\$
4
  • \$\begingroup\$ hi, i've read through your answer, im new to programming, first time using java. the part which u mentioned "int block[][] = new int[gridsize][gridsize]; .... randomSet[i] = (int) (Math.random() * gridsize * gridsize) + 1;" and " StringBuilder sb = new StringBuilder(); for (int i = 0; i < gridsize; i++) { sb.append(String.format("%4d", i)); } " how does it work, i mean where do i start. mhy programming teacher did not teach me about stringbuilder. help \$\endgroup\$
    – user32809
    Nov 30, 2013 at 16:59
  • \$\begingroup\$ the 4 dots .... , is it intended or do i have to write the arrays? \$\endgroup\$
    – user32809
    Nov 30, 2013 at 17:12
  • \$\begingroup\$ @Hecton - the dots are just to show that there's more code afterwards. As for your other comment/question, I don't thing the things I have suggested are that much more complicated than your original question, so I feel there is a gap somewhere... You need to sit with someone (your teacher?) and go through with them. This is not the right forum. As for StringBuilder, you can read up on it here: docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html it is just a faster way to join String values. \$\endgroup\$
    – rolfl
    Nov 30, 2013 at 17:26
  • \$\begingroup\$ i seem to be getting alot of errors with this method, too confusing, such as illegal start of expression private static.. \$\endgroup\$
    – user32809
    Nov 30, 2013 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.