开发日志: 开发日志是按日期写的,主要的一些说明请看最后。19:15 2006-08-19:思量了很久,还是尝试写一下这个程序。但目前就写一个游戏模式,而不是解决方案。20:45 2006-08-19:一直在研究透明的效果怎么搞,因为没有网络,也没有带书回来,只能想去反编译程序找API了,但是这里的机子里的反编译程序也不是图形界面,dumpbin与dumppe,虽然是很强的命令行工具,但还是令人比较郁闷。目前机子里有透明效果的程序好像就是千千静听与现在用的万能五笔了,但更为郁闷的是,根本无法从反汇编的程序中找到API,千千静听反编译有1M多,万能五笔更可怕,7M多,我先反编译的千千,一看开头,我就愣了,push esp mov ebp,esp,开头两条指令好像我在书里看过是防静态汇编或跟踪云云,头就大了,二话不说,删。万能五笔我就看了看,最后只好看它们的导入表,万能五笔好点导入表小,千千静听太多了,看不过来,还有一些导入表Masm32v8.2根本就找不到链接库,更别说测试了。21:52 2006-08-19:终于找到了,好像就是SetBkMode,我原来一直误区在alpha关键字里。经过很多的测试,可以确定这个API就是对图形透明的函数了。累死我了,只摸到一点门,以后有空再继续。PS:在找这个API的过程中,还是学到了不少的东西。10:55 2006-08-21:无法使用setBkMode,郁闷,主要是我不会用,也不知道应该怎么用。16:15 2006-08-22:今天我应该吐血N升!!!!我终于深刻地认识到C与C++里的变量、数组是一个多美妙事情,今天下午我花了N个小时在分析数据在内存中的存放顺序以调整我的程序结构。开始有点怀念C了。呜呜~~~ 而且一个十分细小的口算错误,竟让我一直卡在一个点怎么想都想不通,N小时后,天见怜,让我猛然发现了数据竟然在最后一个错掉了。吐血吐血吐血吐血吐血吐血吐血吐血吐血吐血吐血吐血21:47 2006-08-22:但究竟还是解决了一些问题,按捺不住高兴啊。又做了好久了,今天就做到这里,是一个纪念。我把后、左、下三个面画出来了,因为画的程序还可以精减,但我现在不准备做这个工作,嘿嘿,先把立体图画出来再考虑吧。14:06 2006-08-23:目前只画了三个面,又出了点问题,正在解决ing...18:11 2006-08-23:问题的出现是因为有重复计算,最后发现了,郁闷。16:44 2006-08-24:今天把六个面全部画完了,但是效果并不是很理想,不好看,郁闷。因为dialog无法处理加速键的问题,所以我把dialog改成window了,多了一些处理过程,但在窗口大小改变的时候,在随机次改变后,颜色发生变化以及在窗口外画图了,郁闷。正在解决ing...22:20 2006-08-24:为了不再发生上面所说的错误,因为我也不知道到底是哪里出错了,所以我把窗口限制大小了。就是禁止调整大小罢了。另外,这里又要记录一个错误,我把info数组放到.const里,左转操作的时候老是出错,调整了好久,程序没错,就是想不到哪里错了,后来又要靠灵光一闪,对了.const,马上拉到.data里,立即正确了。嘿嘿。现在左转操作反应慢,好像send paint消息没什么作用。21:21 2006-08-26:在我快要放弃的时候,终于尝试成功了一个函数:GetDC。这是一个很简单的API,但之前我却没有去注意它,因为它太平凡,结果证明它的用处。我试了几天,用了一切可想的办法,如createDC...不是毫无作用就是无限循环。用了GetDC,终于解决了在WM_PAINT消息中画面不更新的问题了,哇哈哈。当然,在WM_PAINT里我没有忘记让DC有效起来,原来用v..Rect,后来想想,又用beginPaint了,嘿嘿,画面的背景就回去了,而不是刚刚的黑色。 过几天把12个转向的函数写完以后就开始着手看看用两个窗口层叠,上层透明来实现画图,嘿嘿,这样画出来的魔方才能叫魔方,我看了一下还没有实现这个技术的程序,当方块转动无序后,画面就是一片花,太难看了。对了,昨天没写日志,因为到姐那里上网查到了一个好API,窗口透明,嘿嘿,这回是真家伙。13:31 2006-08-27:试验了几次以后,发现些规律,又多学习了几个方面的知识,两个窗口,主与子,只有主窗口的消息函数才能使用,所以子窗口的消息函数完全可以省掉,而且因为消息函数里使用的窗口句柄都是局部变量,对同时处理与分别处理两个窗口的消息很有好处哦。 然后就是知道了对于我的单线程的话,还是用postmessage比较好而不是sendmessage以等待处理。15:01 2006-08-27:今天把魔方的六个面分别画正常了,不再采用原来的上层画法。六个面的绘画一切正常。 新加一个功能,用pageup、pagedown、home、end来控制上层窗口的透明度17:39 2006-08-27:主要的一些绘画功能都完成了,现在正在精减程序,靠,房间里竟然有一只蚊子,咬死我了,郁闷。停会。18:20 2006-08-27:转动程序的函数已经精减完毕。 这里提一下程序的资源消耗问题,当前机器是:AMD Athlon XP 1600+ 1.41G 程序的计算量是很小的,一般的操作都能维持在1%的使用率,就是可以忽略不计,就算是按住绘画命令不放,CPU的使用率也是在60%以下。可见计算量很小。 而显卡:GeForce 2 MX 64M的,因为都是画图,所以可能工作都给它承担了,所以看不出来实际绘画需要的计算量是多少,到时回到学校后应该可以看一下。 窗口只实现了绘图同步,其它还没有同步,这个问题以后再解决。16:44 2006-08-28:今天把保存当前信息的一些功能写了,原来以为会很麻烦,结果因为我写程序一向比较抠门,写出来的程序一向是力求“小”,所以又把写INI文件的函数处理了一下,很爽,不过多计算了几次,但原始变量就省了很多哦。16:21 2006-08-30:今天把路径的保存这个功能写了一下,原来在电脑前坐了好久,老是写不成功,结果没电了,在纸上划两下,结果就出来了。看来我还是适合在纸上演算东西。 因为是对上一步的验证算法,所以,虽然说完全没有错误,但是功能的实现上还是有些瑕疵的,我会再想办法把它做好的。现在能想到的办法就是再加一个last以验证再上一步的过程。 而要让这个程序成为一个正式的游戏还有一个功能没有实现,就是随机打乱魔方的排布,以让用户自己寻找解决之道。 对了,绘图的模块还没有精减,这里记一下,免得忘记。21:20 2006-08-30:新加了一个last1的变量,记录倒数第二次的操作类型,嘿嘿,我在想,如果以后再加上其它6个转向,达到全部的18转,那写程序真是太恐怖了。不过好在我尽量地把程序模块化了。而且,我也不准备去实现18转了,只不过我在现在的程序里尽量给以后还是有可能续写的18转考虑自由的空间了已经。 现在貌似完成了,对于操作步骤的come back不会要求严格步步顺序了,至少对前两步的判定使之更加“人性化”了。21:41 2006-08-30:把_draw_fRect函数删掉了,因为用不着了,唉,那可是我花了一个晚上想出来的连点画线的方法啊,可惜现在用不上了。努力精减draw模块...22:50 2006-08-30:嘿嘿,模块化设计就是好,draw模块很快就精减完了,函数多了,但程序小了,程序由原来的17.5K飚减到14.5K,整整3K啊,我这个工作就节省了3K的程序空间啊,因为节省空间而增加的运算量所付出的代价是很小的,与这个3K比起来就忽略不计了,再说了,现在的CPU很快了,这点运算量几乎就可以为0。13:37 2006-08-31:设置了游戏级别,低中高及自定义。刚刚发现一个思路错误,导致路径记录时出现覆盖。正在想办法...14:18 2006-08-31:成了,嘿嘿,还是要在纸上分析实在,我在纸上一划拉,就把_load函数写好了。高级的过程,50步,完全可以按照步骤提示还原掉,嘿嘿。 但是至于步骤提示怎么还原魔方,我还不想去写,因为如果很快就知道怎么解决游戏的话,无论什么游戏都不会再长久地吸引玩家的兴趣了。只不过我会在“使用说明”里提一下。14:34 2006-08-31:最后我看这个程序先告一个段落吧,把它的版本改为1.0,嗯。这是迄今为止我写过的最长的程序了,丫的全都是一键一键打出来的。源文件很大,但写出来的程序很小,这就是我的风格。21:25 2006-9-3:我回来了,经过检验,图形的绘画也基本不需要消耗什么资源,至此,可以证明这个程序做得不错,嘿嘿,自得一下。。。 使用说明: 魔方(ver 0.1) 使用说明加速鍵: ▲12个转动方向: W ↑ 7 9 A S D ← ↓ → 1 3 (小键盘) ▲透明度调整: Home(不透明) PageUp(渐不透明) End(完全透明) PageDown(渐透明) ▲上下层窗口分离:随意拖动窗口load提示:从后面往前读!:D 1:AA A:A":→ 2:←← B:←#:S 3:WW C:W$:↓ 4:↑↑ D:↑%:3 5:11 E:1&:9 6:77 F:7照着步骤做,嘿嘿,就能还原魔方。 mofang.asm .586 .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc include shell32.incinclude gdi32.incinclude masm32.incincludelib user32.lib includelib kernel32.lib includelib shell32.libincludelib gdi32.libincludelib masm32.libinclude C:masm32macrosMACROS.ASMinclude mofang.inc ;一些变量常数在这里.code_colors proc LOCAL @tmp:LOGBRUSH ;先设定六种颜色笔刷的句柄以及黑色刷与NULL刷 invoke CreateSolidBrush,_red mov hBrush,eax invoke CreateSolidBrush,_yellow mov hBrush[4],eax invoke CreateSolidBrush,_cheng mov hBrush[8],eax invoke CreateSolidBrush,_white mov hBrush[0ch],eax invoke CreateSolidBrush,_blue mov hBrush[10h],eax invoke CreateSolidBrush,_green mov hBrush[14h],eax invoke CreateSolidBrush,_black mov hBrush[18h],eax push 1 pop @tmp.lbStyle push 0000ff00h pop @tmp.lbColor push 5 POP @tmp.lbHatch invoke CreateBrushIndirect,addr @tmp mov hBrush[1ch],eax ;六色画笔与黑笔&点刷 invoke CreatePen,PS_SOLID,1,_red mov hPen[00h],eax invoke CreatePen,PS_SOLID,1,_yellow mov hPen[04h],eax invoke CreatePen,PS_SOLID,1,_cheng mov hPen[08h],eax invoke CreatePen,PS_SOLID,1,_white mov hPen[0ch],eax invoke CreatePen,PS_SOLID,1,_blue mov hPen[10h],eax invoke CreatePen,PS_SOLID,1,_green mov hPen[14h],eax invoke CreatePen,PS_SOLID,1,_black mov hPen[18h],eax invoke CreatePen,PS_DOT,1,NULL mov hPen[1ch],eax ;粗的画笔刷以及虚线刷 invoke CreatePen,PS_SOLID,3,_red mov hPen2[00h],eax invoke CreatePen,PS_SOLID,3,_yellow mov hPen2[04h],eax invoke CreatePen,PS_SOLID,3,_cheng mov hPen2[08h],eax invoke CreatePen,PS_SOLID,3,_white mov hPen2[0ch],eax invoke CreatePen,PS_SOLID,3,_blue mov hPen2[10h],eax invoke CreatePen,PS_SOLID,3,_green mov hPen2[14h],eax invoke CreatePen,PS_SOLID,3,_black mov hPen2[18h],eax invoke CreatePen,PS_DASH,3,NULL mov hPen2[1ch],eax ret_colors endp_init proc LOCAL @tmp push ebx push esi push edi ;写键名 KeyInfo == info01,0,info02,0,...info27,0 xor ebx,ebx xor esi,esi .while esi < 28 inc esi invoke lstrcpy,addr KeyInfo[ebx],addr szKeyInfo invoke wsprintf,addr tmp_str,addr fmt_info,esi invoke lstrcat,addr KeyInfo[ebx],addr tmp_str add ebx,7 .endw ;取得透明度,以取得透明度开始,如果透明度都取不到,说明文件不存在,那么下面就不要忙了。 invoke GetPrivateProfileInt,addr szSecName,addr szKeyAlpha,0,addr szFileName .if eax != 0 mov nAlpha,eax ;取得当前魔方信息 xor ebx,ebx xor esi,esi .while esi < 28 inc esi invoke GetPrivateProfileInt,addr szSecName,addr KeyInfo[ebx],0,addr szFileName .if eax != 0 mov info[esi*4-4],eax .endif add ebx,7 .endw ;取得当前路径计数 invoke GetPrivateProfileInt,addr szSecName,addr szKeyCout_l,0,addr szFileName .if eax != 0 mov coutl,eax inc eax inc eax mov @tmp,eax invoke GetPrivateProfileString,addr szSecName,addr szKeyLoad,addr load,addr load,@tmp,addr szFileName mov eax,coutl .if eax > 1 mov ecx,eax dec eax lea esi,load[eax] lodsb movzx eax,al mov last1,eax mov eax,ecx .endif lea esi,load[eax] lodsb movzx eax,al mov last,eax ;定义最近一次操作的类型 .endif .endif pop edi pop esi pop ebx ret_init endp_out proc pushad ;保存当前信息 ;当前透明度 invoke wsprintf,addr tmp_str,addr fmt_num,nAlpha invoke WritePrivateProfileString,addr szSecName,addr szKeyAlpha,addr tmp_str,addr szFileName ;当前魔方信息 xor ebx,ebx xor esi,esi .while esi < 28 inc esi invoke wsprintf,addr tmp_str,addr fmt_num,info[esi*4-4] invoke WritePrivateProfileString,addr szSecName,addr KeyInfo[ebx],addr tmp_str,addr szFileName add ebx,7 .endw ;当前路径计数 invoke wsprintf,addr tmp_str,addr fmt_num,coutl invoke WritePrivateProfileString,addr szSecName,addr szKeyCout_l,addr tmp_str,addr szFileName mov ecx,coutl mov eax,last lea edi,load[ecx] stosb xor eax,eax stosb ;当前路径 invoke WritePrivateProfileString,addr szSecName,addr szKeyLoad,addr load,addr szFileName popad ret_out endp_load proc @last push ecx push edx push esi push edi mov eax,@last and eax,0fh mov ecx,last and ecx,0fh xor eax,ecx ;该次操作是否与上次操作相同 .if eax == 0 ;如果两次操作类型相同@@: mov eax,@last and eax,0f0h sub eax,010h mov ecx,last add eax,ecx .if eax >50h ;如果超出了范围,一是重复,一是已经还原 sub eax,40h .if eax < 20h ;如果操作已经还原成了上步操作 mov eax,coutl dec eax mov coutl,eax dec eax .if eax >= 0 ;既然还原上步操作,上上步的操作也要还原而对于上上步操作的还原,也要考虑一些因素 lea esi,load[eax] lodsb movzx eax,al mov last1,eax lodsb movzx eax,al .else mov eax,7eh mov last1,eax .endif .endif .endif .else ;如果两次操作类型不同 mov eax,last mov ecx,last1 and ecx,0fh and eax,0fh .if eax > ecx dec eax .else dec ecx .endif .if eax == ecx ;上面的操作判定前面两次的操作是否“邻近”,如果邻近,才允许操作置换 and eax,01h .if eax != 0 ;如果操作邻近,而且是被允许的,则置换 mov ecx,@last ;这里,就要判定该次操作是否与上上次的操作类型相符 mov eax,last1 and ecx,0fh and eax,0fh xor eax,ecx .if eax == 0 ;如果相符的话,那么把last与last1操作置换一下 mov ecx,coutl dec ecx lea edi,load[ecx] mov eax,last mov ecx,eax stosb mov eax,last1 mov last1,ecx mov last,eax jmp @B ;这些条件都符合才能置换last与last1,并再记录 .endif .endif .endif ;一旦有条件不符合就说明是全新操作,记录操作 mov ecx,coutl mov eax,last mov last1,eax lea edi,load[ecx] stosb inc ecx mov coutl,ecx mov eax,@last .endif mov last,eax ;把这一句拿出来的原因是我觉得把三句节省为一句,也好,毕竟是对mem的操作嘛 pop edi pop esi pop edx pop ecx ret_load endp;------------产生随机数的通用程序iRand proc uses ecx edx @first:DWORD, @second:DWORD invoke GetTickCount ; 取得随机数种子,当然,可用别的方法代替 mov edx,eax invoke nrandom,@second add edx,eax invoke nrandom,@second add edx,eax invoke nrandom,@second add edx,eax mov ecx, 23 ; X = ecx = 23 mul ecx ; eax = eax * X add eax, 7 ; eax = eax + Y (Y = 7) mov ecx, @second ; ecx = 上限 sub ecx, @first ; ecx = 上限 - 下限 inc ecx ; Z = ecx + 1 (得到了范围) xor edx, edx ; edx = 0 div ecx ; eax = eax mod Z (余数在edx里面) add edx, @first ; 修正产生的随机数的范围 mov eax, edx ; eax = Rand_Number retiRand endp include draw.asminclude action.asm_breakit proc @cout LOCAL @lpfunc[8]:DWORD mov eax,offset _action1 mov @lpfunc[00h],eax mov eax,offset _action3 mov @lpfunc[04h],eax mov eax,offset _action5 mov @lpfunc[08h],eax mov eax,offset _action7 mov @lpfunc[0ch],eax mov eax,offset _action9 mov @lpfunc[10h],eax mov eax,offset _action11 mov @lpfunc[14h],eax invoke _resetMofang mov eax,coutl .while eax < @cout invoke iRand,0,5 push 1 shl eax,1 shl eax,1 call @lpfunc[eax] mov eax,coutl .endw invoke PostMessage,hWin,WM_PAINT,NULL,NULL invoke PostMessage,hWinMain,WM_PAINT,NULL,NULL ret_breakit endp_DLG_proc proc hWnd,wMsg,wParam,lParam mov eax,wMsg .if eax == WM_COMMAND mov eax,wParam .if ax == IDOK invoke GetDlgItemInt,hWnd,IDC_NUM,NULL,TRUE mov _Result,eax invoke EndDialog,hWnd,NULL .endif .elseif eax == WM_CLOSE mov _Result,0 invoke EndDialog,hWnd,NULL .endif xor eax,eax ret _DLG_proc endp;------------主消息_MainProc proc hWnd,wMsg,wParam,lParam mov eax,wMsg .if eax == WM_PAINT mov eax,hWnd .if eax == hWinMain invoke _initMofang,1 ;统一作初始 .else invoke _initMofang,0 .endif .elseif eax == WM_COMMAND mov eax,wParam .if (ax > IDC_1-1) &&(ax < IDC_12+1) .if ax == IDC_1 invoke _action1,1 .elseif ax == IDC_2 invoke _action1,3 .elseif ax == IDC_3 invoke _action3,1 .elseif ax == IDC_4 invoke _action3,3 .elseif ax == IDC_5 invoke _action5,1 .elseif ax == IDC_6 invoke _action5,3 .elseif ax == IDC_7 invoke _action7,1 .elseif ax == IDC_8 invoke _action7,3 .elseif ax == IDC_9 invoke _action9,1 .elseif ax == IDC_10 invoke _action9,3 .elseif ax == IDC_11 invoke _action11,1 .elseif ax == IDC_12 invoke _action11,3 ;以上一段是转动 .endif invoke PostMessage,hWinMain,WM_PAINT,NULL,NULL invoke PostMessage,hWin,WM_PAINT,NULL,NULL .elseif (ax > IDC_pageup-1) && (ax < IDC_home+1) .if ax ==IDC_pageup mov eax,nAlpha add eax,08h .if eax > 0ffh push 0ffh .else push eax .endif pop nAlpha .elseif ax ==IDC_pagedown mov eax,nAlpha sub eax,08h .if eax < 0 push 0 .else push eax .endif pop nAlpha .elseif ax ==IDC_end push 0 pop nAlpha .elseif ax ==IDC_home push 0ffh pop nAlpha ;以上一段是透明 .endif invoke SetLayeredWindowAttributes,hWinMain,0eeh,nAlpha,2 .elseif ax == IDC_EXIT invoke PostMessage,hWnd,WM_CLOSE,NULL,NULL .elseif ax == IDC_reset invoke _resetMofang .elseif ax == IDC_copyright MsgBox hWinMain,addr szCopyRight,"版权声明",MB_OK or MB_ICONINFORMATION .elseif ax == IDC_help szText @szHelpName,"使用说明.txt" invoke ShellExecute,0,0,addr @szHelpName,0,0,SW_SHOW .if eax < 31 MsgBox hWinMain," 使用说明 文件丢失!",NULL,MB_OK or MB_ICONWARNING .endif .elseif (ax >IDC_Low-1) && (ax < IDC_Self+1) .if ax == IDC_Low push 10 .elseif ax == IDC_Mid push 25 .elseif ax == IDC_High push 50 .else invoke DialogBoxParam,hInstance,DLG_MAIN,hWinMain,addr _DLG_proc,NULL mov eax,_Result .if eax == 0 jmp @F .endif push eax .endif call _breakit .endif .elseif eax == WM_CLOSE invoke _out invoke DestroyWindow,hWnd invoke PostQuitMessage,NULL .else @@: invoke DefWindowProc,hWnd,wMsg,wParam,lParam ret .endif xor eax,eax ret_MainProc endp_MAIN proc LOCAL @stWndClass:WNDCLASSEX invoke _colors ;先设置一些笔刷以备后用 invoke _init invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass invoke LoadCursor,0,IDC_ARROW mov @stWndClass.hCursor,eax push hInstance pop @stWndClass.hInstance mov @stWndClass.cbSize,sizeof WNDCLASSEX mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW mov @stWndClass.lpfnWndProc,offset _MainProc mov @stWndClass.hbrBackground,2 ;窗口背景颜色 mov @stWndClass.lpszClassName,offset szClassName invoke RegisterClassEx,addr @stWndClass invoke LoadMenu,hInstance,IDM_MAIN ;菜单 mov hMenu,eax invoke CreateWindowEx,WS_EX_DLGMODALFRAME, offset szClassName,offset _name, WS_OVERLAPPED OR WS_CAPTION OR WS_SYSMENU OR WS_MINIMIZEBOX,;这里我禁了trickframe,不想让改变大小 MY_X,MY_Y,MY_W,MY_H, ;位置,大小 NULL,hMenu,hInstance,NULL mov hWin,eax invoke LoadIcon,hInstance,ICO_MAIN ;图标 mov hIcon,eax invoke SendMessage,hWin,WM_SETICON,ICON_BIG,hIcon invoke ShowWindow,hWin,SW_SHOWNORMAL invoke UpdateWindow,hWin ;下面这个是子窗口 mov @stWndClass.lpfnWndProc,NULL ;不准备再加个消息处理,也不能重复消息处理 invoke CreateWindowEx,WS_EX_DLGMODALFRAME or 80000h, ;这里加了一个WS_EX_LAYERED的属性 offset szClassName,offset _name, WS_OVERLAPPED OR WS_CAPTION OR WS_SYSMENU OR WS_MINIMIZEBOX, MY_X,MY_Y,MY_W,MY_H, hWin,hMenu,hInstance,NULL mov hWinMain,eax invoke SendMessage,hWinMain,WM_SETICON,ICON_BIG,hIcon invoke ShowWindow,hWinMain,SW_SHOWNORMAL invoke UpdateWindow,hWinMain ;上面一坨注册窗口的过程比diglog麻烦多了 invoke LoadAccelerators,hInstance,IDA_MAIN mov hAcc,eax ;注册了加速键,嘿嘿 invoke SetLayeredWindowAttributes,hWinMain,0eeh,nAlpha,2 ;非要设置透明度 .while TRUE invoke GetMessage,addr @stMsg,NULL,0,0 .break .if eax == 0 invoke TranslateAccelerator,hWinMain,hAcc,addr @stMsg ;其实无论传给哪个窗口都是统一消息处理 .if !eax invoke TranslateMessage,addr @stMsg invoke DispatchMessage,addr @stMsg .endif .endw xor eax,eax ret_MAIN endpstart: invoke GetModuleHandle,NULL mov hInstance,eax invoke _MAIN invoke ExitProcess,NULLend start action.asm _Point_script proc @pos ;对原点进行定位 mov eax,@pos .if eax == 1 invoke GetClientRect,hWinMain,addr @rect_now .else invoke GetClientRect,hWin,addr @rect_now .endif mov eax,@rect_now.right sub eax,@rect_now.left shr eax,1 add eax,@rect_now.left .if eax >0 mov Z_X,eax .endif mov ecx,@rect_now.bottom sub ecx,@rect_now.top shr ecx,1 add ecx,@rect_now.top .if eax >0 mov Z_Y,ecx .endif ;可以对高与宽进行运算设定,但现在不做运算 push 20 pop p_h push 48 pop p_w mov eax,p_w ;计算3倍量 shl eax,1 add eax,p_w mov p_w3,eax mov eax,p_h shl eax,1 add eax,p_h mov p_h3,eax ret_Point_script endp_draw_Block proc @nshr xor edi,edi mov @i,edi .while ebx < 108 mov eax,info[ebx] mov ecx,@nshr shr eax,cl and eax,7 .if eax != 7 invoke SelectObject,_hdc,hBrush[eax*4] invoke Polygon,_hdc,addr @p[edi],4 add edi,10h inc @i .endif add ebx,4 .break .if @i == 3 .endw ret_draw_Block endp;左右两个侧边_draw_side proc @X,@Y,@nshr xor ebx,ebx mov eax,@X mov @p,eax mov @p[18h],eax mov @p[20h],eax mov @p[38h],eax mov eax,@Y mov @p[4],eax add eax,p_w mov @p[1ch],eax add eax,p_w mov @p[24h],eax add eax,p_w mov @p[3ch],eax mov eax,@p[0] add eax,p_h mov @p[8],eax mov @p[10h],eax mov @p[28h],eax mov @p[30h],eax mov eax,@p[4] sub eax,p_h mov @p[0ch],eax add eax,p_w mov @p[14h],eax add eax,p_w mov @p[2ch],eax add eax,p_w mov @p[34h],eax invoke _draw_Block,@nshr mov eax,@p[8] add eax,p_h mov @p,eax mov @p[18h],eax mov @p[20h],eax mov @p[38h],eax mov eax,@p[0ch] sub eax,p_h mov @p[4],eax add eax,p_w mov @p[1ch],eax add eax,p_w mov @p[24h],eax add eax,p_w mov @p[3ch],eax invoke _draw_Block,@nshr mov eax,@p[0] add eax,p_h mov @p[8],eax mov @p[10h],eax mov @p[28h],eax mov @p[30h],eax mov eax,@p[4] sub eax,p_h mov @p[0ch],eax add eax,p_w mov @p[14h],eax add eax,p_w mov @p[2ch],eax add eax,p_w mov @p[34h],eax invoke _draw_Block,@nshr ret_draw_side endp_draw_r proc push 6 mov ecx,p_h3 mov edx,p_w3 mov eax,Z_Y add eax,ecx sub eax,edx ;Y push eax mov ecx,p_h3 mov edx,p_w3 mov eax,Z_X sub eax,ecx add eax,edx push eax ;X call _draw_side ret_draw_r endp_draw_l proc ;参数需要反入栈 push 12 mov ecx,p_h3 mov eax,Z_Y add eax,ecx sub eax,p_w3 push eax ;Y mov ecx,p_h3 mov eax,Z_X sub eax,ecx push eax ;这是X call _draw_side ret_draw_l endp_draw_updown proc @X,@Y,@nshr xor ebx,ebx mov eax,@Y mov @p[4],eax mov @p[1ch],eax mov @p[24h],eax mov @p[3ch],eax mov eax,@X mov @p[0],eax add eax,p_w mov @p[18h],eax add eax,p_w mov @p[20h],eax add eax,p_w mov @p[38h],eax mov eax,@p[4] sub eax,p_h mov @p[0ch],eax mov @p[14h],eax mov @p[2ch],eax mov @p[34h],eax mov eax,@p[0] add eax,p_h mov @p[8],eax add eax,p_w mov @p[10h],eax add eax,p_w mov @p[28h],eax add eax,p_w mov @p[30h],eax invoke _draw_Block,@nshr mov eax,@p[0ch] sub eax,p_h mov @p[4h],eax mov @p[1ch],eax mov @p[24h],eax mov @p[3ch],eax mov eax,@p[8] add eax,p_h mov @p[0],eax add eax,p_w mov @p[18h],eax add eax,p_w mov @p[20h],eax add eax,p_w mov @p[38h],eax invoke _draw_Block,@nshr mov eax,@p[4] sub eax,p_h mov @p[0ch],eax mov @p[14h],eax mov @p[2ch],eax mov @p[34h],eax mov eax,@p[0] add eax,p_h mov @p[8],eax add eax,p_w mov @p[10h],eax add eax,p_w mov @p[28h],eax add eax,p_w mov @p[30h],eax invoke _draw_Block,@nshr ret ret_draw_updown endp_draw_u proc push 0 mov ecx,p_h3 mov eax,Z_Y add eax,ecx mov ecx,p_w3 sub eax,ecx push eax ;Y mov ecx,p_h3 mov eax,Z_X sub eax,ecx push eax ;X call _draw_updown ret_draw_u endp_draw_d proc push 3 mov eax,p_h3 add eax,Z_Y push eax ;Y mov eax,p_h3 mov edx,Z_X sub edx,eax mov eax,edx push eax ;X call _draw_updown ret_draw_d endp_draw_face proc @X,@Y,@nshr xor ebx,ebx mov eax,@X mov @p,eax mov @p[8],eax add eax,p_w mov @p[10h],eax mov @p[18h],eax add eax,p_w mov @p[20h],eax mov @p[28h],eax add eax,p_w mov @p[30h],eax mov @p[38h],eax mov ecx,@Y mov @p[4],ecx mov @p[1ch],ecx mov @p[24h],ecx mov @p[3ch],ecx add ecx,p_w mov @p[0ch],ecx mov @p[14h],ecx mov @p[2ch],ecx mov @p[34h],ecx invoke _draw_Block,@nshr mov ecx,p_w shl ecx,1 add ecx,@p[4] mov @p[4],ecx mov @p[1ch],ecx mov @p[24h],ecx mov @p[3ch],ecx invoke _draw_Block,@nshr mov ecx,p_w shl ecx,1 add ecx,@p[0ch] mov @p[0ch],ecx mov @p[14h],ecx mov @p[2ch],ecx mov @p[34h],ecx invoke _draw_Block,@nshr ret_draw_face endp_draw_f proc push 15 mov ecx,p_h3 mov eax,Z_Y add eax,ecx mov ecx,p_w3 sub eax,ecx push eax ;Y mov ecx,p_h3 mov eax,Z_X sub eax,ecx push eax ;X call _draw_face ret_draw_f endp_draw_b proc push 9 mov ecx,p_w3 mov eax,Z_Y sub eax,ecx push eax ;Y mov eax,Z_X push eax ;X call _draw_face ret_draw_b endp_draw_3side proc @lpfunc1,@lpfunc2,@lpfunc3,@hWnd push esi push edi push ebx invoke BeginPaint,@hWnd,addr @ps invoke EndPaint,@hWnd,addr @ps invoke GetDC,@hWnd mov _hdc,eax call @lpfunc1 call @lpfunc2 call @lpfunc3 invoke ReleaseDC,@hWnd,_hdc pop esi pop edi pop ebx ret_draw_3side endp_drawf proc push hWinMain mov eax,offset _draw_f push eax mov eax,offset _draw_u push eax mov eax,offset _draw_r push eax call _draw_3side ret_drawf endp_drawb proc push hWin mov eax,offset _draw_b push eax mov eax,offset _draw_d push eax mov eax,offset _draw_l push eax call _draw_3side ret_drawb endp;重置info数组,coutl计数置0,步骤类型记录重置_resetMofang proc push ecx mov ecx,27@@: push source_info[ecx*4-4] pop info[ecx*4-4] loop @B pop ecx xor eax,eax mov coutl,eax mov eax,7eh mov last,eax mov last1,eax invoke PostMessage,hWinMain,WM_PAINT,NULL,NULL invoke PostMessage,hWin,WM_PAINT,NULL,NULL ret_resetMofang endp;预备从ini文件里读初始化信息,但现在只做reset_initMofang proc @pos invoke _Point_script,@pos mov eax,@pos .if eax == 1 call _drawf .else call _drawb .endif ret_initMofang endp action.asm ;通用程序,实现参数入栈出栈及多次调用;入口参数: @n1~8 八个参加转动的方块代号; @count 重复执行的次数; @lpfunc 计算程序的入口地址_action_all proc @n1,@n2,@n3,@n4,@n5,@n6,@n7,@n8,@count,@lpfunc LOCAL @n[8] push ecx push @n3 ;参数反入栈,顺出栈 pop @n[00h] push @n5 pop @n[04h] push @n8 pop @n[08h] push @n2 pop @n[0ch] push @n7 pop @n[10h] push @n1 pop @n[14h] push @n4 pop @n[18h] push @n6 pop @n[1ch] .while @count >0 mov ecx,8@@: mov eax,@n1[ecx*4-4] push info[eax] loop @B mov ecx,8@@: pop eax push @n[ecx*4-4] call @lpfunc loop @B dec @count .endw pop ecx ret_action_all endp;这类函数还有一个默认的入口参数:EAX,另外这里不能破坏ecx_action1_1 proc @pos push ecx push eax push eax and eax,1c0h shl eax,12 pop edx and edx,0003fe00h or edx,eax shr edx,3 pop eax and eax,03fh or eax,edx mov ebx,@pos mov ecx,info[ebx] and ecx,0FFFC0000h or eax,ecx mov info[ebx],eax pop ecx ret_action1_1 endp;局部通用_action1 proc @count mov eax,offset _action1_1 push eax mov ecx,8 push @count@@: push turn_info0[ecx*4-4] loop @B call _action_all mov eax,@count .if eax == 1 push 21h .else push 41h .endif call _load ret_action1 endp_action3 proc @count mov eax,offset _action1_1 push eax mov ecx,8 push @count@@: push turn_info1[ecx*4-4] loop @B call _action_all mov eax,@count .if eax == 1 push 22h .else push 42h .endif call _load ret_action3 endp_action5_1 proc @pos LOCAL @tmp push ecx push eax push eax push eax push eax push 0 pop @tmp and eax,07h ;这是上色 shl eax,9 ;转到后色 or @tmp,eax pop eax and eax,0E00h ;这是后色 shr eax,6 ;变成下色 or @tmp,eax pop eax and eax,38h shl eax,12 ;下色--前色 or @tmp,eax pop eax and eax,38000h shr eax,15 or @tmp,eax pop eax and eax,71C0h ;保存左右色 or eax,@tmp ;出结果 mov ebx,@pos mov ecx,info[ebx] and ecx,0FFFC0000h or eax,ecx mov info[ebx],eax pop ecx ret_action5_1 endp_action5 proc @count mov eax,offset _action5_1 push eax mov ecx,8 push @count@@: push turn_info2[ecx*4-4] loop @B call _action_all mov eax,@count .if eax == 1 push 23h .else push 43h .endif call _load ret_action5 endp_action7 proc @count mov eax,offset _action5_1 push eax mov ecx,8 push @count@@: push turn_info3[ecx*4-4] loop @B call _action_all mov eax,@count .if eax == 1 push 24h .else push 44h .endif call _load ret_action7 endp_action9_1 proc @pos LOCAL @tmp push ecx push eax push eax push eax push eax push 0 pop @tmp and eax,07h ;这是上色 shl eax,12 ;转到左色 or @tmp,eax pop eax and eax,7000h ;这是左色 shr eax,9 ;变成下色 or @tmp,eax pop eax and eax,38h shl eax,3 ;下色--右色 or @tmp,eax pop eax and eax,1C0h shr eax,6 ;右--上 or @tmp,eax pop eax and eax,38E00h ;保存前后色 or eax,@tmp ;出结果 mov ebx,@pos mov ecx,info[ebx] and ecx,0FFFC0000h or eax,ecx mov info[ebx],eax pop ecx ret_action9_1 endp_action9 proc @count mov eax,offset _action9_1 push eax mov ecx,8 push @count@@: push turn_info4[ecx*4-4] loop @B call _action_all mov eax,@count .if eax == 1 push 25h .else push 45h .endif call _load ret_action9 endp_action11 proc @count mov eax,offset _action9_1 push eax mov ecx,8 push @count@@: push turn_info5[ecx*4-4] loop @B call _action_all mov eax,@count .if eax == 1 push 26h .else push 46h .endif call _load ret_action11 endp mofang.inc DLG_MAIN equ 4210ICO_MAIN equ 4210IDM_MAIN equ 4210IDA_MAIN equ 4210IDC_copyright equ 4210IDC_1 equ 4211IDC_2 equ 4212IDC_3 equ 4213IDC_4 equ 4214IDC_5 equ 4215IDC_6 equ 4216IDC_7 equ 4217IDC_8 equ 4218IDC_9 equ 4219IDC_10 equ 4220IDC_11 equ 4221IDC_12 equ 4222IDC_reset equ 4230IDC_EXIT equ 4231IDC_help equ 4232IDC_Low equ 4233IDC_Mid equ 4234IDC_High equ 4235IDC_Self equ 4236IDC_pageup equ 4301IDC_pagedown equ 4302IDC_end equ 4303IDC_home equ 4304IDC_NUM equ 4401MY_X equ 330MY_Y equ 240MY_W equ 320MY_H equ 340_red equ 000000FFh_yellow equ 0000FFFFh_cheng equ 000080FFh_white equ 00FFFFFFh_blue equ 00FF0000h_green equ 0000FF00h_black equ 00000000h.const;原始信息,当魔方完全初始的时候的正确信息source_info dd 00a81ffdh,01887ffdh,02987efdh dd 03281fffh,044087FFFh,05187effh dd 06681fe7h,07487fe7h,08587ee7h dd 10a39ffdh,5183FFFDh,1293fefdh dd 53239FFFh,5403FFFFh,5513FEFFh dd 16639fe7h,5743FFE7h,1853fee7h dd 20a795fdh,2187f5fdh,2297f4fdh dd 232795ffh,6407F5FFh,2517f4ffh dd 266795e7h,2747f5e7h,2857f4e7h dd 0,0,0,0turn_info0 dd 00h,04h,08h,24h,2ch,48h,4ch,50hturn_info1 dd 18h,1ch,20h,3ch,44h,60h,64h,68hturn_info2 dd 00h,0ch,18h,24h,3ch,48h,54h,60hturn_info3 dd 08h,14h,20h,2ch,44h,50h,5ch,68hturn_info4 dd 00h,04h,08h,0ch,14h,18h,1ch,20hturn_info5 dd 48h,4ch,50h,54h,5ch,60h,64h,68h dd 0,0,0,0.datanAlpha dd 0d0h ;透明度,初始为d0;正常初始化魔方信息,如果有ini文件,将被覆盖info dd 00a81ffdh,01887ffdh,02987efdh dd 03281fffh,044087FFFh,05187effh dd 06681fe7h,07487fe7h,08587ee7h dd 10a39ffdh,5183FFFDh,1293fefdh dd 53239FFFh,5403FFFFh,5513FEFFh dd 16639fe7h,5743FFE7h,1853fee7h dd 20a795fdh,2187f5fdh,2297f4fdh dd 232795ffh,6407F5FFh,2517f4ffh dd 266795e7h,2747f5e7h,2857f4e7h dd 0,0,0,0szCopyRight db 10,"江西理工大学 环境032班 ",10,10,9,"Triones",10,10," 版权所有 2006(c)",0szClassName db 'MyClass',0_name db "魔方(ver 1.0)",0fmt_num db "%d",0fmt_info db "%02d",0szFileName db ".mofang.ini",0szSecName db "魔方信息",0szKeyAlpha db "Alpha",0szKeyInfo db "info",0szKeyLoad db "Load",0szKeyCout_l db "cont_l",0coutl dd 0last dd 07Ehlast1 dd 07Eh.data?hInstance dd ?hWinMain dd ? ;顶层窗口hWin dd ? ;作为底层窗口使用hAcc dd ? ;加速键句柄hIcon dd ? ;图标句柄hMenu dd ?_Result dd ?p_h dd ? ;point heightp_w dd ? ;point widthp_h3 dd ?p_w3 dd ? ;3*w_hdc HDC ? ;设备句柄Z_X dd ? ;绘画原点的变量Z_Y dd ?@p dd 64 dup (?) ;因为程序结构的需要放上来,但它还是小局部使用的共用全局数组@i dd ?@stMsg MSG <>@ps PAINTSTRUCT <>@rect_now RECT <>hBrush dd 8 dup (?)hPen dd 8 dup (?)hPen2 dd 8 dup (?)KeyInfo db 256 dup (?)tmp_str db 360 dup (?)_tmp_str db 128 dup (?)load db 2048 dup (?) mofang.rc #include <C:masm32include esource.h>#define ICO_MAIN 4210#define DLG_MAIN 4210#define IDM_MAIN 4210#define IDA_MAIN 4210#define IDC_copyright 4210#define IDC_1 4211#define IDC_2 4212#define IDC_3 4213#define IDC_4 4214#define IDC_5 4215#define IDC_6 4216#define IDC_7 4217#define IDC_8 4218#define IDC_9 4219#define IDC_10 4220#define IDC_11 4221#define IDC_12 4222#define IDC_reset 4230#define IDC_EXIT 4231#define IDC_help 4232#define IDC_Low 4233#define IDC_Mid 4234#define IDC_High 4235#define IDC_Self 4236#define IDC_pageup 4301#define IDC_pagedown 4302#define IDC_end 4303#define IDC_home 4304#define IDC_NUM 4401ICO_MAIN ICON "cm02_triones.ico"IDM_MAIN MENU discardable...{ popup "操作(&O)" ...{ menuitem "重置魔方(&R)",IDC_reset menuitem separator menuitem "退出(&X)",IDC_EXIT } popup "游戏(&G)" ...{ menuitem "初级(&L)",IDC_Low menuitem "中级(&M)",IDC_Mid menuitem "高级(&H)",IDC_High menuitem "自定义(&S)",IDC_Self } popup "帮助(&H)" ...{ menuitem "使用说明(&H)",IDC_help menuitem separator menuitem "关于(&A)",IDC_copyright }}IDA_MAIN accelerators...{ "a",IDC_1 "A",IDC_1 "d",IDC_2 "D",IDC_2 VK_LEFT,IDC_3,VIRTKEY VK_RIGHT,IDC_4,VIRTKEY "w",IDC_5 "W",IDC_5 "s",IDC_6 "S",IDC_6 VK_UP,IDC_7,VIRTKEY VK_DOWN,IDC_8,VIRTKEY "1",IDC_9 "3",IDC_10 "7",IDC_11 "9",IDC_12 0x21,IDC_pageup,VIRTKEY //VK_PGUP与VK_PGDN不知道为什么这里不认识 0x22,IDC_pagedown,VIRTKEY VK_END,IDC_end,VIRTKEY VK_HOME,IDC_home,VIRTKEY }DLG_MAIN DIALOG 20,15,150,41STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | DS_3DLOOKCAPTION "魔方设置"FONT 9, "宋体"...{ LTEXT " 请输入打乱魔方的次数:",-1,4,15,100,11 EDITTEXT IDC_NUM,100,12,14,11,ES_NUMBER | ES_CENTER PUSHBUTTON "OK",IDOK,120,10,23,14}