線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:8605
推到 Plurk!
推到 Facebook!

圖片分割,亂數排列,排圖小遊戲

 
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-05-30 23:04:18 IP:211.76.xxx.xxx 訂閱
本遊戲靈感來自 ■【BCB】【發表】圖片分割,亂數排列 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=50139     我不會美工,不然我想畫一些小朋友喜歡的圖應該是不錯玩 < > 附上幾張圖,所以有點大... 不想下的,可以直接看看以下的原始碼 < >
//---------------------------------------------------------------------------    #ifndef PartPictureUnitH
#define PartPictureUnitH
//---------------------------------------------------------------------------
#include 
#include 
#include 
#include <Forms.hpp>
#include 
#include 
#include 
#include 
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
  TOpenPictureDialog *OpenPictureDialog1;
  TLabel *Label1;
  TComboBox *ComboBox1;
  TLabel *Label3;
  TLabel *Label2;
  TTimer *Timer1;
  TImage *Image1;
  TImage *Image2;
  TCheckBox *CheckBox1;
  TCheckBox *CheckBox2;
  TCheckBox *CheckBox3;
  TCheckBox *CheckBox4;
  TComboBox *ComboBox2;
  void __fastcall ComboBox1Change(TObject *Sender);
  void __fastcall ComboBox2Change(TObject *Sender);
  void __fastcall MyImageClick(TObject *Sender);
  void __fastcall Timer1Timer(TObject *Sender);
  void __fastcall CheckBox1Click(TObject *Sender);
  void __fastcall CheckBox2Click(TObject *Sender);
  void __fastcall ImageMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y);
  void __fastcall ImageMouseMove(TObject *Sender, TShiftState Shift,
          int X, int Y);
  void __fastcall ImageMouseUp(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y);
  void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift, int X,
          int Y);
  void __fastcall CheckBox3Click(TObject *Sender);
private: // User declarations
  TStringList *MyImageList;
  int          InVisibleIndex;
  int          Part;
  int          ChangeableIndex[4];
  TDateTime    StartTime;
  AnsiString   LastSelectBmpFile;
  int          LastSelectIndex;      bool  bMouseDown;
  int   iDownIndex;
  int   iDownX;
  int   iDownY;
  int   iImageX;
  int   iImageY;
  bool  bNeedExchange;
  bool  bAlreadyDone;      void __fastcall UpdateChangeableIndex(void);
  void __fastcall ChangeImage(int Index1,int Index2);
  void __fastcall UpdateDebugInformation(void);
  void __fastcall CheckIfAlreadyDone(void);
  void __fastcall RePartImage(AnsiString BmpFileName);    public:  // User declarations
  __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
// 圖片分割,亂數排列,排圖小遊戲  by dllee http://dllee.ktop.com.tw
// 本範例使用了以下技巧:
// 1. 使用 Canvas->CopyRect() 分割圖片
// 2. 動態產生物件,及指定事件
// 3. 使用 TStringList 儲存元件
// 4. srand, random 產生亂數的方法
// 5. 以交換方式亂排
// 6. 移動元件
// 7. 使用 Canvas->StretchDraw() 自動縮放
//---------------------------------------------------------------------------
#include 
#pragma hdrstop    #include "PartPictureUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
  MyImageList=new TStringList;
  Image1->Width=512;
  Image1->Height=512;
  Image1->Top=50;
  Image1->Left=0;
  Image1->Visible=false;
  ComboBox1->ItemIndex=0;
  ComboBox2->ItemIndex=0;
  CheckBox1Click(NULL);
  CheckBox2Click(NULL);
  ComboBox2Change(NULL);
  this->DoubleBuffered=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateChangeableIndex(void)
{
  // 左邊
  if(InVisibleIndex%Part==0) // 已在最左邊
    ChangeableIndex[0]=-1;
  else
    ChangeableIndex[0]=InVisibleIndex-1;      // 右邊
  if((InVisibleIndex+1)%Part==0) // 已在最右邊
    ChangeableIndex[1]=-1;
  else
    ChangeableIndex[1]=InVisibleIndex+1;      // 上面
  if(InVisibleIndex/Part==0) // 已在最上面
    ChangeableIndex[2]=-1;
  else
    ChangeableIndex[2]=InVisibleIndex-Part;      // 下面
  if(InVisibleIndex/Part==Part-1) // 已在最下面
    ChangeableIndex[3]=-1;
  else
    ChangeableIndex[3]=InVisibleIndex+Part;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ChangeImage(int Index1,int Index2)
{
  AnsiString tempS=MyImageList->Strings[Index1];
  TObject   *tempO=MyImageList->Objects[Index1];
  int temp1X=((TImage*)MyImageList->Objects[Index1])->Left;
  int temp1Y=((TImage*)MyImageList->Objects[Index1])->Top;
  int temp2X=((TImage*)MyImageList->Objects[Index2])->Left;
  int temp2Y=((TImage*)MyImageList->Objects[Index2])->Top;
  MyImageList->Strings[Index1]=MyImageList->Strings[Index2];
  MyImageList->Objects[Index1]=MyImageList->Objects[Index2];
  MyImageList->Strings[Index2]=tempS;
  MyImageList->Objects[Index2]=tempO;
  ((TImage*)MyImageList->Objects[Index1])->Left=temp1X;
  ((TImage*)MyImageList->Objects[Index1])->Top= temp1Y;
  ((TImage*)MyImageList->Objects[Index2])->Left=temp2X;
  ((TImage*)MyImageList->Objects[Index2])->Top= temp2Y;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateDebugInformation(void)
{
  AnsiString as=EmptyStr;
  for(int i=0;iCount;i++)
    as=as
      +((MyImageList->Strings[i].Length()==1)?" ":"")
      +MyImageList->Strings[i]
      +(((i+1)%Part==0)?"\n":" ");
  Label3->Caption=as;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckIfAlreadyDone(void)
{
  // 判斷是否已經排好
  for(int i=0;iCount;i++)
  {
    if(MyImageList->Strings[i]!=String(i+1))
      return;
  }
  // 如果已排好,則把隱藏的那一塊顯示出來,同時禁止再移動了
  ((TImage*)MyImageList->Objects[InVisibleIndex])->Visible=true;
  for(int i=0;i<4;i++) ChangeableIndex[i]=-1;
  Timer1->Enabled=false;                          // 不必再更新花費時間
  bAlreadyDone=true;
  ShowMessage("恭喜您! 完成了!");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RePartImage(AnsiString BmpFileName)
{
    Part=ComboBox1->Text.SubString(1,1).ToIntDef(3);  // 決定分割數
    srand(GetTickCount());                            // 決定亂數種子        for(int i=0;iCount;i++)   // 刪除上次的 Image 元件
      delete ((TImage*)MyImageList->Objects[i]);
    MyImageList->Clear();                                                // 清除上次的圖案
    Image1->Canvas->FillRect(Rect(0,0,512,512));
                                            // 載入原始圖
    Graphics::TBitmap *Bitmap = new Graphics::TBitmap();
    Bitmap->LoadFromFile(BmpFileName);
    if(CheckBox4->Checked)                  // 自動縮放
      Image1->Canvas->StretchDraw(Rect(0,0,512,512),Bitmap);
    else                                    // 原圖切割
      Image1->Canvas->CopyRect(Rect(0,0,512,512),Bitmap->Canvas,
        Rect(0,0,512,512));
    Image2->Canvas->StretchDraw(Rect(0,0,200,200),Image1->Picture->Graphic);  // 原圖參考
    delete Bitmap;        for(int i=0;iParent=this;
        img->Width=Image1->Width/Part;      // 決定大小
        img->Height=Image1->Height/Part;
        img->Canvas->CopyRect(Rect(0,0,img->Width,img->Height),
          Image1->Canvas,                   // 由原圖按順序切割成小圖
          Rect(j*img->Width,i*img->Height,(j+1)*img->Width,(i+1)*img->Height));
        img->Canvas->Brush->Color=clSilver; // 加灰色邊框
        img->Canvas->FrameRect(Rect(0,0,img->Width,img->Height));            img->Left=(j)*(img->Width);
        img->Top =(i)*(img->Height) + 50;   // 保留上面 50 點給按鈕
        img->MyImageClick;
        img->ImageMouseDown;
        img->ImageMouseMove;
        img->ImageMouseUp;
        img->Tag=i*Part+j;
        MyImageList->AddObject(String(i*Part+j+1),img); // 加入 ImageList 以便管理
      }
    }
    InVisibleIndex=Part*Part-1;
    ((TImage*)MyImageList->Objects[InVisibleIndex])->Visible=false;        for(int i=0;iCount*8;i++)
    {
      int ChangeIndex=random(MyImageList->Count); // 以亂數決定交換位置 (交換法)
      ChangeImage(InVisibleIndex,ChangeIndex);    // 與不可見的交換
      InVisibleIndex=ChangeIndex;
    }
    UpdateChangeableIndex();
    UpdateDebugInformation();
    CheckBox3Click(NULL);
    bAlreadyDone=false;
    StartTime=Now();                              // 計時開始
    Timer1->Enabled=true;                         // 開始顯示花費時間
    LastSelectBmpFile=BmpFileName;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox1Change(TObject *Sender)
{
  RePartImage(LastSelectBmpFile);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox2Change(TObject *Sender)
{
  switch(ComboBox2->ItemIndex)
  {
    case 0:
      RePartImage(ExtractFilePath(Application->ExeName)+"牽牛花.bmp");
      LastSelectIndex=0;
      break;
    case 1:
      RePartImage(ExtractFilePath(Application->ExeName)+"未成熟梨.bmp");
      LastSelectIndex=1;
      break;
    case 2:
      RePartImage(ExtractFilePath(Application->ExeName)+"野菜.bmp");
      LastSelectIndex=2;
      break;
    default:
      if(OpenPictureDialog1->Execute())         // 選檔
        RePartImage(OpenPictureDialog1->FileName);
      else
      {
        ComboBox2->ItemIndex=LastSelectIndex;
        ComboBox2Change(Sender);
      }
      break;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MyImageClick(TObject *Sender)
{
  if(bAlreadyDone         // 如果已完成
  || CheckBox3->Checked)  // 在自由移動模式,不啟動以下程式
    return;      int ThisIndex=MyImageList->IndexOfObject(Sender);
  if(ThisIndex<0) return;      // 判斷是否可以交換
  bool Changeable=false;
  for(int i=0;i<4;i++)
  {
    if(ThisIndex==ChangeableIndex[i])
    {
      Changeable=true;
      break;
    }
  }
  if(Changeable==false) return;      // 與看不見的換位置
  ChangeImage(InVisibleIndex,ThisIndex);
  InVisibleIndex=ThisIndex;
  UpdateChangeableIndex();      UpdateDebugInformation();      CheckIfAlreadyDone();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{ // 顯示花費時間
  Label2->Caption=(Now()-StartTime).FormatString("hh:nn:ss");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{
  Label3->Visible=CheckBox1->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckBox2Click(TObject *Sender)
{
  Image2->Visible=CheckBox2->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  if(bAlreadyDone         // 如果已完成
  || !CheckBox3->Checked) // 不在自由移動模式,不啟動以下程式
    return;      TImage *img=(TImage*)Sender;
  if(Button==mbLeft)
  {
    bMouseDown=true;
    iDownX=img->Width/2;
    iDownY=img->Height/2;
    iDownIndex=MyImageList->IndexOfObject(Sender);
    iImageX=img->Left;
    iImageY=img->Top;
    img->BringToFront();
    ImageMouseMove(Sender,Shift,X,Y);
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
  if(bAlreadyDone         // 如果已完成
  || !CheckBox3->Checked) // 不在自由移動模式,不啟動以下程式
    return;      if(bMouseDown)
  {
    ((TImage*)Sender)->Left+=X-iDownX;
    ((TImage*)Sender)->Top+=Y-iDownY;
  }
  if(bNeedExchange)
  {
    ChangeImage(iDownIndex,MyImageList->IndexOfObject(Sender));
    bNeedExchange=false;
    UpdateDebugInformation();
    CheckIfAlreadyDone();
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageMouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
  if(bAlreadyDone         // 如果已完成
  || !CheckBox3->Checked) // 不在自由移動模式,不啟動以下程式
    return;      TImage *img=(TImage*)Sender;
  img->Left=iImageX;
  img->Top=iImageY;
  bMouseDown=false;
  bNeedExchange=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
      int X, int Y)
{
  bNeedExchange=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckBox3Click(TObject *Sender)
{ // 在自由移動模式,所有的圖都顯示,在非自動移動模式,有一個圖是隱藏的
  ((TImage*)MyImageList->Objects[InVisibleIndex])->Visible=CheckBox3->Checked;
}
//---------------------------------------------------------------------------
http://www.ViewMove.com 視動自動化科技股份有限公司 ViewMove Technologies, Inc. 發表人 - dllee 於 2004/05/30 23:07:08
------
http://www.ViewMove.com
附加檔案:51019_PartPicture.zip
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-06-07 22:47:46 IP:59.105.xxx.xxx 訂閱
重貼程式碼: 
■ PartPictureUnit.dfm
[code cpp]
object Form1: TForm1
Left = 194
Top = 115
BorderIcons = [biSystemMenu, biMinimize]
BorderStyle = bsSingle
Caption = '圖片分割,亂數排列,排圖小遊戲 by dllee http://dllee.ktop.com.tw'
ClientHeight = 591
ClientWidth = 776
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
Icon.Data = {
0000010001001010000000000000680500001600000028000000100000002000
0000010008000000000040010000000000000000000000000000000000000000
00000E0E0E00FFD4E300FFD0E000FFCCDD00FFCCDC00FFC8D900FFB2C700F2F2
F200EFEFEF00EDEDED00FFC3D500FFBACE00FF9FB800CECECE00C9C9C900B1B1
B100FFC6D700FFBDD000C2C2C200B6B6B6009E9E9E00FFB8CC00FFA3BC00E8E8
E800BABABA00DEDEDE00A2A2A200FFFFFF000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000001010101010101010101010101000000011A
1B151515011A1B15151501000000011819141415011819141415010000000108
0E13141501080E1314150100000001080E0E0F1001080E0E0F10010000000108
0808090A01080808090A0100000001010101010101010101010101000000011A
1B15151501000000000000000000011819141415010001010101010101000108
0E13141501000116170D0D0D010001080E0E0F1001000111120C0C0D01000108
0808090A01000102050B0C0D0100010101010101010001020505060701000000
000000000000010202020304010000000000000000000101010101010100FFFF
00000007000000070000000700000007000000070000000700000007000001FF
00000101000001010000010100000101000001010000FF010000FF010000}
OldCreateOrder = False
Position = poScreenCenter
OnMouseMove = FormMouseMove
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 16
Top = 18
Width = 53
Height = 15
AutoSize = False
Caption = '切割數:'
OnMouseMove = FormMouseMove
end
object Label3: TLabel
Left = 534
Top = 72
Width = 235
Height = 197
AutoSize = False
Caption = 'DEBUG'
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Courier New'
Font.Style = []
ParentFont = False
WordWrap = True
OnMouseMove = FormMouseMove
end
object Label2: TLabel
Left = 406
Top = 18
Width = 48
Height = 13
Caption = '花費時間'
OnMouseMove = FormMouseMove
end
object Image1: TImage
Left = 36
Top = 66
Width = 105
Height = 105
end
object Image2: TImage
Left = 532
Top = 284
Width = 200
Height = 200
OnMouseMove = FormMouseMove
end
object ComboBox1: TComboBox
Left = 66
Top = 14
Width = 133
Height = 21
Style = csDropDownList
ItemHeight = 13
TabOrder = 0
OnChange = ComboBox1Change
Items.Strings = (
'3 - Easy'
'4 - Medium'
'5 - Hard'
'9 - OOXX')
end
object CheckBox1: TCheckBox
Left = 536
Top = 8
Width = 97
Height = 17
Caption = '提示 '
Checked = True
State = cbChecked
TabOrder = 1
OnClick = CheckBox1Click
OnMouseMove = FormMouseMove
end
object CheckBox2: TCheckBox
Left = 536
Top = 34
Width = 97
Height = 17
Caption = '預覽全圖 '
Checked = True
State = cbChecked
TabOrder = 2
OnClick = CheckBox2Click
OnMouseMove = FormMouseMove
end
object CheckBox3: TCheckBox
Left = 646
Top = 8
Width = 97
Height = 17
Caption = '自由移動 '
TabOrder = 3
OnClick = CheckBox3Click
OnMouseMove = FormMouseMove
end
object CheckBox4: TCheckBox
Left = 646
Top = 34
Width = 119
Height = 17
Caption = '自動縮放原圖 '
Checked = True
State = cbChecked
TabOrder = 4
end
object ComboBox2: TComboBox
Left = 220
Top = 14
Width = 175
Height = 21
Style = csDropDownList
ItemHeight = 13
TabOrder = 5
OnChange = ComboBox2Change
Items.Strings = (
'Level1 -- 牽牛花'
'Level2 -- 未成熟梨'
'Level3 -- 野菜'
'[自行選檔]')
end
object OpenPictureDialog1: TOpenPictureDialog
Filter = 'Bitmaps (*.bmp)|*.bmp'
Left = 254
Top = 74
end
object Timer1: TTimer
Enabled = False
Interval = 333
OnTimer = Timer1Timer
Left = 354
Top = 74
end
end
[/code]

■ PartPictureUnit.h
[code cpp]
//---------------------------------------------------------------------------
#ifndef PartPictureUnitH
#define PartPictureUnitH
//---------------------------------------------------------------------------
#include
#include
#include
#include <Forms.hpp><br />#include
#include
#include
#include
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TOpenPictureDialog *OpenPictureDialog1;
TLabel *Label1;
TComboBox *ComboBox1;
TLabel *Label3;
TLabel *Label2;
TTimer *Timer1;
TImage *Image1;
TImage *Image2;
TCheckBox *CheckBox1;
TCheckBox *CheckBox2;
TCheckBox *CheckBox3;
TCheckBox *CheckBox4;
TComboBox *ComboBox2;
void __fastcall ComboBox1Change(TObject *Sender);
void __fastcall ComboBox2Change(TObject *Sender);
void __fastcall MyImageClick(TObject *Sender);
void __fastcall Timer1Timer(TObject *Sender);
void __fastcall CheckBox1Click(TObject *Sender);
void __fastcall CheckBox2Click(TObject *Sender);
void __fastcall ImageMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y);
void __fastcall ImageMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y);
void __fastcall ImageMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y);
void __fastcall FormMouseMove(TObject *Sender, TShiftState Shift, int X,
int Y);
void __fastcall CheckBox3Click(TObject *Sender);
private: // User declarations
TStringList *MyImageList;
int InVisibleIndex;
int Part;
int ChangeableIndex[4];
TDateTime StartTime;
AnsiString LastSelectBmpFile;
int LastSelectIndex;

bool bMouseDown;
int iDownIndex;
int iDownX;
int iDownY;
int iImageX;
int iImageY;
bool bNeedExchange;
bool bAlreadyDone;

void __fastcall UpdateChangeableIndex(void);
void __fastcall ChangeImage(int Index1,int Index2);
void __fastcall UpdateDebugInformation(void);
void __fastcall CheckIfAlreadyDone(void);
void __fastcall RePartImage(AnsiString BmpFileName);

public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
[/code]

■ PartPictureUnit.cpp
[code cpp]
//---------------------------------------------------------------------------
// 圖片分割,亂數排列,排圖小遊戲 by dllee http://dllee.ktop.com.tw
// 本範例使用了以下技巧:
// 1. 使用 Canvas->CopyRect() 分割圖片
// 2. 動態產生物件,及指定事件
// 3. 使用 TStringList 儲存元件
// 4. srand, random 產生亂數的方法
// 5. 以交換方式亂排
// 6. 移動元件
// 7. 使用 Canvas->StretchDraw() 自動縮放
//---------------------------------------------------------------------------
#include
#pragma hdrstop

#include "PartPictureUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
MyImageList=new TStringList;
Image1->Width=512;
Image1->Height=512;
Image1->Top=50;
Image1->Left=0;
Image1->Visible=false;
ComboBox1->ItemIndex=0;
ComboBox2->ItemIndex=0;
CheckBox1Click(NULL);
CheckBox2Click(NULL);
ComboBox2Change(NULL);
this->DoubleBuffered=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateChangeableIndex(void)
{
// 左邊
if(InVisibleIndex%Part==0) // 已在最左邊
ChangeableIndex[0]=-1;
else
ChangeableIndex[0]=InVisibleIndex-1;

// 右邊
if((InVisibleIndex 1)%Part==0) // 已在最右邊
ChangeableIndex[1]=-1;
else
ChangeableIndex[1]=InVisibleIndex 1;

// 上面
if(InVisibleIndex/Part==0) // 已在最上面
ChangeableIndex[2]=-1;
else
ChangeableIndex[2]=InVisibleIndex-Part;

// 下面
if(InVisibleIndex/Part==Part-1) // 已在最下面
ChangeableIndex[3]=-1;
else
ChangeableIndex[3]=InVisibleIndex Part;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ChangeImage(int Index1,int Index2)
{
AnsiString tempS=MyImageList->Strings[Index1];
TObject *tempO=MyImageList->Objects[Index1];
int temp1X=((TImage*)MyImageList->Objects[Index1])->Left;
int temp1Y=((TImage*)MyImageList->Objects[Index1])->Top;
int temp2X=((TImage*)MyImageList->Objects[Index2])->Left;
int temp2Y=((TImage*)MyImageList->Objects[Index2])->Top;
MyImageList->Strings[Index1]=MyImageList->Strings[Index2];
MyImageList->Objects[Index1]=MyImageList->Objects[Index2];
MyImageList->Strings[Index2]=tempS;
MyImageList->Objects[Index2]=tempO;
((TImage*)MyImageList->Objects[Index1])->Left=temp1X;
((TImage*)MyImageList->Objects[Index1])->Top= temp1Y;
((TImage*)MyImageList->Objects[Index2])->Left=temp2X;
((TImage*)MyImageList->Objects[Index2])->Top= temp2Y;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::UpdateDebugInformation(void)
{
AnsiString as=EmptyStr;
for(int i=0;iCount;i )
as=as
((MyImageList->Strings[i].Length()==1)?" ":"")
MyImageList->Strings[i]
(((i 1)%Part==0)?"\n":" ");
Label3->Caption=as;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckIfAlreadyDone(void)
{
// 判斷是否已經排好
for(int i=0;iCount;i )
{
if(MyImageList->Strings[i]!=String(i 1))
return;
}
// 如果已排好,則把隱藏的那一塊顯示出來,同時禁止再移動了
((TImage*)MyImageList->Objects[InVisibleIndex])->Visible=true;
for(int i=0;i<4;i ) ChangeableIndex[i]=-1;
Timer1->Enabled=false; // 不必再更新花費時間
bAlreadyDone=true;
ShowMessage("恭喜您! 完成了!");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::RePartImage(AnsiString BmpFileName)
{
Part=ComboBox1->Text.SubString(1,1).ToIntDef(3); // 決定分割數
srand(GetTickCount()); // 決定亂數種子

for(int i=0;iCount;i ) // 刪除上次的 Image 元件
delete ((TImage*)MyImageList->Objects[i]);
MyImageList->Clear();

// 清除上次的圖案
Image1->Canvas->FillRect(Rect(0,0,512,512));
// 載入原始圖
Graphics::TBitmap *Bitmap = new Graphics::TBitmap();
Bitmap->LoadFromFile(BmpFileName);
if(CheckBox4->Checked) // 自動縮放
Image1->Canvas->StretchDraw(Rect(0,0,512,512),Bitmap);
else // 原圖切割
Image1->Canvas->CopyRect(Rect(0,0,512,512),Bitmap->Canvas,
Rect(0,0,512,512));
Image2->Canvas->StretchDraw(Rect(0,0,200,200),Image1->Picture->Graphic); // 原圖參考
delete Bitmap;

for(int i=0;i {
for(int j=0;j {
TImage *img=new TImage(this); // 建立圖片
img->Parent=this;
img->Width=Image1->Width/Part; // 決定大小
img->Height=Image1->Height/Part;
img->Canvas->CopyRect(Rect(0,0,img->Width,img->Height),
Image1->Canvas, // 由原圖按順序切割成小圖
Rect(j*img->Width,i*img->Height,(j 1)*img->Width,(i 1)*img->Height));
img->Canvas->Brush->Color=clSilver; // 加灰色邊框
img->Canvas->FrameRect(Rect(0,0,img->Width,img->Height));

img->Left=(j)*(img->Width);
img->Top =(i)*(img->Height) 50; // 保留上面 50 點給按鈕
img->MyImageClick;
img->ImageMouseDown;
img->ImageMouseMove;
img->ImageMouseUp;
img->Tag=i*Part j;
MyImageList->AddObject(String(i*Part j 1),img); // 加入 ImageList 以便管理
}
}
InVisibleIndex=Part*Part-1;
((TImage*)MyImageList->Objects[InVisibleIndex])->Visible=false;

for(int i=0;iCount*8;i )
{
int ChangeIndex=random(MyImageList->Count); // 以亂數決定交換位置 (交換法)
ChangeImage(InVisibleIndex,ChangeIndex); // 與不可見的交換
InVisibleIndex=ChangeIndex;
}
UpdateChangeableIndex();
UpdateDebugInformation();
CheckBox3Click(NULL);
bAlreadyDone=false;
StartTime=Now(); // 計時開始
Timer1->Enabled=true; // 開始顯示花費時間
LastSelectBmpFile=BmpFileName;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox1Change(TObject *Sender)
{
RePartImage(LastSelectBmpFile);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox2Change(TObject *Sender)
{
switch(ComboBox2->ItemIndex)
{
case 0:
RePartImage(ExtractFilePath(Application->ExeName) "牽牛花.bmp");
LastSelectIndex=0;
break;
case 1:
RePartImage(ExtractFilePath(Application->ExeName) "未成熟梨.bmp");
LastSelectIndex=1;
break;
case 2:
RePartImage(ExtractFilePath(Application->ExeName) "野菜.bmp");
LastSelectIndex=2;
break;
default:
if(OpenPictureDialog1->Execute()) // 選檔
RePartImage(OpenPictureDialog1->FileName);
else
{
ComboBox2->ItemIndex=LastSelectIndex;
ComboBox2Change(Sender);
}
break;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::MyImageClick(TObject *Sender)
{
if(bAlreadyDone // 如果已完成
|| CheckBox3->Checked) // 在自由移動模式,不啟動以下程式
return;

int ThisIndex=MyImageList->IndexOfObject(Sender);
if(ThisIndex<0) return;

// 判斷是否可以交換
bool Changeable=false;
for(int i=0;i<4;i )
{
if(ThisIndex==ChangeableIndex[i])
{
Changeable=true;
break;
}
}
if(Changeable==false) return;

// 與看不見的換位置
ChangeImage(InVisibleIndex,ThisIndex);
InVisibleIndex=ThisIndex;
UpdateChangeableIndex();

UpdateDebugInformation();

CheckIfAlreadyDone();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{ // 顯示花費時間
Label2->Caption=(Now()-StartTime).FormatString("hh:nn:ss");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckBox1Click(TObject *Sender)
{
Label3->Visible=CheckBox1->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckBox2Click(TObject *Sender)
{
Image2->Visible=CheckBox2->Checked;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if(bAlreadyDone // 如果已完成
|| !CheckBox3->Checked) // 不在自由移動模式,不啟動以下程式
return;

TImage *img=(TImage*)Sender;
if(Button==mbLeft)
{
bMouseDown=true;
iDownX=img->Width/2;
iDownY=img->Height/2;
iDownIndex=MyImageList->IndexOfObject(Sender);
iImageX=img->Left;
iImageY=img->Top;
img->BringToFront();
ImageMouseMove(Sender,Shift,X,Y);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
if(bAlreadyDone // 如果已完成
|| !CheckBox3->Checked) // 不在自由移動模式,不啟動以下程式
return;

if(bMouseDown)
{
((TImage*)Sender)->Left =X-iDownX;
((TImage*)Sender)->Top =Y-iDownY;
}
if(bNeedExchange)
{
ChangeImage(iDownIndex,MyImageList->IndexOfObject(Sender));
bNeedExchange=false;
UpdateDebugInformation();
CheckIfAlreadyDone();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ImageMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if(bAlreadyDone // 如果已完成
|| !CheckBox3->Checked) // 不在自由移動模式,不啟動以下程式
return;

TImage *img=(TImage*)Sender;
img->Left=iImageX;
img->Top=iImageY;
bMouseDown=false;
bNeedExchange=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
bNeedExchange=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckBox3Click(TObject *Sender)
{ // 在自由移動模式,所有的圖都顯示,在非自動移動模式,有一個圖是隱藏的
((TImage*)MyImageList->Objects[InVisibleIndex])->Visible=CheckBox3->Checked;
}
//---------------------------------------------------------------------------
[/code]

VMASKVMIO-Server / HMI / SECS/GEMblog.yam.com/dlleedllee's StatPlus
------
http://www.ViewMove.com
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-06-07 23:15:20 IP:59.105.xxx.xxx 訂閱
rocketronnie: 您好!我是RR7788 (私密留言<!-- 私密留言 -->) 2008-06-07 00:19:27
您好! 關於您發表的"排圖小遊戲" 我實在是看不懂原理~"~ 我是指程式碼而不是元件! 比如精采C 一書裡的智慧盤其移動陣列: //建立移動陣列資料 int table[9][9] = { {0, 1, 0, 1, 0, 0, 0, 0, 0}, {1, 0, 1, 0, 1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 1, 0, 0, 0}, {1, 0, 0, 0, 1, 0, 1, 0, 0}, {0, 1, 0, 1, 0, 1, 0, 1, 0}, {0, 0, 1, 0, 1, 0, 0, 0, 1}, {0, 0, 0, 1, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 0, 1, 0, 1}, {0, 0, 0, 0, 0, 1, 0, 1, 0} }; (在3*3裡也就是1~9,1可以移動到2,4) 在您的程式碼裡我看不出來是哪行.. 還有提示(DEBUG)也看不太懂.. 可以請您詳細一點的說明一下嗎? 因為我怕我看不太懂.. 感恩!!


RR7788, 您好,

不好意思,因為程式都在 Delphi.Ktop,有問題還是在此問會比較好,我也選擇在此回覆。

在我程式中 PartPictureUnit.cpp 第 146-149
img->On Click=MyImageClick;
img->On MouseDown=ImageMouseDown;
img->On MouseMove=ImageMouseMove;
img->On MouseUp=ImageMouseUp;

主要設定 Image 的事件,
MouseDown/Move/Up 主要用在自由移動(應該不是您想問的內容)
Click 主要作的就是點圖移到附近的空位上,也就是您想問的部分。

MyImageClick() 在 第 211 行先找出是那個 Image 被點到,
因為 Sender 就是被點到的 Image 元件指標,在事前已將

所有 Image 都放在 MyImageList 內,所以用 IndexOfObject(Sender) 就可以取得是分割出來的第幾個小圖。

第 215-223 就是判斷點到的圖可不可以移,
我的作法是,
因為空位只有一個,所以,最多只有 4 個位置可以移到此空位,因此,
在確定好空位後,就把可以移入的 4 個位置放在
ChangeableIndex[ ] 內,
就作位置的比對,確認所點的圖是否在這 4 個位置,
如果不是,就不理會此次的圖檔 Click
如果是,就移動圖檔
ChangeImage(InVisibleIndex,ThisIndex);
更新看空位的位置 InVisibleIndex=ThisIndex;
更新可移位空位的位置 UpdateChangeableIndex();
更新 DEBUG 資訊(顯示目前小圖的編號) UpdateDebugInformation();
檢查是否已排好 CheckIfAlreadyDone();

我想,應該不難,在 IDE 好好的單步 Trace,查看/記錄變數變化的狀況,就會更明白。
VMASKVMIO-Server / HMI / SECS/GEMblog.yam.com/dlleedllee's StatPlus
------
http://www.ViewMove.com
rr7788
一般會員


發表:2
回覆:6
積分:1
註冊:2008-05-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-06-09 22:26:33 IP:218.175.xxx.xxx 訂閱
感謝您的答覆^^

其實我是看到您的"上次登入時間"想說您可能沒空常來這網站
想說BLOG可能會比較常上所以才貼到那邊的...

順便再請教一下
38~81行 的功能...
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-06-09 22:59:58 IP:59.105.xxx.xxx 訂閱
UpdateChangeableIndex() 就是更新可移空位的位置
以目前空位的位置,其上下左右為可移到空位的位置,
如果已在最上,當然,就無法由其上面移下圖。
同理己在最下,也無法由其下面移上圖,
同樣左右也是,就是作這些判斷而已。
此函式原有的註解應該夠清楚了。

ChangeImage() 就是把兩個影像位置互換
所以記錄了兩張圖的位置,並互換,
其中,因為我把圖的編號放在一個 StringList 內,並把圖放在它的 ObjectList 內,
所以,多了這個部分的處理。

在發表過的文提問或回覆,我會收到 EMail 通知,就會知道有人回覆了。
Blog 提問... 我 Blog 設的 EMail 是 Yahoo,我並不會去 Check Yahoo 的 EMail,因為垃圾信太多了。

VMASKVMIO-Server / HMI / SECS/GEMblog.yam.com/dlleedllee's StatPlus
------
http://www.ViewMove.com
系統時間:2024-03-29 19:44:10
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!