程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> C語言基礎知識 >> 用游戲串起程序員的基本功之二

用游戲串起程序員的基本功之二

編輯:C語言基礎知識

  第一篇我們用數組實現了洗牌的步驟。當然還有其他的方法。這也就是編程的帶給我們的樂趣——靈活,自由。只要你想不得到,沒有你做不到的。
  
  今天我們就來實現第二步。擲色子,發牌。
  
  擲色子的問題,其實很簡單,但涉及到動畫制作的原理。所以我們先來補充些這方面的知識。
  
  我們知道,人的視覺都有一種現象,比如當你在黑暗中看燈泡時,忽然燈泡熄滅了,但燈泡發光的影像還會在我們眼前停幾秒鐘,這就是我們熟知的“視覺暫留效果”。我們所看到的電視、電影,包括我們說熟知的flash,Director等動畫制作軟件,都是依靠這個效果才實現的。當我們在高速狀態下(一般是每秒24幀),按一定的順序切換內容相近和連貫的一組圖片時,我們看到的不是一張張單獨的圖片影像,而是一段連貫的動畫。
  
  根據這個原理。我們擲色子的動畫也就很輕易實現了。只要我們快速的變換不同點數的色子6個面,就會讓人覺得好象是真實的轉動著的色子了。你不用擔心,運行速度的問題,只要你的機子能看vcd,一般都沒問題。先看看下面的代碼框架:
  
   void zhisaizi()
  {
   int i;
   i= (int)5*rand()+1;
   switch(i)
  case 1:
   //載入第一張圖片
  case 2:
   //載入第二張圖片
  case 3:
  。。。。。。//省略中間過程
  case 6:
   //載入第六張圖片
  }
  至於怎樣載入和現實圖像不是我們本篇的主要內容,大家可以學習《windows程序設計》這本書。
  
  對於發牌的問題,我想大家應該不會在有問題了。這裡我只給出代碼,其中有具體的注釋,就不解釋了。下面是代碼:
  
   int apai[13],bpai[13];
  //apai,bpai分別代表兩玩家手中的牌,假如你做的是四個人
  //的麻將,可你在自由擴展
  
  void fapai()
  {
   int a,b;
   int i;//i代表發牌的起始位置
   if((i/2)= =0)//是否為偶數
  apai[a++]=pai[i++]; //雙數牌發給a玩家
   else
  bpai[b++]=pai[i++];//單數牌發給b玩家
  }
  下面是我們本篇要講的重點:就是在玩家都拿到牌之後,我們需要按順序擺放好牌。這裡我們會更加深入的談到數據結構方面的一些知識,希望大家專心。
  
  對於這個問題實質上也就是排序的問題。我們前面用136個整型數來代表136張牌,可以用1~136分別表示1~9萬,1~9條,1~9餅,以及東南西北紅中發財,也可以用1~39中的個位數分別對應著和他相等的1~9萬,如3、13、23、33分別代表四張3萬。其他以此類推。剩余的數字來表示東南西北紅中發財。這個就可以由自己決定了。在此我們選擇第一種方法來描述問題。
  
  那麼就請怎樣排序呢?最輕易想到的方法是:取得一個數,和他前面的所有數比較,直到找到一個前面的數比它小,後面的數比他大的位置,並將其放入其中。再取得下一個數,繼續上面的步驟。
  
  示例如下:
  
   8 7 4 3 6 1 //是要排序的數值
  7 8 4 3 6 1 //第一次,取得7,小於前面的8,交換位置
  7 4 8 3 6 1 //第二次,取得4,小於前面的8,交換位置
  4 7 8 3 6 1 //第三次,小於再前面的7,交換位置
  4 7 3 8 6 1 //第四次,取得3,小於前面的8,交換位置
  4 3 7 8 6 1 //第五次,小於再前面的7,交換位置
  3 4 7 8 6 1 //第六次,小於再前面的4,交換位置
  3 4 7 6 8 1 //第七次,取得6,小於前面的8,交換位置
  3 4 6 7 8 1 //第八次,小於再前面的7,交換位置
  3 4 6 7 1 8 //第九次,取得1,小於前面的8,交換位置
  3 4 6 1 7 8 //第十次,小於再前面的7,交換位置
  3 4 1 6 7 8 //第十一次,小於再前面的6,交換位置
  3 1 4 6 7 8 //第十二次,小於在前面的4,交換位置
  1 3 4 6 7 8 //第十三次,小於再前面的3,交換位置
  
  我們把這種方法叫做“插入排序法”。下面是源代碼。
  
  void paixu ()// 用插入排序法
  {
   for (int i = 1; i <=13; i++)
   {
  int temp = apai[i];//取得一個數
  int j;
  for ( j = i; j > 0 && temp < apai[j - 1]; j--) //和他前面的每一個數進行比較,
   apai[j] = apai[j - 1]; //假如這個數小於她前面的數就交換
   apai[j] = temp;//插入到正確位置
   }//end for
  }//end
  我們先來分析一下這種算法。可以看到,為了找到合適的插入位置,我們要用取得的數值與他前面的所有數值進行比較,並將進行多次的交換位置。尤其是當較小的數值放得越靠後時,交換到合適的位置所需的時間越長,如示例中的6和1,位置都靠後且相鄰,但6放置到合適的位置只用了兩步,而1放置到合適的位置卻用了五步。
  
  有沒有其他的方法呢?針對比較次數和交換次數較多,我們可以用另一種“折半插入排序法”。基本思路是:為了減少比較的次數,我們不用每個數都比較,而是先找到所取得的數值在數組中的位置,並找到它前面已排好順序的數組的中間的一個數值,比較兩數,假如取得的數值大,就與後面的數值的中間數值比較,一直下去,直到找到合適的位置;同理假如所取得的數值小,就與前面的數值的中間數值比較,一直下去,直到找到合適的位置。
  
  下面是示例:
  
  
   8 7 4 3 6 1 //是要排序的數值
  7 8 4 3 6 1 //第一次,取得7,小於前面的8,交換位置
  7 4 8 3 6 1 //第二次,取得4,小於前面的8,交換位置
  4 7 8 3 6 1 //第三次,小於再前面的7,交換位置
  3 4 7 8 6 1 //第四次,取得3,小於前面的數組(4 7 8)中的中間數值7比較,小於7,所以比較數組(4 7)中間數值4,大於4,並交換到合適位置
  3 4 6 7 8 1 //第五次,取得6,小於前面的數組(3 4 7 8)中的7,再與再靠前的數組(3 4 7)中間值4比較,大於4,交換位置
  1 3 4 7 8 6 //第六次,取得1,小於再前面的數組(3 4 6 7 8)中間值6,再與數組
  (3 4 6)中間值4比較,小於4,最後與數組(3 4)中間值3 比較,
  小於3,交換位置
  
  很明顯這種方法的減少了比較的次數,但交換次數仍沒減少。下面是其代碼:
  
   void paixu()//用折半排序法
  {
   for (int i = 1; i < =13; i++)
   {
  int temp = apai[i]; //取得數值
  int low = 0, high = i - 1;//low,high,分別表示比較范圍的上下限
   while (low <= high)//折半查找
  {
   int mid = (low + high) / 2; //取得中間位置
   if ( temp < apai[mid]) //假如小於中間位置的值
  high = mid - 1; //從新確定下限
   else //假如大於中間位置的值
  low = mid + 1; //從新確定上限
  }//end while
  for (int j = i - 1; j >= low; j--)
   apai[j + 1] = apai[j]; //記錄後移
   apai[low] = temp; //插入到合適位置
   }//end for
  }//end
 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved