770 likes | 978 Views
陣列. 鄭士康 國立台灣大學 電機工程學系 / 電信工程研究所 / 資訊網路與多媒體研究所. 綱要. 一維陣列 亂數產生器 猜數字遊戲 一維陣列的排序、倒排、搜尋 整個陣列的設值與複製 矩形二維陣列 井字遊戲 Tic-tac-toe * 不規則二維陣列 *高維陣列 foreach 敘述. 綱要. 一維陣列 亂數產生器 猜數字遊戲 一維陣列的排序、倒排、搜尋 整個陣列的設值與複製 矩形二維陣列 井字遊戲 Tic-tac-toe * 不規則二維陣列 *高維陣列 foreach 敘述. p1 = 2; p2 = 3; p3 = 5;
E N D
陣列 鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
綱要 • 一維陣列 • 亂數產生器 • 猜數字遊戲 • 一維陣列的排序、倒排、搜尋 • 整個陣列的設值與複製 • 矩形二維陣列 • 井字遊戲Tic-tac-toe • *不規則二維陣列 • *高維陣列 • foreach 敘述
綱要 • 一維陣列 • 亂數產生器 • 猜數字遊戲 • 一維陣列的排序、倒排、搜尋 • 整個陣列的設值與複製 • 矩形二維陣列 • 井字遊戲Tic-tac-toe • *不規則二維陣列 • *高維陣列 • foreach 敘述
p1 = 2; p2 = 3; p3 = 5; p4 = 7; p5 = 11; p[0] = 2; p[1] = 3; p[2] = 5; p[3] = 7; p[4] = 11; . . . Console.WriteLine(p[i-1]); 前五個質數
p[0] p[1] p[2] p[3] p[4] 一維陣列 • 一維陣列與陣列索引 int[] p = new int [5];
程式Array1D.Program片段 const int N = 5; int[] p = new int[N]; p[0] = 2; p[1] = 3; p[2] = 5; p[3] = 7; p[4] = 11; int i; for (i = 0; i < N; ++i) { Console.WriteLine(p[i]); }
注意事項 • 「索引在陣列的界限之外」 錯誤 • 語意錯誤 • 需要仔細閱讀程式碼,或以偵錯器追蹤索引的變化過程
陣列元素宣告並設值的兩種寫法 int[] p = new int[5] { 2, 3, 5, 7, 11 }; int[] p = { 2, 3, 5, 7, 11 };
程式Array1D2.Program片段 int[] p = { 2, 3, 5, 7, 11 }; int i; for (i = 0; i < p.Length; ++i) { Console.WriteLine(p[i]); }
程式Array1D3.Program片段 Console.Write("輸入年數: "); int n = Int32.Parse(Console.ReadLine()); double[] m = new double[n]; int i; for (i = 0; i < n; ++i) { m[i] = c*Math.Pow(1.0 + p, i+1); } for (i = 0; i < n; ++i) { Console.WriteLine("第{0}年後的本利和為{1}", i+1, m[i]); }
練習 • 寫一程式,用迴圈輸入3位同學成績到一維陣列,再用迴圈把所有成績顯示出來. • 修改上述程式, 使同學人數可以在程式執行時決定.
綱要 • 一維陣列 • 亂數產生器 • 猜數字遊戲 • 一維陣列的排序、倒排、搜尋 • 整個陣列的設值與複製 • 矩形二維陣列 • 井字遊戲Tic-tac-toe • *不規則二維陣列 • *高維陣列 • foreach 敘述
亂數 • 依一定機率分佈隨機產生的數 • 均勻分佈之亂數通常以整數除法的餘數產生 • 亂數產生器 • 亂數種子與亂數數列
UsingRandom.Program片段 int seed = 123; Random rand = new Random(seed); int[] count = new int[10]; for (k = 0; k < 10; ++k) { count[k] = 0; } const int N = 1000; for (i = 0; i < N; ++i) { k = rand.Next() % 10; ++count[k]; }
產生不固定的亂數數列 Random rand = new Random();
練習 • 產生一萬個0到9之間的亂數,統計各點數出現次數,以星號繪出對應長條圖, 每個星號代表出現50次 • 例如: 0 ******************** • ********************* • ******************* • ******************** • ***************** • ********************** • ****************** . . . 9 *********************
綱要 • 一維陣列 • 亂數產生器 • 猜數字遊戲 • 一維陣列的排序、倒排、搜尋 • 整個陣列的設值與複製 • 矩形二維陣列 • 井字遊戲Tic-tac-toe • *不規則二維陣列 • *高維陣列 • foreach 敘述
遊戲規則 • 電腦先隨機產生一個四個位數都不同的四位數作為謎底 • 最高位數字(千位數)可以是0 • 接著使用者猜測一個四位數 • 電腦比較所猜的數字與謎底 • 假設使用者所猜的四個位數中有m位數,不論位置,在謎底中出現;而其中n位數,其數值與位置都與謎底相同,則電腦告知使用者nAmB的訊息 • 使用者產生下一次所猜的數字
nAmB一例 • 謎底為0567 • 所猜數字為5566 • 5、5、6、6均出現在謎底中,所以m等於4 • 其中一個5一個6與謎底的第二與第三位數之位置與數值均相同,所以n等於2 • 電腦顯示2A4B
虛擬碼 1 利用亂數產生一個四位數字都不同的四位數x 2 x的四個位數為xd[0]~xd[3] 3 do { 3.1 使用者輸入所猜四位數y 3.2 決定並輸出nAnB 3.3 if( n == 4 ) { 3.3.1 輸出猜對訊息 3.3.2 break } } while ( 猜測次數未達上限 ) 4 輸出謎底與猜測次數
決定nAmB虛擬碼 // 謎底xd[0]~xd[3] // 使用者輸入yd[0]~yd[3] for(i=0; i<4; ++i) { for(j=0; j<4; ++j) { if( yd[i] != xd[j] ) continue ++m if( i == j ) ++n break } }
第0版GuessingNumber.Program片段 (1/3) xd[0] = '0'; xd[1] = '5'; xd[2] = '6'; xd[3] = '7'; char[] yd = new char[4]; do { Console.Write("猜一個四位數: "); yd = Console.ReadLine().ToCharArray(); ++nGuess; n = 0; m = 0;
第0版GuessingNumber.Program片段 (2/3) for(i=0; i<4; ++i) { for(j=0; j<4; ++j) { if( yd[i] != xd[j] ) continue; ++m; if( i == j ) ++n; break; } } Console.WriteLine("{0}A{1}B", n, m);
第0版GuessingNumber.Program片段 (3/3) if( n == 4 ) { Console.WriteLine("恭喜!您猜對了"); break; } } while( nGuess < maxNGuess );
亂數產生四位數字都不同的四位數:虛擬碼 1 設定陣列d[0]~d[9]為’0’~’9’ 2 for(i=0; i<4; ++i) { do { 產生一個0到9之間的亂數k 檢查d[k]是否與先前的xd元素重複 } while( d[k]已出現過 ) xd[i] = d[k] }
GuessingNumber.Program片段 (1/2) char[] d = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; bool again; Random rand = new Random(); for (i = 0; i < 4; ++i){ do{ k = rand.Next() % 10; again = false;
GuessingNumber.Program片段 (2/2) for(j=0; j<i; ++j){ if (d[k] != xd[j]) continue; again = true; break; } } while( again ); xd[i] = d[k]; }
綱要 • 一維陣列 • 亂數產生器 • 猜數字遊戲 • 一維陣列的排序、倒排、搜尋 • 整個陣列的設值與複製 • 矩形二維陣列 • 井字遊戲Tic-tac-toe • *不規則二維陣列 • *高維陣列 • foreach 敘述
排序、倒排、搜尋 • 進階課程如演算法與資料結構討論的對象 • 一般程式設計的書籍也常介紹初步的方法,作為陣列處理的範例 • 大多現代的程式語言,包括C#,都已有現成的函式庫來完成這些工作 • 只說明如何利用這類函式,而不觸及它們背後的演算法
UsingArrayProcessingFunctions片段 // 排序 Array.Sort(a); // 倒排 Array.Reverse(a); // 搜尋1與2的位置 int idx = Array.IndexOf(a, 1); Console.WriteLine("First index of 1 in a is {0}", idx); idx = Array.IndexOf(a, 2); Console.WriteLine("First index of 2 in a is {0}", idx); idx = Array.LastIndexOf(a, 1);
鍵(Key)與項(Item) • 鍵 • 排序所根據的一維陣列 • 項 • 跟著鍵同時變動,同樣多元素的一維陣列
SortingDataArray片段 (1/2) int N_STUDENTS = 3; string[] registerNumber = new string[N_STUDENTS]; registerNumber[0] = "B645330"; registerNumber[1] = "B645331"; registerNumber[2] = "B645332"; int[] score = new int[N_STUDENTS]; score[0] = 88; score[1] = 92; score[2] = 86;
SortingDataArray片段 (2/2) Array.Sort(score, registerNumber); Array.Reverse(registerNumber); Array.Reverse(score); Console.WriteLine("名次 \t 學號 \t 成績"); for (k = 0; k < N_STUDENTS; ++k) { Console.WriteLine( (k+1) + "\t" + registerNumber[k] + "\t" + score[k]); }
綱要 • 一維陣列 • 亂數產生器 • 猜數字遊戲 • 一維陣列的排序、倒排、搜尋 • 整個陣列的設值與複製 • 矩形二維陣列 • 井字遊戲Tic-tac-toe • *不規則二維陣列 • *高維陣列 • foreach 敘述
ArrayAssignmentAndCopy片段 int seed = 123; Random rand = new Random(seed); const int N = 10; int[] a = new int[N]; for (k = 0; k < N; ++k) { a[k] = rand.Next() % 10; } // 陣列直接設值的副作用:以偵錯器觀察b和a的變化 int[] b = a; Array.Sort(b); //a已隨b改變
ArrayAssignmentAndCopy片段 // 陣列複製的效果:以偵錯器觀察c和a的變化 int[] c = new int[N]; for (k = 0; k < N; ++k) { c[k] = a[k]; } Array.Reverse(c); //a不隨c倒轉 // 陣列複製的效果:以偵錯器觀察d和a的變化 int[] d = new int[N]; Array.Copy(a, d, N); Array.Reverse(d); //a不隨d倒轉
綱要 • 一維陣列 • 亂數產生器 • 猜數字遊戲 • 一維陣列的排序、倒排、搜尋 • 整個陣列的設值與複製 • 矩形二維陣列 • 井字遊戲Tic-tac-toe • *不規則二維陣列 • *高維陣列 • foreach 敘述
Array2D.Program片段 (1/3) const int N_STUDENTS = 3; const int N_SUBJECTS = 2; string[] registerNumber = new string[N_STUDENTS]; registerNumber[0] = "B645330"; registerNumber[1] = "B645331"; registerNumber[2] = "B645332"; string[] subject = new string[N_SUBJECTS]; subject[0] = "計算機概論"; subject[1] = "計算機程式設計"; int[,] score = new int[N_STUDENTS,N_SUBJECTS];
Array2D.Program片段 (2/3) score[0, 0] = 90; score[0, 1] = 84; score[1, 0] = 88; score[1, 1] = 86; score[2, 0] = 86; score[2, 1] = 92; double[] individualAverage = new double[N_STUDENTS]; double[] subjectAverage = new double[N_SUBJECTS];
Array2D.Program片段 (3/3) for (int i = 0; i < N_STUDENTS; i++){ int sum = 0; for (int j = 0; j < N_SUBJECTS; j++){ sum += score[i,j]; } individualAverage[i] = (double)sum / N_SUBJECTS; }
score[0,0] score[0,0] score[0,1] score[0,1] score[1,0] score[1,1] score[1,1] score[1,0] score[2,0] score[2,0] score[2,1] score[2,1] 矩形陣列 int[ , ] score = new int [3, 2];
score[0,0] 處理列 i = 0 score[0,1] i = 1 score[1,1] score[1,0] i = 2 score[2,0] score[2,1] j = 0 j = 1 for(i=0; i<N_STUDENTS; ++i) { for(j=0; j<N_SUBJECTS; ++j) { . . . } }
score[0,0] 處理行 i = 0 score[0,1] i = 1 score[1,1] score[1,0] i = 2 score[2,0] score[2,1] j = 0 j = 1 for(j=0; j<N_SUBJECTS; ++j) { for(i=0; i<N_STUDENTS; ++i) { . . . } }
處理列 j=0 j i=0 i data[i,j] for(i=0; i<data.GetUpperBound(0); ++i) { for(j=0; j<data.GetUpperBound(1); ++j) { . . . } }
處理行 j j=0 i=0 i data[i,j] for(j=0; j<data.GetUpperBound(1); ++j) { for(i=0; i<data.GetUpperBound(0); ++i) { . . . } }
Array2D2.Program片段 (1/2) string[] registerNumber = { "B645330", "B645331", "B645332" }; int[,] score = { {90, 84}, {88, 86}, {86, 92} }; int nStudents = score.GetUpperBound(0)+1; int nSubjects = score.GetUpperBound(1)+1; double[] individualAverage = new double[nStudents]; double[] subjectAverage = new double[nSubjects];
Array2D2.Program片段 (2/2) Console.WriteLine( "學號\\科目\t計算機概論\t計算機程式設計\t兩科平均成績"); for (int i = 0; i < nStudents; ++i){ Console.Write(registerNumber[i]+" \t"); for(int j=0; j<nSubjects; ++j) { Console.Write(score[i,j]+" \t\t"); } Console.WriteLine("{0:F2}", individualAverage[i]); }