全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1290
推到 Plurk!
推到 Facebook!

圖片隨機的移動?

尚未結案
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-08-07 18:03:45 IP:220.142.xxx.xxx 未訂閱
請問各位先進,如何可以讓一個image能隨機的往八個方位去移動(如"米"字型)?另外,image的移動如果要以「公分」計算(如移動1公分、2公分…),不知應該怎麼做?懇請賜教!或指點一個方向,謝謝!
nlj859
資深會員


發表:139
回覆:375
積分:322
註冊:2004-03-20

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-08-07 19:07:40 IP:219.80.xxx.xxx 未訂閱
Hello enu,    請參考底下做法: *在form上隨機跳躍 假設你的from大小是640x480. 為何要減掉Image1->Width和Image1->Height? 原因是因為不要讓圖片超出form外面.
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Image1->Left=random(640-Image1->Width);
Image1->Top=random(480-Image1->Height);
}
* 米字型跳躍:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
int i=random(9) 1;
switch (i)
{
  case 1:  Image1->Left=0;   Image1->Top=0; break;
  case 2:  Image1->Left=100; Image1->Top=0; break;
  case 3:  Image1->Left=200; Image1->Top=0; break;
  case 4:  Image1->Left=0;   Image1->Top=100; break;
  case 5:  Image1->Left=100; Image1->Top=100; break;
  case 6:  Image1->Left=200; Image1->Top=100; break;
  case 7:  Image1->Left=0;   Image1->Top=200; break;
  case 8:  Image1->Left=100; Image1->Top=200; break;
  case 9:  Image1->Left=200; Image1->Top=200;
}
}
* 怎麼算出1公分? 我以小畫家去看,32x32剛好是1mx1cm
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
Image1->Left =32;
}    void __fastcall TForm1::FormCreate(TObject *Sender)
{
Image1->Left=0;
}
發表人 - nlj859 於 2004/08/07 19:20:08
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-08-11 09:30:37 IP:163.27.xxx.xxx 未訂閱
謝謝nlj859先生, 不知道還有沒有先進對於image移動以公分計有其方法的? 小弟先用photoimpct去設定一張1cm×1cm的圖片,之後在image中load進來後發現長寬各是38×38,與nlj859先生所說的32×32又有點出入,不知道有沒有那位先進可以提供一點建議的?感激不儘!謝謝! 發表人 - enu 於 2004/08/11 14:53:09
nlj859
資深會員


發表:139
回覆:375
積分:322
註冊:2004-03-20

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-08-11 12:14:15 IP:219.80.xxx.xxx 未訂閱
Hello enu, 可以參考下列文章,或許對你有幫助. http://taiwan.cnet.com/builder/authoring/story/0,2000033954,20004142-20000770c,00.htm http://163.21.31.9/~jdwang/html/1_html/1_1_base.htm
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-08-11 13:48:31 IP:211.76.xxx.xxx 未訂閱
enu 您好:    試試看下列方式是否會比較接近,(Form的Scaled屬性要是true)
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  int n = Form1->PixelsPerInch;
  float pixelsPerCM = (float)n/2.54;  // 1 inch = 2.54 cm
  Form1->Canvas->Rectangle(0, 0, pixelsPerCM, pixelsPerCM);
  ShowMessage(pixelsPerCM);
}
RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====#####
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-08-12 15:46:06 IP:163.27.xxx.xxx 未訂閱
首先感謝nlj859和richtop先生, 從nlj859所提供的資料中也發現了richtop的方法在不同的顯示(如1024×768或800×600),其所呈現的長度亦不同。 小弟再將問題明確的描述一下,看是否有那位先進可以再提供些建議: 一個image(38×38)的小圖片在全螢幕下移動,其可能移動的方向有45、90、135、180、225、270、315、360度等方向(如"米"字型),而其可能移動的距離是1、5 、10、15cm等,但是同一個方向、同一個距離如果已經走過,就不能再走(當然也不能超出form的範圍),直到所有可能移動的方向、距離均走過則停止。 感謝nlj859和richtop先生,小弟根據您們的建議試了幾天,但還是搞不定!不知道還有沒有先進肯指點一下,感激不儘!謝謝!
nlj859
資深會員


發表:139
回覆:375
積分:322
註冊:2004-03-20

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-08-12 16:05:26 IP:163.28.xxx.xxx 未訂閱
引言: 首先感謝nlj859和richtop先生, 從nlj859所提供的資料中也發現了richtop的方法在不同的顯示(如1024×768或800×600),其所呈現的長度亦不同。 我在兩部電腦中試過都是以1024x768的解析度,但是以小畫家來試時一個是32x32,另一個是37x37,我不太曉得這是不是解析度的關係. 小弟再將問題明確的描述一下,看是否有那位先進可以再提供些建議: 一個image(38×38)的小圖片在全螢幕下移動,其可能移動的方向有45、90、135、180、225、270、315、360度等方向(如"米"字型),而其可能移動的距離是1、5 、10、15cm等,但是同一個方向、同一個距離如果已經走過,就不能再走(當然也不能超出form的範圍),直到所有可能移動的方向、距離均走過則停止。 感謝nlj859和richtop先生,小弟根據您們的建議試了幾天,但還是搞不定!不知道還有沒有先進肯指點一下,感激不儘!謝謝!
Hello enu, 現在既然知道你有8個方向且各有4種可能的走法,所以你可以陣列去記錄走過的位置,如bool Direction[8][4];一開始初始值均為false,走過記錄為true. 當然每次走之前要先確認是true還是false. 希望這些建議對你有所幫助.
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-08-12 17:35:05 IP:211.76.xxx.xxx 未訂閱
enu 您好:    嘗試用Windows API:GetDeviceCaps(.),去計算其在目前解析度下,一公分的pixel數(僅算寬度部分),請參考,如下:
void __fastcall TForm1::Button2Click(TObject *Sender)
{ AnsiString msg;      int vSize = GetDeviceCaps(Form1->Canvas->Handle, HORZSIZE); // screen width in mm.
  int vRes  = GetDeviceCaps(Form1->Canvas->Handle, HORZRES ); // pixels of screen width.
  float pixelsPerCM = (float) vRes *10.0 / vSize;      msg.printf("width %d in mm,\npixels: %d,\nPixelsPerCM=%5.2f", vSize, vRes, pixelsPerCM);
  Form1->Canvas->Rectangle(0, 100, pixelsPerCM, 100 pixelsPerCM);      ShowMessage(msg);
}
這也就是說,如果您的目標是要不管在任何解析度下,螢幕上圖片的長度用尺量的結果都要是一公分的話,那麼上述的計算應該就是了。 至於您的圖片,也可以試著在螢幕上量一量是不是接近一公分,以方便判斷是哪一個環節出了問題。 假設上述算法可行,但圖片大小不準,則可以將該Image的長寬重設(令Image->Stretch=true),如此便能在螢幕上出現一個大小接近一公分的正方形。 希望對您能有幫助。 還有您所謂:"但是同一個方向、同一個距離如果已經走過,就不能再走",我不太了解,那是不是往右走一公分之後,就不能再往右走一公分了? RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====#####
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-08-13 10:17:49 IP:163.27.xxx.xxx 未訂閱
再次感謝nlj859和richtop先生, 另外,richtop先生您提到的問題,正是您所想的,也就是往右走一公分之後,就不能再往右走一公分了。因此當所有可能均走過後,程式就會停止。數學程度不好,還有勞您幫忙提供點建議了。謝謝!
nlj859
資深會員


發表:139
回覆:375
積分:322
註冊:2004-03-20

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-08-13 12:26:33 IP:219.80.xxx.xxx 未訂閱
Hello enu, *請問每次固定都是走1, 5, 10, 15cm這4種選擇嗎? 如果是,我想就用記錄的方式去記哪些已走過,哪些沒走過. *往右走1cm之後,就不能再往右走1cm了,那如果是往左走1cm呢? *切到別方向時,是否需照原路徑回來原點,再選擇那個方向去走? 大概是我多慮了,希望不要誤導你.^_^ 發表人 - nlj859 於 2004/08/13 12:29:10
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-08-13 14:07:59 IP:211.76.xxx.xxx 未訂閱
enu 您好:    問題似乎比較清楚了。 不過還有一個疑問要請教: 是不是Image只有 (方向) x (可能的距離) = (8) x (4) = 32 走法,且走過一次就不能再有相同的走法;在隨機且不跑出Form範圍內,看最後Image會在哪裡?    如果是這樣,那可以一個int陣列來存走過的方向與距離, 方向:當成十進位數,比方1-8。 距離:當成個位數,表示某一距離,比方1-4,其中1,2,3,4分別表示1,5,10,15cm。    所以沿方向3走5cm,就能寫成: 3*10 + 2 = 32,(各方向與距離值都不同) 將之存入int path[32]中。 至於可能的方向與要走的距離就隨機產生,比對已經存在path[]中的值,就知道有沒有重複。    這是在方向與可能的距離均有限的情形下,所作的權宜。    其實nlj859的方法能適用於一般的情形,看看您的需要來選擇。    不過我想把真正的走法規則確認之後,這個問題應該能得到解決的。
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-08-13 15:00:46 IP:163.27.xxx.xxx 未訂閱
謝謝nlj859和richtop先生,經由您們的建議,問題解法似手更明確了。 先回答nlj859先生所提的問題,距離的選擇就是固定幾種,而往右走1cm之後,就不能再往右走1cm了,但可以往左走1cm,只要往左走1cm之前並未走過(前提是random剛好產生往左走1cm);此外,切到別方向時,並非回到原點,而是以之前產生的位置繼續走下去,所以才必須注意random後的方向和距離是否超出form的範圍。 小弟的問題應該如richtop先生所整理的,Image只有 (方向) x (可能的距離) = (8) x (4) = 32 走法,且走過一次就不能再有相同的走法;在隨機且不跑出Form範圍內。 如果是這樣,應該如何做比較適當呢?懇請賜教了!感激不儘!
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#13 引用回覆 回覆 發表時間:2004-08-13 22:15:32 IP:211.76.xxx.xxx 未訂閱
enu 您好:    因為還要完成其他事,所以寫了下列的版本供您參考,沒有完全測試過! 就請您自個兒看看,是否能提供您問題解答的參考。 <>< class="code"> //--------------------------------------------------------------------------- struct Direction { int dir; int toGo; }; Direction dirs[32]; int distance[] = {1,5,10,15}; void init() { int index=0; for (int d=0; d<8; d ) { for (int k=0; k<4; k ) { dirs[index].dir = d; dirs[index].toGo = distance[k]; index ; } } } // 方向定義(順時針方向): 0:東,1:東北,2:北,...,依此類推。 int shiftX[]={ 1, 1, 0,-1,-1,-1, 0, 1}; int shiftY[]={ 0,-1,-1,-1, 0, 1, 1, 1}; void getDxDy(int& dx, int& dy, Direction d, float scale=1) // 取x,y方向的相對位移分量 { dx = d.toGo * shiftX[ d.dir ] * scale; dy = d.toGo * shiftY[ d.dir ] * scale; } void exchange(int times) // 隨機交換times次 { int index; Direction temp; for (int k=0; k=Form1->ClientWidth || y<0 || y>=Form1->ClientHeight ) return false; else return true; } bool canMoveTo(int x, int y, Direction dir) // 測試是否可以移去該位置 { int dx, dy; getDxDy(dx, dy, dir); x = dx; y = dy; return ( checkBoundary(x, y) ); } void MoveTo(int &x, int &y, Direction dir) // 真正移動 { int dx, dy; getDxDy(dx, dy, dir); x = dx; y = dy; } int goNext(int &x, int &y) { int found=0; for (int k=0; k<32; k ) { if ( dirs[k].dir>=0 ) // not used. { if ( canMoveTo(x,y,dirs[k]) ) { MoveTo(x, y, dirs[k]); Form1->Canvas->LineTo(x,y); Sleep(500); dirs[k].dir = -1 - dirs[k].dir; // mark used & can be restored. found = 1; } } } return (found); } void __fastcall TForm1::Button1Click(TObject *Sender) { int x=100, y=100, found; init(); exchange(500); Form1->Canvas->MoveTo(x,y); do { found = goNext(x,y); } while ( found!=0 ); //showAll(); } //--------------------------------------------------------------------------- RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====#####
nlj859
資深會員


發表:139
回覆:375
積分:322
註冊:2004-03-20

發送簡訊給我
#14 引用回覆 回覆 發表時間:2004-08-14 16:58:34 IP:219.80.xxx.xxx 未訂閱
Hello enu,    請參考底下程式碼: 程式假設是以1024x768的大小 Unit1.cpp
#include 
#pragma hdrstop
#include "Unit1.h"
const int xy=32;      //以32x32來當1cm
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
}
//---------------------------------------------------------------------------    void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
  if (WayTimes<32)
     {
      Direction=random(8); //8種可能方向
      Distance=random(4);  //4種可能距離
      if (WayChoice[Direction][Distance]==false)
         {
          switch (Distance)
          {
           case 0: DistanceConversion=1;  break; //1cm
           case 1: DistanceConversion=5;  break; //5cm
           case 2: DistanceConversion=10; break; //10cm
           case 3: DistanceConversion=15;        //15cm
          }
          MoveDistance_xy=DistanceConversion*xy;
          bool Go_or_NoGo=Judge();               //判斷是否出界
          if (Go_or_NoGo)
             {
              WayChoice[Direction][Distance]=true;
              MoveToNew();
              WayTimes  ;
              Label1->Caption=WayTimes;
              Label4->Caption=Image1->Left;
              Label5->Caption=Image1->Top;
              Canvas->TextOutA(10,15*WayTimes,(AnsiString)Direction "   " Distance);
             }
         }
     }
   else
     {
      Timer1->Enabled=false;
      ShowMessage("End");
     } 
}
//---------------------------------------------------------------------------    void __fastcall TForm1::FormCreate(TObject *Sender)
{
  randomize();
  Timer1->Interval=100;
  Direction=0;
  Distance=0;
  WayTimes=0;
  for (int i=0;i<8;i  )
      {
       for (int j=0;j<4;j  )
            WayChoice[i][j]=false;
      }
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::Judge()
{
  /*int a=Image1->Left xy MoveDistance_xy;
  int b=Image1->Left-MoveDistance_xy;
  int c=Image1->Top xy MoveDistance_xy;
  int d=Image1->Top-MoveDistance_xy;*/      switch (Direction)
  {
   case 0:
      if (Image1->Left xy MoveDistance_xy>1024)
          return false;
      else
          return true;
   case 1:
      if (Image1->Left xy MoveDistance_xy>1024 || Image1->Top-MoveDistance_xy<0)
          return false;
      else
          return true;
   case 2:
      if (Image1->Top-MoveDistance_xy<0)
          return false;
      else
          return true;
   case 3:
      if (Image1->Left-MoveDistance_xy<0 || Image1->Top-MoveDistance_xy<0)
          return false;
      else
          return true;
   case 4:
      if (Image1->Left-MoveDistance_xy<0)
          return false;
      else
          return true;
   case 5:
      if (Image1->Left-MoveDistance_xy<0 || Image1->Top xy MoveDistance_xy>768)
          return false;
      else
          return true;
   case 6:
      if (Image1->Top xy MoveDistance_xy>768)
          return false;
      else
          return true;
   case 7:
      if (Image1->Left xy MoveDistance_xy>1024 || Image1->Top xy MoveDistance_xy>768)
          return false;
      else
          return true;
   }
}    void __fastcall TForm1::MoveToNew()
{
  switch (Direction)
  {
   case 0: Image1->Left =MoveDistance_xy;                               break;  //0_360
   case 1: Image1->Left =MoveDistance_xy; Image1->Top-=MoveDistance_xy; break;  //45
   case 2:                                Image1->Top-=MoveDistance_xy; break;  //90
   case 3: Image1->Left-=MoveDistance_xy; Image1->Top-=MoveDistance_xy; break;  //135
   case 4: Image1->Left-=MoveDistance_xy;                               break;  //180
   case 5: Image1->Left-=MoveDistance_xy; Image1->Top =MoveDistance_xy; break;  //225
   case 6:                                Image1->Top =MoveDistance_xy; break;  //270
   case 7: Image1->Left =MoveDistance_xy; Image1->Top =MoveDistance_xy;         //315
  }
}
Unit1.h
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include 
#include 
#include 
#include <Forms.hpp>
#include 
#include 
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:        // IDE-managed Components
  TImage *Image1;
  TTimer *Timer1;
  TGroupBox *GroupBox1;
  TLabel *Label2;
  TLabel *Label3;
  TLabel *Label4;
  TLabel *Label5;
  TLabel *Label6;
  TLabel *Label1;
  void __fastcall Timer1Timer(TObject *Sender);
  void __fastcall FormCreate(TObject *Sender);
private:        // User declarations
public:                // User declarations    int Direction;          //8種可能方向
int Distance;           //4種可能距離
int DistanceConversion; //每一種的距離
bool WayChoice[8][4];   //記錄已走過的位置
int WayTimes;           //已用過的次數(最多32次)
int MoveDistance_xy;    //每次所要走的距離
bool __fastcall Judge();
void __fastcall MoveToNew();      __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
有一個問題就是: 因為照你的需求來講,"走過的就不能再走"&"不能超出Form的大小", 但"如果是它走到邊邊角角的位置時,這下發現,死了,以無法回頭,因為可以回頭的那些方法都已經被走過了",那這下程式就永遠走不出去了,永遠沒辦法把8*4=32種走完. 所以當它走到邊邊角角時就很有可能停住不動了. 提供參考. 寫的不好,請多見諒 發表人 -
enu
中階會員


發表:36
回覆:93
積分:55
註冊:2003-10-22

發送簡訊給我
#15 引用回覆 回覆 發表時間:2004-08-23 16:05:39 IP:163.27.xxx.xxx 未訂閱
再次感謝nlj859和richtop先生,從您們提供的參考程式中,晚輩學到不少東西。 nlj859先生最後所提的問題確實如此,不過也只好先暫時如此。但是後來測試您的程式,晚輩的image卻不動了。因此利用richtop先生所提供的參考範例解決了問題,所以只好將分數給richtop先生。(真的好想兩人都給!)
系統時間:2024-06-02 16:44:21
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!