First, the topic Description:
(nine problem) in a 3x3 nine, 1-8 of these 8 digits and a space are randomly placed in one of the squares, as shown in Figure 1-1. This problem is now required: Adjust the nine to the form shown in Figure 1-1 on the right. The rule of adjustment is that you can only translate a number adjacent to a space (top, bottom, or left, right) into a space at a time. Try programming to solve this problem.
(Figure 1-1)
Second, the topic Analysis:
Nine problem is one of the classical problems in artificial intelligence, the problem is in the 3x3 checkerboard, put 8 lattice number, the rest is not put to empty, each move only and adjacent space exchange number. The program automatically generates the initial state of the problem, converting it into a target arrangement through a series of exchange actions (conversion from Figure 1-2 to figure 1-3 below).
|
|
| (Figure 1-2) |
(Figure 1-3) |
In the nine problem, the random permutations produced by the program are two possible, and the two cannot be set up at the same time, that is, odd permutations and even permutations. We can put a random array of arrays from left to right from top to bottom with a one-dimensional array, as shown in Figure 1-2 above we can represent {8,7,1,5,2,6,3,4,0} where 0 represents a space.
In this array we first compute the result that it can rearrange, and the formula is:
∑(F(X))=Y,其中F(X)
is a number in front of him that is smaller than the number of numbers, Y is odd and even number has a solution. Then we can solve the result of the array above.
F(8)=0;
F(7)=0;
F(1)=0;
F(5)=1;
F(2)=1;
F(6)=3;
F(3)=2;
F(4)=3;
Y=0+0+0+1+1+3+2+3=10
Y=10 is an even number, so his rearrangement is the result of Figure 1-3, and if the result is an odd rearrangement the result is the rightmost row of figure 1-1.
Third, the algorithm analysis
The solution to the nine problem is to swap the space (0) position until the target position is reached. The graphic representation is:
(Figure 3-1)
To get the best you need to use breadth first search, the nine so ranked 9! Species, that is, 362880 kinds of row, the amount of data is very large, I use the breadth of search, you need to remember the arrangement of each node, if the use of array records will occupy a lot of memory, we put the data to the appropriate compression. Saved using a DWORD, the compression form is each digit uses 3 bits to represent, like this is the 3x9=27 byte, because 8 binary representation form 1000, cannot use 3 bits to represent, I use a trick is to be 8 to represent bit 000, then uses the extra 5 words to represent 8 place, Can be expressed in a DWORD. Moving data one by one with shift and/or operation is faster than multiplication speed. Several results are defined to store traversal to the results and save the optimal path after the search completes.
The class structure is as follows:
Class Cninegird
{
Public
struct placelist
{
DWORD Place;
Placelist* left;
placelist* right;
};
struct SCANBUF
{
DWORD Place;
int Scanid;
};
struct PathList
{
unsigned char path[9];
};
Private
Placelist *m_pplacelist;
Scanbuf *m_pscanbuf;
RECT M_rresetbutton;
RECT M_rautobutton;
Public
int m_ipathsize;
clock_t M_itime;
UINT M_istepcount;
unsigned char m_itargetchess[9];
unsigned char m_ichess[9];
HWND M_hclientwin;
PathList *m_ppathlist;
BOOL M_bautorun;
Private
inline bool Addtree (DWORD Place, placelist*& parent);
void Freetree (placelist*& parent);
inline void Arraytodword (unsigned char *array, DWORD & Data);
inline void Dwordtoarray (DWORD data, unsigned char *array);
inline bool movechess (unsigned char *array, int way);
BOOL Estimateuncoil (unsigned char *array);
void GetPath (UINT depth);
Public
void movechess (int way);
BOOL Computefeel ();
void Activeshaw (HWND hview);
void Drawgird (HDC HDC, RECT clientrect);
void Drawchess (HDC HDC, RECT clientrect);
void Reset ();
void Onbutton (Point pnt, HWND Hview);
Public
Cninegird ();
~cninegird ();
};The computed random random array uses the vector template to use the random_shuffle (,) function to disrupt the array data and calculate what the target result is. Code:
void Cninegird::reset ()
{
if (m_bautorun) return;
Vector<int> vs;
int i;
for (i = 1; i < 9; i + +)
Vs.push_back (i);
Vs.push_back (0);
Random_shuffle (Vs.begin (), Vs.end ());
Random_shuffle (Vs.begin (), Vs.end ());
for (i = 0; i < 9; i + +)
{
M_ichess[i] = vs[i];
}
if (! Estimateuncoil (m_ichess))
{
unsigned char array[9] = {1,2,3,8,0,4,7,6,5};
memcpy (m_itargetchess, array, 9);
}
Else
{
unsigned char array[9] = {1,2,3,4,5,6,7,8,0};
memcpy (m_itargetchess, array, 9);
}
M_istepcount = 0;
} Data compression function implementation:
inline void Cninegird::arraytodword (unsigned char *array, dword& data)
{
unsigned char night = 0;< br> for (int i = 0; I < 9 i + +)
{
if (array[i] = = 8)
{
Night = (unsigned char) i;< br> break;
}
{
Array[night] = 0;
data = 0;
data = (DWORD) ((DWORD) array[0] << 29 | (DWORD) array[1] << 26 |
(DWORD) array[2] << 23 | (DWORD) array[3] << 20 |
(DWORD) array[4] << 17 | (DWORD) array[5] << 14 |
(DWORD) array[6] << 11 | (DWORD) array[7] << 8 |
(DWORD) array[8] << 5 | night);
Array[night] = 8;
} Decompression is good with compression instead, unzip the code:
inline void CNineGird::DwordToArray(DWORD data , unsigned char *array)
{
unsigned char chtem;
for ( int i = 0 ; i < 9 ; i ++)
{
chtem = (unsigned char)(data >> (32 - (i + 1) * 3) & 0x00000007);
array[i] = chtem;
}
chtem = (unsigned char)(data & 0x0000001F);
array[chtem] = 8;
}