3.9 KiB
3.9 KiB
###Sudoku Generator
Generates a random (but valid) Sudoku puzzle
program SudoGen : display[17, 17]
const
char CHR_EMPTY := ' ';
char CHR_UNKNOWN := ' ';
char CHR_BORDER := '#';
char CHR_INTERSECT := '+';
char CHR_HORZ := '-';
char CHR_VERT := '|';
begin
Init();
Create();
Obfuscate();
end
void Init()
var
int x, y;
begin
for (y = 0; y < DISPLAY_HEIGHT; y++) do
for (x = 0; x < DISPLAY_WIDTH; x++) do
if (x % 2 == 0 && y % 2 == 0) then
display[x, y] = CHR_EMPTY;
elsif ((x + 1) % 6 == 0 || (y + 1) % 6 == 0) then
display[x, y] = CHR_BORDER;
elsif ((x - 1) % 2 == 0 && (y - 1) % 2 == 0) then
display[x, y] = CHR_INTERSECT;
elsif ((x - 1) % 2 == 0 && y % 2 == 0) then
display[x, y] = CHR_VERT;
elsif (x % 2 == 0 && (y - 1) % 2 == 0) then
display[x, y] = CHR_HORZ;
end
end
end
end
bool Create()
var
int x, y;
int on;
int n;
begin
if (!IsValid()) then
return false;
end
on = rand[3] % 9;
for (y = 0; y < 9; y++) do
for (x = 0; x < 9; x++) do
if (display[x * 2, y * 2] == CHR_EMPTY) then
for (n = 0; n < 9; n++) do
display[x * 2, y * 2] = (char)((int)'1' + ((n + on) % 9));
if (Create()) then
return true;
end
display[x * 2, y * 2] = CHR_EMPTY;
end
return false;
end
end
end
return true;
end
bool IsValid()
var
int x, y;
int p;
int c;
int[9] vals;
begin
// Rows
for (y = 0; y < 9; y++) do
for (p = 0; p < 9; ) do
vals[p++] = 0;
end
for (x = 0; x < 9; x++) do
if (display[x * 2, y * 2] != CHR_EMPTY) then
vals[((int)display[x * 2, y * 2]) - ((int)'1')]++;
end
end
for (p = 0; p < 9; p++) do
if (vals[p] > 1) then
return false;
end
end
end
// Cols
for (x = 0; x < 9; x++) do
for (p = 0; p < 9; ) do
vals[p++] = 0;
end
for (y = 0; y < 9; y++) do
if (display[x * 2, y * 2] != CHR_EMPTY) then
vals[((int)display[x * 2, y * 2]) - ((int)'1')]++;
end
end
for (p = 0; p < 9; p++) do
if (vals[p] > 1) then
return false;
end
end
end
// Rects
for (c = 0; c < 9; c++) do
for (p = 0; p < 9; ) do
vals[p++] = 0;
end
for (x = (c / 3) * 3; x < (c / 3 + 1) * 3; x++) do
for (y = (c % 3) * 3; y < (c % 3 + 1) * 3; y++) do
if (display[x * 2, y * 2] != CHR_EMPTY) then
vals[((int)display[x * 2, y * 2]) - ((int)'1')]++;
end
end
end
for (p = 0; p < 9; p++) do
if (vals[p] > 1) then
return false;
end
end
end
return true;
end
bool isRemovable(int x, int y)
var
int v;
int p;
int rx, ry;
bool[9] vals;
begin
v = ((int)display[x * 2, y * 2]) - ((int)'1');
for (p = 0; p < 9; ) do
vals[p++] = false;
end
// Row
for (p = 0; p < 9; p++) do
if (display[p * 2, y * 2] != CHR_UNKNOWN) then
vals[((int)display[p * 2, y * 2]) - ((int)'1')] = true;
end
end
// Col
for (p = 0; p < 9; p++) do
if (display[x * 2, p * 2] != CHR_UNKNOWN) then
vals[((int)display[x * 2, p * 2]) - ((int)'1')] = true;
end
end
//Rect
for (rx = (x / 3) * 3; rx < (x / 3 + 1) * 3; rx++) do
for (ry = (y / 3) * 3; ry < (y / 3 + 1) * 3; ry++) do
if (display[rx * 2, rx * 2] != CHR_UNKNOWN) then
vals[((int)display[rx * 2, ry * 2]) - ((int)'1')] = true;
end
end
end
//Test
for (p = 0; p < 9; p++) do
if (!vals[p] && p != v) then
return false;
end
end
return true;
end
void Obfuscate()
var
int ox, oy;
int x, y;
begin
ox = rand[3];
oy = rand[3];
for (x = ox; x < ox + 9; x++) do
for (y = oy; y < oy + 9; y++) do
if (display[(x % 9) * 2, (y % 9) * 2] != CHR_UNKNOWN) then
if (isRemovable(x % 9, y % 9)) then
display[(x % 9) * 2, (y % 9) * 2] = CHR_UNKNOWN;
Obfuscate();
return;
end
end
end
end
return;
end
end
Note: This and other examples are included in the BefunGen download