Difference between revisions of "Sudoku Generator (Example for the OSGi Lab)"
(→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 19: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];
}
}