欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

如何使用C#編寫(xiě)拼圖游戲-創(chuàng)新互聯(lián)

今天就跟大家聊聊有關(guān)如何使用C#編寫(xiě)拼圖游戲,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

成都創(chuàng)新互聯(lián)公司專(zhuān)業(yè)為企業(yè)提供涵江網(wǎng)站建設(shè)、涵江做網(wǎng)站、涵江網(wǎng)站設(shè)計(jì)、涵江網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、涵江企業(yè)網(wǎng)站模板建站服務(wù),10多年涵江做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

如何使用C#編寫(xiě)拼圖游戲

正文:

拼圖是一個(gè)非常經(jīng)典的游戲,基本每個(gè)人都知道他的玩法,他的開(kāi)始,運(yùn)行,結(jié)束。那么,當(dāng)我們想要做拼圖的時(shí)候如何入手呢?答案是:從現(xiàn)實(shí)出發(fā),去描述需求(盡量描述為文檔),當(dāng)我們擁有了全面的需求,就能夠提供可靠的策略,從而在代碼中實(shí)現(xiàn),最終成為作品!

(一)需求: (這個(gè)需求書(shū)寫(xiě)較為潦草,為廣大小白定制,按照最最最普通人的思維來(lái),按照參與游戲的流程來(lái))

   1.圖片:我們玩拼圖 最起碼有個(gè)圖

   2.切割:拼圖不是一個(gè)圖,我們需要把一個(gè)整圖它切割成N*N的小圖

   3.打亂:把這N*N的小圖打亂順序,但是要保證通過(guò)游戲規(guī)則行走能還原回來(lái)

   4.判斷:判拼圖成功

   5.交互:我們使用哪一種交互方式,這里我選擇鼠標(biāo)點(diǎn)擊

      6.展示原圖片完整的縮略圖

以上為基本功能,以下為擴(kuò)展功能

     7.記錄步數(shù):記錄完成需要多少步

     8.更換圖片:一個(gè)圖片玩久了我們是不是可以換一換啊 哈哈

    9.選擇難度:太簡(jiǎn)單?不要!3*3搞定了有5*5,5*5搞定了有9*9,舍友挑戰(zhàn)最高難度 3000多步,心疼我的鼠標(biāo)TAT

(二)分析:

有了需求,我們就可以分析如何去實(shí)現(xiàn)它(把現(xiàn)實(shí)需求映射在計(jì)算機(jī)中),其中包括:

1.開(kāi)發(fā)平臺(tái):這里選擇C#語(yǔ)言

 1).存儲(chǔ):其中包括我們要存什么?我們用什么結(jié)構(gòu)存?我們反觀需求,會(huì)發(fā)現(xiàn),有一些需要存儲(chǔ)的資源

      圖片:使用 Image 對(duì)象存儲(chǔ)

      單元(原圖片切割后的子圖像集合):自定義結(jié)構(gòu)體 struct Node ,其中包括Image對(duì)象用來(lái)存儲(chǔ)單元小圖片,和用整形存儲(chǔ)的編號(hào)(切割以后,每個(gè)小單元都弄個(gè)編號(hào),利于檢驗(yàn)游戲是否完成)。

      各單元(原圖片切割后的子圖像集合):使用二維數(shù)組(像拼圖,五子棋,消消樂(lè),連連看,俄羅斯方塊等平面點(diǎn)陣游戲都可以用他來(lái)存儲(chǔ),為什么?因?yàn)殚L(zhǎng)得像嘛?。﹣?lái)存儲(chǔ)

      難度:使用自定義的枚舉類(lèi)型(簡(jiǎn)單and普通and困難)存儲(chǔ)

      步數(shù):整形變量 int Num存儲(chǔ) 

  有了存儲(chǔ),我們就可以去思考模塊的劃分(正確的邏輯劃分已于擴(kuò)展,也可以使通信變得更加清晰)并搭建,并實(shí)現(xiàn)各模塊涉及到的具體算法

首先程序的模塊分為四個(gè):

  邏輯型:

    1.拼圖類(lèi):用于描述拼圖

    2.配置類(lèi):存儲(chǔ)配置變量

  交互型:

    3.游戲菜單窗口:進(jìn)行菜單選項(xiàng)

    4.游戲運(yùn)行窗口:游戲的主要界面

如何使用C#編寫(xiě)拼圖游戲

  1.通過(guò)游戲菜單可以操縱配置,如難度或圖片。

  2.運(yùn)行窗口可以訪問(wèn)并獲得游戲配置,并利用其對(duì)應(yīng)構(gòu)造拼圖對(duì)象。

  3.用戶(hù)通過(guò)運(yùn)行窗口進(jìn)行交互,間接使拼圖對(duì)象調(diào)用移動(dòng)方法,獲得圖案方法

  看代碼的同學(xué),我覺(jué)得最有問(wèn)題的地方,不合理的地方就是把 難度的枚舉類(lèi)型寫(xiě)在了拼圖類(lèi)中,應(yīng)該寫(xiě)在配置類(lèi)中,或單獨(dú)成類(lèi),讀者們自行更改

 public enum Diff //游戲難度
 {
  simple,//簡(jiǎn)單
  ordinary,//普通
  difficulty//困難
 }

我們可以認(rèn)為,配置類(lèi)就像數(shù)據(jù)存儲(chǔ),而拼圖類(lèi)呢作為邏輯處理,菜單和運(yùn)行窗口作為表現(xiàn)用于交互,我承認(rèn)這種設(shè)計(jì)不是很合理,但是在問(wèn)題規(guī)模不夠大的時(shí)候,過(guò)分的考慮設(shè)計(jì),會(huì)不會(huì)使程序變得臃腫?我想一定是有一個(gè)度,具體是多少,我不得而知,但我感覺(jué),針對(duì)這個(gè)程序,實(shí)現(xiàn)就好,沉迷設(shè)計(jì)(套路型),有時(shí)得不償失。(個(gè)人不成熟的小觀點(diǎn))

(三)代碼實(shí)現(xiàn):

說(shuō)明:本塊重點(diǎn)描述 Puzzle(拼圖)類(lèi)與游戲運(yùn)行類(lèi)的具體實(shí)現(xiàn)及實(shí)體通訊:

拼圖的構(gòu)造方法:

1.賦值 :

public Puzzle(Image Img,int Width, Diff GameDif)

// 拼圖的圖片,寬度(解釋?zhuān)赫叫蔚倪呴L(zhǎng),單位是像素,名字有歧義,抱歉),游戲的難度

 游戲的難度決定你分割的程度,分割的程度,決定你存儲(chǔ)的數(shù)組的大小,如簡(jiǎn)單對(duì)應(yīng)3行3列,普通對(duì)應(yīng)5行5列,困難對(duì)應(yīng)9行9列

 switch(this._gameDif)
  {
  case Diff.simple:    //簡(jiǎn)單則單元格數(shù)組保存為3*3的二維數(shù)組
   this.N = 3;
   node=new Node[3,3];
   break;
  case Diff.ordinary:   //一般則為5*5
   this.N = 5;
   node = new Node[5, 5];
   break;
  case Diff.difficulty:  //困難則為9*9
   this.N = 9;
   node = new Node[9, 9];
   break;
  }

2.分割圖片

 //分割圖片形成各單元保存在數(shù)組中
  int Count = 0;
  for (int x = 0; x < this.N; x++)
  {
  for (int y = 0; y < this.N; y++)
  {

   node[x, y].Img = CaptureImage(this._img, this.Width / this.N, this.Width / this.N, x * (this.Width / this.N), y * (this.Width / this.N));
   node[x, y].Num = Count;
   Count++;
  }
  }

其實(shí)對(duì)單元數(shù)組進(jìn)行賦值的過(guò)程,使用雙層for循環(huán)對(duì)二維數(shù)組進(jìn)行遍歷操作,然后按序賦值編號(hào)node[x,y].Num;

然后對(duì)node[x,y].Img,也就是單元的小圖片賦值,賦值的方法是,C#的圖像的類(lèi)庫(kù),寫(xiě)一個(gè)截圖方法,使用這個(gè)方法,將大圖中對(duì)應(yīng)對(duì)位置的對(duì)應(yīng)大小的小圖截取下來(lái),并保存在node[x,y].Img中;

width/N是什么?是邊長(zhǎng)除以行數(shù),也就是間隔嘛,間隔也就是每個(gè)單元的邊長(zhǎng)嘛!然后起始坐標(biāo)(X,Y)起始就是在說(shuō),隔了幾個(gè)單元后,我的位置,

即 :(x,y)=(單元邊長(zhǎng)*距離起始X軸相距單元數(shù),單元邊長(zhǎng)*距離起始點(diǎn)Y軸相距單元數(shù));

關(guān)于此類(lèi)問(wèn)題,希望讀者能夠多畫(huà)畫(huà)圖,然后自然就明白了;

public  Image CaptureImage(Image fromImage, int width, int height, int spaceX, int spaceY)

如何使用C#編寫(xiě)拼圖游戲

主要邏輯:利用DrawImage方法:

//創(chuàng)建新圖位圖 
 Bitmap bitmap = new Bitmap(width, height);
//創(chuàng)建作圖區(qū)域 
Graphics graphic = Graphics.FromImage(bitmap);
//截取原圖相應(yīng)區(qū)域?qū)懭胱鲌D區(qū) 
 graphic.DrawImage(fromImage, 0, 0, new Rectangle(x, y, width, height), GraphicsUnit.Pixel);
//從作圖區(qū)生成新圖 
 Image saveImage = Image.FromHbitmap(bitmap.GetHbitmap());

分割了以后,我們要做一個(gè)特殊處理,因?yàn)槲覀冎?,總有那么一個(gè)位置是白的吧?我們默認(rèn)為最后一個(gè)位置,即node[N-1,N-1];

就是寫(xiě)改成了個(gè)白色的圖片,然后四周的邊線都給畫(huà)成紅色,已于被人發(fā)現(xiàn),顯著一些,之前的其他單元我也畫(huà)了邊線,但是是白色,也是為了在拼圖的觀賞性上得到區(qū)分。該代碼不做介紹。

3.打亂圖片:

其實(shí)就是將二維數(shù)組打亂,我們可以采取一些排序打亂方法,但是請(qǐng)注意!不是每一種打亂都能夠復(fù)原的!

那么如何做到可行呢?方法理解起來(lái)很簡(jiǎn)單,就是讓我們的電腦在開(kāi)局之前,將完整的有序的單元按照規(guī)則中提供的行走方式進(jìn)行無(wú)規(guī)則,大次數(shù)的行走!也就是說(shuō)這種方法一定能走回去!

先理解,具體打亂方法,在后面講解。

移動(dòng)方法(Move):

拼圖游戲中方格的移動(dòng),其實(shí)就是兩個(gè)相鄰單元的交換,而這兩個(gè)單元中,必定存在一個(gè)白色單元(即上面提到的node[N-1,N-1]單元,他的編號(hào)為N*N-1,建議自己動(dòng)筆算一算)

所以我們的判斷條件是,如果移動(dòng)一個(gè)方塊,他的上下左右四個(gè)方向中,一旦有一個(gè)相鄰的是白色單元,即N*N-1號(hào)單元,則與其交換。這是基本邏輯,但不包括約束條件,當(dāng)我們的數(shù)組達(dá)到邊界的時(shí)候,我們就不能對(duì)越界數(shù)據(jù)進(jìn)行訪問(wèn),如當(dāng)單元為node[0,0]時(shí),你就不能對(duì)他上面和右面的數(shù)據(jù)進(jìn)行訪問(wèn),因?yàn)镹ode[-1,0] Node[0,-1]都會(huì)越界,發(fā)生異常

移動(dòng)成功,返回TRUE

移動(dòng)失敗,返回FALSE

/// <summary>
 /// 移動(dòng)坐標(biāo)(x,y)拼圖單元
 /// </summary>
 /// <param name="x">拼圖單元x坐標(biāo)</param>
 /// <param name="y">拼圖單元y坐標(biāo)</param>
 public bool Move(int x,int y)
 {
  //MessageBox.Show(" " + node[2, 2].Num);
  if (x + 1 != N && node[x + 1, y].Num == N * N - 1)
  {
  Swap(new Point(x + 1, y), new Point(x, y));
  return true;
  }
  if (y + 1 != N && node[x, y + 1].Num == N * N - 1)
  {
  Swap(new Point(x, y + 1), new Point(x, y));
  return true;
  }  
  if (x - 1 != -1 && node[x - 1, y].Num == N * N - 1)
  {
  Swap(new Point(x - 1, y), new Point(x, y));
  return true;
  } 
  if (y - 1 != -1 && node[x, y - 1].Num == N * N - 1)
  {
  Swap(new Point(x, y - 1), new Point(x, y));
  return true;
  }
  return false;
  
 }

交換方法(Swap):

交換數(shù)組中兩個(gè)元素的位置,該方法不應(yīng)該被類(lèi)外訪問(wèn),顧設(shè)置為private私有權(quán)限

 //交換兩個(gè)單元格
 private void Swap(Point a, Point b)
 {
  Node temp = new Node();
  temp = this.node[a.X, a.Y];
  this.node[a.X, a.Y] = this.node[b.X, b.Y];
  this.node[b.X, b.Y] = temp;
 }

打亂方法:

前面提到,其實(shí)就是讓電腦幫著亂走一通,說(shuō)白了就是大量的調(diào)用Move(int X,int y)方法,也就是對(duì)空白位置的上下左右四個(gè)相鄰的方塊中隨機(jī)抽取一個(gè),并把它的坐標(biāo)傳遞給Move使其進(jìn)行移動(dòng),同樣要進(jìn)行越界考慮,這樣的操作大量重復(fù)!代碼自己看吧 ,利用隨機(jī)數(shù)。

/// <summary>
 /// 打亂拼圖
 /// </summary>
 public void Upset()
 {
  int sum = 100000;
  if (this._gameDif == Diff.simple) sum = 10000;
  //if (this._gameDif == Diff.ordinary) sum = 100000;
  Random ran = new Random();
  for (int i = 0, x = N - 1, y = N - 1; i < sum; i++)
  {
  long tick = DateTime.Now.Ticks;
  ran = new Random((int)(tick & 0xffffffffL) | (int)(tick >> 32)|ran.Next());
  switch (ran.Next(0, 4))
  {
   case 0:
   if (x + 1 != N)
   {
    Move(x + 1, y);
    x = x + 1;
   }
    
   break;
   case 1:
   if (y + 1 != N)
   {
    Move(x, y + 1);
    y = y + 1;
   } 
   break;
   case 2:
   if (x - 1 != -1)
   {
    Move(x - 1, y);
    x = x - 1;
   } 
   break;
   case 3:
   if (y - 1 != -1)
   {
    Move(x, y - 1);
    y = y - 1;
   }
   break;
  }

  }
 }

返回圖片的方法:

當(dāng)時(shí)怎么起了個(gè)這樣的鬼名字。。。DisPlay。。。

這個(gè)方法與分割方法剛好相背,這個(gè)方法其實(shí)就是遍歷數(shù)組,并將其進(jìn)行組合,組合的方法很簡(jiǎn)單,就是將他們一個(gè)一個(gè)的按位置畫(huà)在一張與原圖相等大小的空白圖紙上!最后提交圖紙,也就是return一個(gè)Image;

 public Image Display()
 {
  Bitmap bitmap = new Bitmap(this.Width, this.Width);
  //創(chuàng)建作圖區(qū)域 
  Graphics newGra = Graphics.FromImage(bitmap);
  for (int x = 0; x < this.N; x++)
  for (int y = 0; y < this.N; y++)
   newGra.DrawImage(node[x, y].Img, new Point(x * this.Width / this.N, y * this.Width / this.N));
  return bitmap;
 }

同樣利用的是DrawImage方法,知道如何分割,這個(gè)應(yīng)該很容易理解,自己算一算,在紙上比劃比劃就明白了;

判斷方法:

該方法很容易理解,就是按序按序!遍歷所有單元,如果他們的結(jié)果中有一個(gè)單元的編號(hào)

node[x, y].Num 不等于遍歷的序號(hào),那么說(shuō)明,該單元不在原有位置上,即整個(gè)圖片還沒(méi)有完成,我們就可以直接返回假值false
如果所有遍歷結(jié)果都正確,我們可認(rèn)為,圖片已復(fù)原,此時(shí)返回真值true

 public bool Judge()
 {
  int count=0;
  for (int x = 0; x < this.N; x++)
  {
  for (int y = 0; y < this.N; y++)
  {
   if (this.node[x, y].Num != count)
   return false;
   count++;
  }
  }
  return true;
 }

游戲運(yùn)行窗口:即游戲玩耍時(shí)用于交互的窗口

這里只講一個(gè)方法:即當(dāng)接受用戶(hù)鼠標(biāo)點(diǎn)擊事件時(shí)我們應(yīng)該怎么處理并作出什么樣反應(yīng)

其實(shí)說(shuō)白了就這句難懂:

puzzle.Move(e.X / (puzzle.Width / puzzle.N), e.Y / (puzzle.Width / puzzle.N))

調(diào)用了移動(dòng)方法,移動(dòng)方塊

橫坐標(biāo)為:e.X / (puzzle.Width / puzzle.N)
縱坐標(biāo)為:e.Y / (puzzle.Width / puzzle.N)

我們編程中的整數(shù)除法和數(shù)學(xué)里的除法是不一樣的!比如10/4數(shù)學(xué)上等于2余2或者2.5,計(jì)算機(jī)里直接就是等于2了,只取整數(shù)部分

如何使用C#編寫(xiě)拼圖游戲

行數(shù)=行坐標(biāo) / 方塊邊長(zhǎng)

列數(shù)=列坐標(biāo) / 方塊邊長(zhǎng)

我們看P1,P2這兩點(diǎn)

P1:40/30*30=1
P2:50/30*30=1

我們會(huì)發(fā)現(xiàn)同在一個(gè)單元格中,無(wú)論點(diǎn)擊哪個(gè)位置,通過(guò)這個(gè)算法都能轉(zhuǎn)化為
同一個(gè)坐標(biāo)。

(e.x,e.y)為鼠標(biāo)點(diǎn)擊事件點(diǎn)擊坐標(biāo)

 private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
 {
  if (puzzle.Move(e.X / (puzzle.Width / puzzle.N), e.Y / (puzzle.Width / puzzle.N)))
  {
  Num++;
  pictureBox1.Image = puzzle.Display();
  if (puzzle.Judge())
  { 
   if (MessageBox.Show("恭喜過(guò)關(guān)", "是否重新玩一把", MessageBoxButtons.OKCancel) == DialogResult.OK)
   {
   Num = 0;
   puzzle.Upset();
   pictureBox1.Image = puzzle.Display();
   
   }
   else
   {
   Num = 0;
   closefather();
   this.Close();
   }

  }

  }
  NumLabel.Text = Num.ToString();
 }

好,那么大體的邏輯,程序中最需要思考的算法已經(jīng)講完了,還有不太懂的地方,歡迎交流~么么噠~

如何使用C#編寫(xiě)拼圖游戲

如何使用C#編寫(xiě)拼圖游戲

加了點(diǎn)小功能 音樂(lè)歷史成績(jī)

看完上述內(nèi)容,你們對(duì)如何使用C#編寫(xiě)拼圖游戲有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,感謝大家的支持。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)頁(yè)標(biāo)題:如何使用C#編寫(xiě)拼圖游戲-創(chuàng)新互聯(lián)
文章來(lái)源:http://aaarwkj.com/article24/deodce.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、品牌網(wǎng)站制作、網(wǎng)站建設(shè)外貿(mào)網(wǎng)站建設(shè)、域名注冊(cè)、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷(xiāo)型網(wǎng)站建設(shè)
91精品超碰人人在线公开| 亚洲码av一区二区三区| 未满十八禁止在线播放| 国产中文字幕一区久久| 蜜桃午夜精品一区二区三区| 国产亚洲欧美日韩精品| 欧美黄片在线免费观看| 亚洲精品黄色片中文字幕| 宫部凉花中文字幕在线| 欧美香蕉高清视频免费| 中文日本强暴人妻另类视频| 日本中文字幕一区在线观看| 丰满少妇在线观看网站| 日韩高清av一区二区三区| 夜色一区二区av人片| 久久久久久极精品久久久| 九九蜜桃视频香蕉视频| 亚洲天堂av在线观看| 国产成人精品久久一区二区| 国产91在线视频播放| 后入动漫视频在线观看| av天堂资源在线播放| 亚洲精品成人久久网| 日韩精品高清不卡一区二区三区| 亚洲乱码中文字幕久久| 欧美国产日韩一区二区三区视频| 激情五月婷婷久久激情| 粉嫩av北条麻妃电影| 日本束缚人妻一区二区三区| 91人妻一区二区三区久久| 五月婷婷av综合激情| 天天躁日日躁夜夜躁夜夜| 国产欧美又粗又猛又爽老| 亚洲国产精品视频自拍| 少妇人妻偷人精品系列| 日韩视频一区二区三区系列| 中文字幕人妻丝袜一区一三区| 激情视频一区二区三区| 大陆av剧情网站在线观看| 国产精品日产三级在线观看| 久久精品夜夜夜夜夜久久|