Click here to Skip to main content
15,896,526 members
Articles / Programming Languages / C++/CLI

Sudoku Solver

Rate me:
Please Sign up or sign in to vote.
2.40/5 (5 votes)
7 Feb 2007CPOL3 min read 77.1K   1.9K   18  
Sudoku solver using a backtracking algorithm
#include "StdAfx.h"
#include "sudokugame.h"
#include<iostream>
using namespace std;
sudokugame::sudokugame(void)
{
	int i,j;
	m=gcnew array<int^,2>(9,9);
	sol=new LIST<int**>;
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			m[i,j]=gcnew int;
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			*m[i,j]=0;
	Application::Run(display=gcnew Form1(this));
}

sudokugame::~sudokugame(void)
{
	clearsoln();
}

int sudokugame::mat(int i, int j,bool assign,int val)
{
	if(assign)
	{
		*m[i,j]=val;
	}
	return *m[i,j];
}
bool sudokugame::backtrack(int &i,int &j,bool rq[9][9],barrs l[9][9])
{
	l[i][j].repr();
	do{
		if(i==0&&j==0)	return 0;
		if(j==0)	i--,j=8;
		else	j--;
	}while(!rq[i][j]);
	if(j==0)	i--,j=8;
	else	j--;
	return 1;
}

int sudokugame::evaluate()
{
	clearsoln();
	bool rq[9][9];//2D array indicating corresponding elements of m that need to be evaluated
	int i,j,k//used as iterators
		,r=0//return value(number of solutions found and inserted to sol
		,li=8,lj=8//(li,lj)->indices of last position in m to be evaluated
		;
	if(!valid(0))	return 0;
	if(valid(1))	return 1;
	//evaluate rq
	for(i=0;i<9;i++){
		for(j=0;j<9;j++){
			rq[i][j]=!(*m[i,j]);
		}
	}
	barrs l[9][9];//array of lists, each list containing allowable digits at corresponding position in m, as per following logic
	int *de1,*de2,*de3;
	for(i=0;i<9;i++){
		for(j=0;j<9;j++){
			if(rq[i][j]){
				//add to l[i][j] all elements from 1 through 9 not present in either row or column or grid of m[i,j]
				for(k=1;k<10;k++){
					*m[i,j]=k;
					if(validsarr(de3=row(i),0)){
						if(validsarr(de1=col(j),0)){
							if(validsarr(de2=grd(grid(i,j)),0))
								l[i][j].ins(k);
							delete[] de2;
						}
						delete[] de1;
					}
					delete[] de3;
				}
				l[i][j].calf();//make l[i][j] ready to process
				*m[i,j]=0;
			}
		}
	}
	//evaluate (li,lj)
	bool f=1;
	for(i=8;i>=0;i--){
		for(j=8;j>=0;j--){
			if(rq[i][j]){
				li=i;
				lj=j;
				f=0;
				break;
			}
		}
		if(!f)	break;
	}
	//evaluate
	for(i=0;i<9;i++){
		for(j=0;j<9;j++){
			if(rq[i][j]){
				do{
					*m[i,j]=l[i][j].prel();//make next guess for m[i,j]
					if(!(*m[i,j])){//if no guess left, then backtrack
						if(!backtrack(i,j,rq,l))	return r;
						break;
					}
					//check to see if the last guess made leaves m in a valid state
					if(validsarr(de3=row(i),0)){
						if(validsarr(de1=col(j),0)){
							if(validsarr(de2=grd(grid(i,j)),0)){
								delete[] de3;
								delete[] de1;
								delete[] de2;
								break;//last guess made leaves m in valid state
							}
							delete[] de2;
						}
						delete[] de1;
					}
					delete[] de3;
				}while(1);
				if(i==li&&j==lj){//if position just filled was last one to be filled to give a solution
					if(addtosoln()){//add present state of m to sol;if succesful in doing so
						r++;
						if(r==LIMIT)	return LIMIT;
						if(!backtrack(i,j,rq,l))	return r;
					}
					else
						return -1;//indicate error(though more solutions exist then present in sol, and though number of solutions in sol is less than LIMIT,we could'nt add to sol,probably due to memory shortage)
				}
			}
		}
	}
	return r;
}
int* sudokugame::row(int n)
{
	int *r;
	r=new int[9];
	for(int i=0;i<9;i++)
		r[i]=*m[n,i];
	return r;
}
int* sudokugame::col(int n)
{
	int *r;
	r=new int[9];
	for(int i=0;i<9;i++)
		r[i]=*m[i,n];
	return r;
}
int* sudokugame::grd(int n)
{
	int *r;
	r=new int[9];
	int radd=3*(n/3),cadd=3*(n%3);
	for(int i=0;i<3;i++)
		for(int j=0;j<3;j++)
			r[3*i+j]=Convert::ToInt32(m[radd+i,cadd+j]);
	return r;
}
int sudokugame::validsarr(int arr[9],bool comp)
{
	int r[10]={0},f=1,f1=1,i;
	for(i=0;i<9;i++)
		r[arr[i]]++;
	for(i=1;i<10;i++)
		if(r[i]!=1)
		{
			f=0;
			if(r[i]>1)
				f1=0;
		}
	if(comp)	return f;
	return f1;
}
int sudokugame::valid(bool comp)
{
	int *a;
	for(int i=0;i<9;i++)
	{
		if(!validsarr(a=row(i),comp))
		{
			delete[]a;
			return 0;
		}
		delete[] a;
		if(!validsarr(a=col(i),comp))
		{
			delete[]a;
			return 0;
		}
		delete[] a;
		if(!validsarr(a=grd(i),comp))
		{
			delete[]a ;
			return 0;
		}
		delete[] a;
	}
	return 1;
}
int sudokugame::grid(int i, int j)
{
	return (i/3)*3+j/3;
}
int sudokugame::addtosoln()
{
	int **s,i,j;
	try
	{
		s=new int*[9];
		for(i=0;i<9;i++)
			s[i]=new int[9];
	}
	catch(...)
	{
		return 0;
	}
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			s[i][j]=*m[i,j];
	sol->frontins(s);
	return 1;
}
int sudokugame::prsoln()
{
	int **p=sol->prel();
	if(!p)
	{
		sol->repr();
		p=sol->prel();
	}
	int i,j;
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			try
			{
				*m[i,j]=p[i][j];
			}
			catch(...)
			{
			}
	return sol->pos(p);
}
void sudokugame::clearsoln()
{
	int **d,i;
	while(!sol->isempty())
	{
		d=sol->frontel();
		for(i=0;i<9;i++)
		{
			delete[] d[i];
		}
		delete[] d;
		sol->frontdel();
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Yahoo!
India India
I've studied info. sc. engg. from Sir MVIT, Bangalore.

I'm interested in programming.

Some of my technical blogs:

http://perl-blog.kbsbng.com/
http://java-blog.kbsbng.com/

I also enjoy writing some webpages such as http://sites.google.com/site/plantencyclopedia/

More about me at http://www.kbsbng.com and http://blog.kbsbng.com.

Comments and Discussions