您的当前位置:首页详解javascript九宫格图片随机打乱位置的实现方法

详解javascript九宫格图片随机打乱位置的实现方法

2023-12-01 来源:热乐宠物网
这篇文章主要为大家详细介绍了javascript九宫格图片随机打乱位置的实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

今天就做个九宫格的简易拼图,最让我头疼的就是点击开始打乱图片位置。一开始在百度查看相关博客,走了很多弯路。最后看了众多的例子,自己写了个方法。

点击开始可以达到随机打乱图片位置的效果,如下

小编还为您整理了以下内容,可能对您也有帮助:

如何用c#实现九宫格拼图?

九宫格拼图教程一步一步图解如下:

1. 九宫格拼图的起点比较简单,我们一定要从外围开始拼。1号和2号拼图比较容易就可以归位,第三块拼图相对较难。

2. 我们将3号拼图移动到正确位置的相邻位置,此时不能直接将3号拼图归位。我们要先将拼图全部下移,为1好拼图留下空间。

3. 1号拼图有空间后,就可以直接向右移动,然后2号拼图跟着1号拼图移动。这样3号拼图周围就没有干扰的拼图,可以为3号拼图提供换位的空间。

4. 直接以3号拼图为中心,将3块拼图进行顺时针或者逆时针的换位,直到3号拼图进入到正确的位置。随后2号拼图和1号拼图原路返回。

5. 完成前3号拼图的复原后,我们就可以先放置4号拼图。5号拼图类似3号拼图,放置到正确位置的附近后,为1号拼图留下空间。

6.完成后,将所有拼图原路返回进行复原,这样九宫格拼图的外围就全部完成。内部剩下的3个拼图,直接旋转,就可以恢复到正确的位置。

将1张图采用3*3的方式,分成9部分,将第3行3列的小图取出,打乱剩余的8个部分的位置,然后开始游戏,将打乱的8个位置的图片通过左右挪动的方式复位,成功后,将第9张图归位,即游戏结束。.

编程时同样采取了这个逻辑,将切割后的小图片存放入容器中,然后随机拜访,给每一张小图设置点击事件,点击后可根据所缺空隙进行挪动,直到全部正确归位为止,我引入了计时功能,可以记录完成游戏时间。

九宫格拼图·求此问题解法~~思路~代码都可~~就是关于其还原算法的·急~在线等~多谢哈

http://www.cublog.cn/u/8780/showart.php?id=163291

在一个3×3的九宫中有1-8这8个数及一个空格随机的摆放在其中的格子里,如图1-1所示。现在要求实现这个问题:将其调整为如图1-1右图所示的形式。调整的规则是:每次只能将与空格(上、下、或左、右)相邻的一个数字平移到空格中。试编程实现这一问题的求解。

(图1-1)

二、题目分析:

这是人工智能中的经典难题之一,问题是在3×3方格棋盘中,放8格数,剩下的没有放到的为空,每次移动只能是和相邻的空格交换数。程序自动产生问题的初始状态,通过一系列交换动作将其转换成目标排列(如下图1-2到图1-3的转换)。

(图1-2) (图1-3)

该问题中,程序产生的随机排列转换成目标共有两种可能,而且这两种不可能同时成立,也就是奇数排列和偶数排列。可以把一个随机排列的数组从左到右从上到下用一个一维数组表示,如上图1-2我们就可以表示成{8,7,1,5,2,6,3,4,0}其中0代表空格。

在这个数组中我们首先计算它能够重排列出来的结果,公式就是:

∑(F(X))=Y,其中F(X)

是一个数前面比这个数小的数的个数,Y为奇数和偶数时各有一种解法。(八数码问题是否有解的判定 )

上面的数组可以解出它的结果。

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是偶数,所以其重排列就是如图1-3的结果,如果加起来的结果是奇数重排的结果就是如图1-1最右边的排法。

三、算法分析

求解方法就是交换空格(0)位置,直至到达目标位置为止。图形表示就是:

(图3-1)

要想得到最优的就需要使用广度优先搜索,九宫的所以排列有9!种,也就是362880种排法,数据量是非常大的,使用广度搜索,需要记住每一个结点的排列形式,要是用数组记录的话会占用很多的内存,可以把数据进行适当的压缩。使用DWORD形式保存,压缩形式是每个数字用3位表示,这样就是3×9=27个字节,由于8的二进制表示形式1000,不能用3位表示,使用了一个小技巧就是将8表示为000,然后用多出来的5个字表示8所在的位置,就可以用DWORD表示了。用移位和或操作将数据逐个移入,比乘法速度要快点。定义了几个结果来存储遍历到了结果和搜索完成后保存最优路径。

类结构如下:

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();

};

计算随机随机数组使用了vector模板用random_shuffle(,)函数来打乱数组数据,并计算目标结果是什么。代码:

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;

}

数据压缩函数实现:

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;

}

解压缩时跟压缩正好相反,解压代码:

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;

}

由于可扩展的数据量非常的大,加上在保存的时候使用的是DWORD类型,将每一步数据都记录在一个排序二叉树中,按从小到大从左到有的排列,搜索的时候跟每次搜索将近万次的形式比较快几乎是N次方倍,把几个在循环中用到的函数声明为内联函数,并在插入的时候同时搜索插入的数据会不会在树中有重复来加快总体速度。二叉树插入代码:

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);

}

计算结果是奇数排列还是偶数排列的代码:

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;

}

移动到空格位的代码比较简单,只要计算是否会移动到框外面就可以了,并在移动的时候顺便计算一下是不是已经是目标结果,这是用来给用户手工移动是给与提示用的,代码:

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 , "你真聪明这么快就搞定了!" , "^_^" , 0);

}

}

return moveok;

}

在进行广度搜索时候,将父结点所在的数组索引记录在子结点中了,所以得到目标排列的时候,只要从子结点逆向搜索就可以得到最优搜索路径了。用变量m_iPathsize来记录总步数,具体函数代码:

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;

}

动态排列的演示函数最简单了,为了让主窗体有及时刷新的机会,启动了一个线程在需要主窗体刷新的时候,用Slee(UINT)函数来暂停一下线程就可以了。代码:

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 , "^_^ ! 搞定了!\r\n计算步骤用时%d毫秒" , pGird->m_iTime);

MessageBox(NULL , msg , "~_~" , 0);

pGird->m_bAutoRun = false;

return 0L;

}

最后介绍一下搜索函数的原理,首先得到源数组,将其转换成DWORD型,与目标比较,如果相同完成,不同就交换一下数据和空格位置,加入二叉树,搜索下一个结果,直到没有步可走了,在搜索刚刚搜索到的位置的子位置,这样直到找到目标结果为止,函数:

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)) //是否移动成功

{

ArrayToDword(temparray , fountain);

if (AddTree(fountain, m_pPlaceList)) //加入搜索数

{

m_pScanbuf[ child ].Place = fountain;

m_pScanbuf[ child ].ScanID = parentID;

if (fountain == target) //是否找到结果

{

m_iTime = clock() - tim;

GetPath(child);//计算路径

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;

}

重要函数的介绍结束;下面是程序的运行结果和运算结果:

做九宫格的技巧与方法

做九宫格的技巧与方法如下:

排它法:观察各行各列,若个位置其他数字都填不了,那么就可以填写剩下的数字。基本交叉。

排除法:利用同一排和列的三个九宫内,两个相同数字找出另一个相同数字的位置。

联除法:在并排的三个九宫格中的两排寻找到一些相同的数字,然后再利用九宫格得出另一排中该数字位置,该方法非常适用于中高级数独。

九宫格是一款数字游戏,起源于河图洛书,九宫格游戏规则:1至9九个数字,横竖都有3个格,思考怎么使每行、每列两个对角线上的三数之和都等于15。

九宫格除了有上面的玩法以外,还有口诀可以参考,具体口诀如下:

1.戴九履一,右三左七,二四为肩,六八为足。

口诀解释:通常要求1-9在九宫格上填数,做到行、列、对角线之和相等,且数字不重复。解答时其实要有个口诀:2、4为肩;6、8为足;上9下1;左7右3。

2.一居上行正*,依次斜填切莫忘;上出框时向下放,右出框时向左放;排重便在下格填,右上排重一个样。

做九宫格的技巧与方法

做九宫格的技巧与方法如下:

排它法:观察各行各列,若个位置其他数字都填不了,那么就可以填写剩下的数字。基本交叉。

排除法:利用同一排和列的三个九宫内,两个相同数字找出另一个相同数字的位置。

联除法:在并排的三个九宫格中的两排寻找到一些相同的数字,然后再利用九宫格得出另一排中该数字位置,该方法非常适用于中高级数独。

九宫格是一款数字游戏,起源于河图洛书,九宫格游戏规则:1至9九个数字,横竖都有3个格,思考怎么使每行、每列两个对角线上的三数之和都等于15。

九宫格除了有上面的玩法以外,还有口诀可以参考,具体口诀如下:

1.戴九履一,右三左七,二四为肩,六八为足。

口诀解释:通常要求1-9在九宫格上填数,做到行、列、对角线之和相等,且数字不重复。解答时其实要有个口诀:2、4为肩;6、8为足;上9下1;左7右3。

2.一居上行正*,依次斜填切莫忘;上出框时向下放,右出框时向左放;排重便在下格填,右上排重一个样。

九宫格图片制作方法

九宫格图片制作方法如下:

1、打开PPT或者WPS演示文稿。

2、选择“插入,形状”,选择矩形框,在文档的空白处插入一个矩形框。

3、将矩形框的形状调整为正方形,然后复制8个,再将9个正方形摆成九宫格。

4、全部选中9个正方形,然后组合成一个形状。

5、往这个形状中插入图片即可完成九宫格图片制作。

使用九宫格切图快捷指令有以下优点:

快速:使用九宫格切图快捷指令可以快速准确地切出九宫格图片,提高工作效率。

准确:九宫格切图快捷指令可以设置需要切出的区域,保证切出的图片准确无误。

方便:九宫格切图快捷指令可以直接将生成的图片保存到本地,方便在项目中使用。

易用:九宫格切图快捷指令的操作简单易懂,即使是初学者也可以轻松上手。

九宫格游戏规则就是用1至9九个数字,横竖都有3个格,思考怎么使每行、每列两个对角线上的三数之和都等于15。这个游戏不仅仅考验人的数字推理能力,也同时考验了人的思维逻辑能力。

九宫格游戏对人们的思维锻炼有着极大的作用,从古时起人们便意识到九宫的教育意义。千百年来影响巨大,在文学、影视中都曾出现过。九宫格最早叫“洛书”,现在也叫“幻方” 。

在《射雕英雄传》中黄蓉曾破解九宫格,口诀:戴九履一,左三右七,二四有肩,八六为足,五居。

还有口诀:“一居上行正,依次斜填切莫忘;上出框时向下放,右出框时向左放;排重便在下格填,右上排重一个样。” 这口诀不仅适用于九宫,也适用于推广的奇数九宫,如五五图,七七图等等。

如何制作九宫格图片

1、首先将在ps中构建一个1800*1800画布,然后单击“文件-新建”。

2、宽度和高度更改为1800*1800的选项。

3、然后选择鼠标将照片拖入ps的页面中。

4、Ctrlt将图片调整为与画布相同的大小,调整它以单击上面的选标记。

5、选择鼠标单击“切片工具”的功能选项。

6、选择图像并右键单击“分区切片”的功能选项。

7、选择纵向3级,垂直3级。

8、选择鼠标点击另存为网络格式。

9、使用鼠标选择整个图像并将其更改为jpg格式。

10、保存所选位置,然后点击“保存”。完成。

注意事项:

“九宫格”是一种构图方法。

摄影中的构图,常用到的是三分法。即在摄影构图时,将画面的横向和纵向平均分成三份。

而三分法线条交叉处叫做趣味中心。当我们在观察一副照片时,目光会优先被吸引到趣味中心的位置,所以在拍照时我们尽可能将主体事物安排在趣味中心的附近。

三分法既可以横向划分,也可以竖向划分。当两种都使用时,即采用“井”字型构图时,这重构图方法就是九宫格构图。

九宫格构图属于黄金分割式的一种形式。就是把画面平均分成九块,在中心块上四个角的点,用任意一点的位置来安排主体位置。

热乐宠物网还为您提供以下相关内容希望对您有帮助:

九宫格拼图·求此问题解法~~思路~代码都可~~就是关于其还原算法的·急...

求解方法就是交换空格(0)位置,直至到达目标位置为止。图形表示就是:(图3-1) 要想得到最优的就需要使用广度优先搜索,九宫的所以排列有9!种,也就是362880种排法,数据量是非常大的,使用广度搜索,需要记住每一个结点的排列形式,要是用数组记录的话会占用很多的内存,可以把数据进行适当的压缩。使用DWORD形式保存,压缩...

如何用c#实现九宫格拼图?

1. 九宫格拼图的起点比较简单,我们一定要从外围开始拼。1号和2号拼图比较容易就可以归位,第三块拼图相对较难。2. 我们将3号拼图移动到正确位置的相邻位置,此时不能直接将3号拼图归位。我们要先将拼图全部下移,为1好拼图留下空间。3. 1号拼图有空间后,就可以直接向右移动,然后2号拼图跟着1号...

...结构体 二维数组等知识点,用C语言的知识,九宫格风景照拼图,用VC6....

通过 LoadImageA 加载图像 GetBitmapDimensionEx 获取图片尺寸;输入划分的行和列号,初始化 grid 数组;通过Bitbits从原图复制图像在窗口显示 响应WM_LBUTTONDOWN、WM_MOUSEMOVE,WM_LBUTTONUP消息,实现图块的拖动。放开时,交换拖动块和目标块的行列坐标。对拖动计数;判断每块的实际位置和原图位置是否一致...

九宫格图片拼图怎么拼?

1. 九宫格拼图的起点比较简单,我们一定要从外围开始拼。1号和2号拼图比较容易就可以归位,第三块拼图相对较难。2. 我们将3号拼图移动到正确位置的相邻位置,此时不能直接将3号拼图归位。我们要先将拼图全部下移,为1好拼图留下空间。3. 1号拼图有空间后,就可以直接向右移动,然后2号拼图跟着1号...

九宫格图怎么拼?

1. 九宫格拼图的起点比较简单,我们一定要从外围开始拼。1号和2号拼图比较容易就可以归位,第三块拼图相对较难。2. 我们将3号拼图移动到正确位置的相邻位置,此时不能直接将3号拼图归位。我们要先将拼图全部下移,为1好拼图留下空间。3. 1号拼图有空间后,就可以直接向右移动,然后2号拼图跟着1号...

拼图插画图片叶子-九宫格图片拼图怎么拼?

将1张图采用3*3的方式,分成9部分,将第3行3列的小图取出,打乱剩余的8个部分的位置,然后开始游戏,将打乱的8个位置的图片通过左右挪动的方式复位,成功后,将第9张图归位,即游戏结束。.编程时同样采取了这个逻辑,将切割后的小图片存放入容器中,然后随机拜访,给每一张小图设置点击事件,点击后可根据所...

Top