Digital Puzzle (eight digital) dynamic demonstration of solution process

Source: Internet
Author: User
This article turns from: http://www.qqgb.com/Program/VC/VCarithmetic/Program_55328.html First, the topic Description:
  
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. It is now required to implement this problem by adjusting it 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:
  
This is one of the classic problems of artificial intelligence, the problem is that in the 3x3 checkerboard, put 8 lattice number, the rest is not put to empty, each move can only be 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 this problem, the random permutations produced by the program are two possible, and the two can not be set up at the same time, that is, odd arrangement and even arrangement. You 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 represent spaces.
In this array we first compute the result that it can rearrange, and the formula is:

∑ (f (x)) =y, where F (x)

is a number preceded by the number of small numbers,y is odd and even when there is a solution. (Eight digital problem whether there is a solution to the decision)

The array above can solve its results.
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 even, so its 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 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, so there are 9 nine. Species, that is, 362880 kinds of row, the amount of data is very large, the use of breadth search, you need to remember the arrangement of each node, if the use of array records will occupy a lot of memory, can be appropriate compression of data. Saved using a DWORD, the compression form is 3 bits per digit, so that is 3x9=27 byte, because of the binary representation of 8 1000, can not be expressed in 3 bits, using a trick is to 8 as 000, and then use the extra 5 words to indicate 8 location, 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 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;
for (int i = 0; i < 9; i + +)
{
if (array[i] = = 8)
{
Night = (unsigned char) i;
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 the exact opposite of compression, unzip the code:

inline void Cninegird::D wordtoarray (DWORD data, unsigned char *array)
{
unsigned char chtem;
for (int i = 0; i < 9; i + +)
{
Chtem = (unsigned char) (data >> (i + 1) * 3) & 0x00000007);
Array[i] = Chtem;
}
Chtem = (unsigned char) (data & 0x0000001f);
Array[chtem] = 8;
}

Because the amount of scalable data is very large, plus at the time of the save use is the DWORD type, each step data are recorded in a sorted binary tree, according to from small to large from left to the arrangement, search time and each search will be nearly million times the form of nearly n Times Square times, Declaring several functions used in loops as inline functions and searching for inserted data at the time of insertion will not repeat in the tree to speed up the overall speed. Binary Tree Insert code:

inline bool Cninegird::addtree (DWORD Place, placelist*& parent)
{
if (parent = NULL)
{
Parent = new Placelist ();
Parent->left = Parent->right = NULL;
Parent->place = place;
return true;
}
if (Parent->place = place)
return false;

if (Parent->place > place)
{
Return Addtree (place, parent->right);
}
Return Addtree (place, parent->left);
}

Code that evaluates to an odd-numbered or even-numbered arrangement:

BOOL Cninegird::estimateuncoil (unsigned char *array)
{
int sun = 0;
for (int i = 0; i < 8; i + +)
{
for (int j = 0; J < 9; J + +)
{
if (Array[j]!= 0)
{
if (array[j] = = i +1)
Break
if (Array[j] < i + 1)
sun++;
}
}
}
if (Sun% 2 = 0)
return true;
Else
return false;
}

Move to the space bit of the code is relatively simple, as long as the calculation will be moved to the outside of the box can be, and in the moving time to calculate whether it is already the target results, which is used to hand-move to the user is to give a hint, code:

inline bool cninegird::movechess (unsigned char *array, int way)
{
int zero, Chang;
BOOL Moveok = false;
for (zero = 0; zero < 9; zero + +)
{
if (Array[zero] = = 0)
Break
}
Point PNT;
Pnt.x = zero% 3;
pnt.y = Int (ZERO/3);
Switch (way)
{
Case 0://up
if (Pnt.y + 1 < 3)
{
Chang = (pnt.y + 1) * 3 + pnt.x;
Array[zero] = Array[chang];
Array[chang] = 0;
Moveok = true;
}
Break
Case 1://down
if (Pnt.y-1 >-1)
{
Chang = (pnt.y-1) * 3 + pnt.x;
Array[zero] = Array[chang];
Array[chang] = 0;
Moveok = true;
}
Break
Case 2://left
if (Pnt.x + 1 < 3)
{
Chang = pnt.y * 3 + pnt.x + 1;
Array[zero] = Array[chang];
Array[chang] = 0;
Moveok = true;
}
Break
Case 3://right
if (Pnt.x-1 >-1)
{
Chang = pnt.y * 3 + pnt.x-1;
Array[zero] = Array[chang];
Array[chang] = 0;
Moveok = true;
}
Break
}
if (Moveok &&!m_bautorun)
{
M_istepcount + +;

DWORD Temp1, Temp2;
Arraytodword (array, TEMP1);
Arraytodword (m_itargetchess, TEMP2);
if (Temp1 = = Temp2)
{
MessageBox (NULL, "You're so smart to get it done!", "^_^", 0);
}
}
return moveok;
}

In the search of breadth, the index of the parent node is recorded in the sub node, so when the target is arranged, the optimal search path can be obtained as long as the reverse search is done from the sub node. Use variable m_ipathsize to record the total number of steps, the specific function code:

void Cninegird::getpath (UINT depth)
{
int now = 0, maxpos = 100;
UINT ParentID;
if (m_ppathlist!= NULL)
{
Delete[] m_ppathlist;
}
M_ppathlist = new Pathlist[maxpos];
ParentID = m_pscanbuf[depth]. Scanid;

Dwordtoarray (M_pscanbuf[depth]. Place, M_ppathlist[++now]. Path);

while (ParentID!=-1)
{
if (now = = Maxpos)
{
Maxpos + 10;
PathList * temlist = new Pathlist[maxpos];
memcpy (temlist, m_ppathlist, sizeof (pathlist) * (maxpos-10));
Delete[] m_ppathlist;
M_ppathlist = temlist;
}
Dwordtoarray (M_pscanbuf[parentid]. Place, M_ppathlist[++now]. Path);
ParentID = M_pscanbuf[parentid]. Scanid;
}
M_ipathsize = Now;
}

Dynamically arranged demo functions are the simplest, and in order for the main form to be refreshed in time, a thread can be paused with the Slee (UINT) function when the main form refresh is needed. Code:

unsigned __stdcall movechessthread (LPVOID pparam)
{
Cninegird * Pgird = (Cninegird *) Pparam;
RECT RECT;
Pgird->m_istepcount = 0;
:: GetClientRect (Pgird->m_hclientwin, &rect);
for (int i = pgird->m_ipathsize i > 0; i--)
{
memcpy (Pgird->m_ichess, pgird->m_ppathlist[i). Path, 9);
Pgird->m_istepcount + +;
InvalidateRect (Pgird->m_hclientwin, &rect, false);
Sleep (300);
}
Char msg[100];
sprintf (MSG, "^_^! It's done.!\r\n calculated steps in%d milliseconds ", pgird->m_itime);
MessageBox (NULL, MSG, "~_~", 0);
Pgird->m_bautorun = false;
return 0L;
}

Finally, the principle of the search function is introduced, first get the source array, convert it to a DWORD, compared to the target, if the same completion, the difference is to exchange data and space position, add a binary tree, search the next result, until there is no step to go, in search just find the location of the child position, So until you find the target result, the function:

BOOL Cninegird::computefeel ()
{
unsigned char *array = m_ichess;
UINT i;
const int MAXSIZE = 362880;
unsigned char temparray[9];

DWORD Target, Fountain, parent, ParentID = 0, child = 1;
Arraytodword (m_itargetchess, target);
Arraytodword (array, fountain);
if (fountain = = target)
{
return false;
}
if (m_pscanbuf!= NULL)
{
Delete[] M_pscanbuf;
}
M_pscanbuf = new Scanbuf[maxsize];
Addtree (fountain, m_pplacelist);
m_pscanbuf[0]. place = Fountain;
m_pscanbuf[0]. Scanid =-1;
clock_t Tim = Clock ();
while (ParentID < MAXSIZE && Child < MAXSIZE)
{
Parent = M_pscanbuf[parentid]. Place;
for (i = 0; i < 4; i + +)//0:up, 1:down, 2:left,3:right
{
Dwordtoarray (parent, Temparray);
if (movechess (temparray,i))//whether to move successfully
{
Arraytodword (Temparray, Fountain);
if (Addtree (Fountain, m_pplacelist))//join number of searches
{
m_pscanbuf[Child]. place = Fountain;
m_pscanbuf[Child]. Scanid = ParentID;
if (fountain = = target)//Whether the result is found
{
M_itime = Clock ()-Tim;
GetPath (child);//calculation path
Freetree (m_pplacelist);
Delete[] M_pscanbuf;
M_pscanbuf = NULL;
return true;
}
Child + +;
}
}
}//For I
parentid++;
}
M_itime = Clock ()-Tim;

Freetree (m_pplacelist);
Delete[] M_pscanbuf;
M_pscanbuf = NULL;
return false;
}

The description of the important function ends; The following is the result of the program's operation and the results of the operation:

Source:

file: 9Gg Ird_src.zip
size: 33KB
Download: download

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.