Yes, I understand all that. Where exactly does it go into an infinite loop?

One technique I use when debugging (and not using a debugger for whatever reason) is to liberally sprinkly printf statements around the code, saying where it is up to, what the value of certain variables is, and that can be very helpful.

What's the point of the e array in assign()? e[k]=k-1 if k>=0 and k<=8, so you could just do "k-1" instead of "e[k]".

If I were debugging then as an example I might put at the start of assign():
int assign(int i,int j,int k)//assigns first valid no. from array e[9]
{                            //to b[i][j], if no no. is possible returns 1
printf("Entering assign(i=%d, j=%d, k=%d)\n",i,j,k);
	int e[9]={1,2,3,4,5,6,7,8,9};
	if(k==9)return 1;
One and two letter variable names make it impossible to understand what your code is doing. Yes, YOU know what k, ce, a, b, i, cs and so on all do, but that doesn't help anyone else. Often a code reviewer can work out what code is supposed to do (even if it isn't doing that) if meaningful variable names are used, whereas if the variable names are meaningless then just like if I were to use meaningless one/two letter word replacements, u wd he a cu wa he fk I' gi on bu. OK, you CAN work out what that means, but imagine if my whole update were written like that, or worse still if the letters bore no relation to the word at all. Uq nr kk jl mk ni ni ni pp rz!