Difference between revisions of "Sudoku Generator (Example for the OSGi Lab)"

From CDOT Wiki
Jump to: navigation, search
(Sudoku Generator (Example for the OSGi Lab))
(Design and Implementation)
Line 10: Line 10:
 
First, let me say that I followed Jordan's Voting System example, for both the code as well as the writeup on this wiki.
 
First, let me say that I followed Jordan's Voting System example, for both the code as well as the writeup on this wiki.
  
<h4>1. Define the Service</h4>
+
<h4> 1. Define the Service</h4>
 
Create the bundle ''ca.on.senecac.scs.sudoku''
 
Create the bundle ''ca.on.senecac.scs.sudoku''
<h6>1.1 Create SudokuGenerator.java</h6>
+
<h6> 1.1 Create SudokuGenerator.java</h6>
 
<source lang="java">
 
<source lang="java">
 
package ca.on.senecac.scs.sudoku;
 
package ca.on.senecac.scs.sudoku;
Line 27: Line 27:
 
}
 
}
 
</source>
 
</source>
<h6>1.2 Define the MANIFEST.MF for the service</h6>
+
<h6> 1.2 Define the MANIFEST.MF for the service</h6>
 
<source lang="xml">
 
<source lang="xml">
 
Manifest-Version: 1.0
 
Manifest-Version: 1.0
Line 36: Line 36:
 
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
 
Export-Package: ca.on.senecac.scs.sudoku
 
Export-Package: ca.on.senecac.scs.sudoku
 +
</source>
 +
<h4> 2. Define the Service Provider</h4>
 +
Create the bundle ''ca.on.senecac.scs.sudoku.provider''
 +
<h6> 2.1 Create SudokuActivator.java</h6>
 +
<source lang="java">
 +
package ca.on.senecac.scs.sudoku.provider;
 +
 +
import org.osgi.framework.BundleActivator;
 +
import org.osgi.framework.BundleContext;
 +
 +
import ca.on.senecac.scs.sudoku.SudokuGenerator;
 +
import ca.on.senecac.scs.sudoku.provider.internals.*;
 +
 +
/**
 +
* The Sudoku Generator provider bundle is registered here.
 +
*
 +
* @author John Selmys
 +
*
 +
*/
 +
public class SudokuActivator implements BundleActivator {
 +
 +
    private static BundleContext context;
 +
   
 +
    static BundleContext getContext() {
 +
        return context;
 +
    }
 +
 +
    public void start(BundleContext bundleContext) throws Exception {
 +
        SudokuActivator.context = bundleContext;
 +
       
 +
        SudokuGenerator sg = new SimpleSudokuGenerator();
 +
        context.registerService(SudokuGenerator.class.getName(), sg, null);
 +
        System.out.println("Sudoku Generator Registered !");
 +
    }
 +
 +
 
 +
    public void stop(BundleContext context) throws Exception {
 +
        SudokuActivator.context = null;
 +
        System.out.println("Sudoku Generator Stopped !");
 +
 +
    }
 +
 +
}
 +
</source>
 +
<h6> 2.2 Create SimpleSudokuGenerator.java</h6>
 +
<source lang="java">
 +
package ca.on.senecac.scs.sudoku.provider.internals;
 +
import java.util.Random;
 +
import ca.on.senecac.scs.sudoku.SudokuGenerator;
 +
 +
/**
 +
* The code to generate a Sudoku grid is here. Note that the
 +
* method "generate(int,int)" is recursive.
 +
*
 +
* @author John Selmys
 +
*
 +
*/
 +
public class SimpleSudokuGenerator implements SudokuGenerator {
 +
    static Grid g = new Grid(9);
 +
    static int counter = 0;
 +
 
 +
    /**
 +
    * The computation of a random valid (9x9) Sudoku puzzle
 +
    * starts here.
 +
    */
 +
    public void generate(int row, int col) {
 +
        if(row > 8) {
 +
            puzzle();
 +
            System.out.println("All Done!");
 +
            g.display();
 +
            System.exit(0);
 +
        }
 +
        int[] a = {1,2,3,4,5,6,7,8,9};
 +
        get9(a);
 +
        for(int i=0;i<9;i++) {
 +
            int m = a[i];
 +
            counter++;
 +
            if(available(row,col,m)) {
 +
                g.setGrid(row, col, m);
 +
                if(col < 8) {
 +
                    generate(row,col+1);
 +
                } else {
 +
                    generate(row+1,0);
 +
                }
 +
            }
 +
        }
 +
        if(col > 0) {
 +
            col--;
 +
        } else {
 +
            col = 8;
 +
            row--;
 +
        }
 +
        g.setGrid(row, col, 0);
 +
    }
 +
 
 +
    /**
 +
    * Make a 3x3 Sudoku puzzle and place into grid.
 +
    *
 +
    */
 +
    static void puzzle() {
 +
        for(int r=0;r<7;r+=3) {
 +
            for(int c=0;c<7;c+=3) {
 +
                int x[] = {1,2,3,4,5,6,7,8,9};
 +
                get9(x);
 +
                for(int row=0;row<3;row++) {
 +
                    for(int col=0;col<3;col++) {
 +
                        int R = row+r;
 +
                        int C = col+c;
 +
                        int p = row * 3 + col + 1;
 +
                        if(p==x[0] || p==x[1] || p==x[2] || p==x[3]) {
 +
                            g.setGrid(R, C, 0);
 +
                        }
 +
                    }
 +
                }
 +
            }
 +
        }
 +
    }
 +
 +
    /**
 +
    * Checks the grid to see if value 'm' can be placed at
 +
    * position (r,c)
 +
    *
 +
    */
 +
    static boolean available(int r, int c, int m) {
 +
        for(int col=0;col<9;col++) {
 +
            if(g.getGrid(r, col) == m) return false;
 +
        }
 +
        for(int row=0;row<9;row++) {
 +
            if(g.getGrid(row, c) == m) return false;
 +
        }
 +
        r = r/3 * 3;
 +
        c = c/3 * 3;
 +
        for(int row=0;row<3;row++) {
 +
            for(int col=0;col<3;col++) {
 +
                int R = row + r;
 +
                int C = col + c;
 +
                if(g.getGrid(R, C) == m) return false;
 +
            }
 +
        }
 +
        return true;
 +
    }
 +
 
 +
    /**
 +
    * Get an array containing integers [1..9] in random order.
 +
    *
 +
    */
 +
    static void get9(int a[]) {
 +
        Random rand = new Random();
 +
        for(int i=8; i>0; i--) {
 +
            int r = rand.nextInt(i);
 +
            int t = a[i];
 +
            a[i] = a[r];
 +
            a[r] = t;
 +
        }
 +
        for(int k=0;k<9;k++)System.out.print(a[k]+"  ");
 +
        System.out.println(" ");
 +
    }
 +
 +
 +
}
 +
</source>
 +
<h6> 2.3 Create Grid.java</h6>
 +
<source lang="java">
 +
package ca.on.senecac.scs.sudoku.provider.internals;
 +
 +
/**
 +
* The Sudoku Grid class contains the results of the Sudoku
 +
* Generator.
 +
*
 +
* @author John Selmys
 +
*
 +
*/
 +
public class Grid {
 +
    int[][] grid;
 +
 +
    Grid(int side) {
 +
        grid = new int[side][side];
 +
        for (int i=0;i<9;i++)
 +
            for(int j=0;j<9;j++)
 +
                grid[i][j] = 0;
 +
    }
 +
 
 +
    void display() {
 +
        for (int i=0;i<9;i++) {
 +
            for(int j=0;j<9;j++)
 +
                System.out.print(grid[i][j]+" ");
 +
            System.out.println();
 +
        }
 +
    }
 +
 
 +
    void setGrid(int r, int c, int v) {
 +
        grid[r][c] = v;
 +
    }
 +
 
 +
    int getGrid(int r, int c) {
 +
        return grid[r][c];
 +
    }
 +
}
 
</source>
 
</source>

Revision as of 20:35, 13 February 2011

Sudoku Generator (Example for the OSGi Lab)

This is my first attempt to build a simple Java application using the OSGi framework.

Some time ago I wrote a Sudoku Generator program using BASH version 4. You can find the code on my blog at selmys.wordpress.com. I've chosen this same example to rewrite in Java/OSGi.

Yes, I know my code (and lack of documentation) is sloppy. That's because I tried to focus on trying to figure out what goes into each bundle. I'm sure I got many things wrong but on the positive side, the code works and actually generates a 9x9 Sudoku puzzle, albeit on the console in text mode. Perhaps in the future I'll produce a GUI output - or maybe someone can do it for me?

Design and Implementation

First, let me say that I followed Jordan's Voting System example, for both the code as well as the writeup on this wiki.

1. Define the Service

Create the bundle ca.on.senecac.scs.sudoku

1.1 Create SudokuGenerator.java
package ca.on.senecac.scs.sudoku;

/**
 * Defines the interface to the Sudoku Generator OSGi-based
 * application.
 *
 * @author John Selmys
 *
 */
public interface SudokuGenerator {
    void generate(int row, int col);
}
1.2 Define the MANIFEST.MF for the service
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Sudoku
Bundle-SymbolicName: ca.on.senecac.scs.sudoku
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: ca.on.senecac.scs.sudoku

2. Define the Service Provider

Create the bundle ca.on.senecac.scs.sudoku.provider

2.1 Create SudokuActivator.java
package ca.on.senecac.scs.sudoku.provider;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

import ca.on.senecac.scs.sudoku.SudokuGenerator;
import ca.on.senecac.scs.sudoku.provider.internals.*;

/**
 * The Sudoku Generator provider bundle is registered here.
 *
 * @author John Selmys
 *
 */
public class SudokuActivator implements BundleActivator {

    private static BundleContext context;
     
    static BundleContext getContext() {
        return context;
    }

    public void start(BundleContext bundleContext) throws Exception {
        SudokuActivator.context = bundleContext;
         
        SudokuGenerator sg = new SimpleSudokuGenerator();
        context.registerService(SudokuGenerator.class.getName(), sg, null);
        System.out.println("Sudoku Generator Registered !");
    }

   
    public void stop(BundleContext context) throws Exception {
        SudokuActivator.context = null;
        System.out.println("Sudoku Generator Stopped !");

    }

}
2.2 Create SimpleSudokuGenerator.java
package ca.on.senecac.scs.sudoku.provider.internals;
import java.util.Random;
import ca.on.senecac.scs.sudoku.SudokuGenerator;

/**
 * The code to generate a Sudoku grid is here. Note that the
 * method "generate(int,int)" is recursive.
 *
 * @author John Selmys
 *
 */
public class SimpleSudokuGenerator implements SudokuGenerator {
    static Grid g = new Grid(9);
    static int counter = 0;
   
    /**
     * The computation of a random valid (9x9) Sudoku puzzle
     * starts here.
     */
    public void generate(int row, int col) {
        if(row > 8) {
            puzzle();
            System.out.println("All Done!");
            g.display();
            System.exit(0);
        }
        int[] a = {1,2,3,4,5,6,7,8,9};
        get9(a);
        for(int i=0;i<9;i++) {
            int m = a[i];
            counter++;
            if(available(row,col,m)) {
                g.setGrid(row, col, m);
                if(col < 8) {
                    generate(row,col+1);
                } else {
                    generate(row+1,0);
                }
            }
        }
        if(col > 0) {
            col--;
        } else {
            col = 8;
            row--;
        }
        g.setGrid(row, col, 0);
    }
   
    /**
     * Make a 3x3 Sudoku puzzle and place into grid.
     *
     */
    static void puzzle() {
        for(int r=0;r<7;r+=3) {
            for(int c=0;c<7;c+=3) {
                int x[] = {1,2,3,4,5,6,7,8,9};
                get9(x);
                for(int row=0;row<3;row++) {
                    for(int col=0;col<3;col++) {
                        int R = row+r;
                        int C = col+c;
                        int p = row * 3 + col + 1;
                        if(p==x[0] || p==x[1] || p==x[2] || p==x[3]) {
                            g.setGrid(R, C, 0);
                        }
                    }
                }
            }
        }
    }

    /**
     * Checks the grid to see if value 'm' can be placed at
     * position (r,c)
     *
     */
    static boolean available(int r, int c, int m) {
        for(int col=0;col<9;col++) {
            if(g.getGrid(r, col) == m) return false;
        }
        for(int row=0;row<9;row++) {
            if(g.getGrid(row, c) == m) return false;
        }
        r = r/3 * 3;
        c = c/3 * 3;
        for(int row=0;row<3;row++) {
            for(int col=0;col<3;col++) {
                int R = row + r;
                int C = col + c;
                if(g.getGrid(R, C) == m) return false;
            }
        }
        return true;
    }
   
    /**
     * Get an array containing integers [1..9] in random order.
     *
     */
    static void get9(int a[]) {
        Random rand = new Random();
        for(int i=8; i>0; i--) {
            int r = rand.nextInt(i);
            int t = a[i];
            a[i] = a[r];
            a[r] = t;
        }
        for(int k=0;k<9;k++)System.out.print(a[k]+"  ");
        System.out.println(" ");
    }


}
2.3 Create Grid.java
package ca.on.senecac.scs.sudoku.provider.internals;

/**
 * The Sudoku Grid class contains the results of the Sudoku
 * Generator.
 *
 * @author John Selmys
 *
 */
public class Grid {
    int[][] grid;

    Grid(int side) {
        grid = new int[side][side];
        for (int i=0;i<9;i++)
            for(int j=0;j<9;j++)
                grid[i][j] = 0;
    }
   
    void display() {
        for (int i=0;i<9;i++) {
            for(int j=0;j<9;j++)
                System.out.print(grid[i][j]+" ");
            System.out.println();
        }
    }
   
    void setGrid(int r, int c, int v) {
        grid[r][c] = v;
    }
   
    int getGrid(int r, int c) {
        return grid[r][c];
    }
}