Hướng dẫn sử dụng Macromedia Flash mx


Bài 44: Trình bày các số trong dãy



tải về 0.86 Mb.
trang27/27
Chuyển đổi dữ liệu02.09.2017
Kích0.86 Mb.
#32845
1   ...   19   20   21   22   23   24   25   26   27

Bài 44: Trình bày các số trong dãy



Để tạo trò chơi tìm số nhỏ nhất, bạn đã thực hiện việc đưa các số từ một dãy vào các ô trên sân khấu một cách ngẫu nhiên. Việc ấy được thực hiện ngay khi sắp xếp các ô trên sân khấu. Tuy nhiên, thao tác lấy số ngẫu nhiên đưa vào các ô sẽ được thực hiện lặp đi, lặp lại mỗi khi có một ô biến mất (trường hợp người chơi bấm trúng ô có số nhỏ nhất). Vì vậy, ta nên tách thao tác ấy thành một hàm riêng biệt để dùng lại khi cần thiết. Bạn sửa chương trình như sau:

nums = [ 2.2, 1.2, 3.65, 0.71, 0.31, 0.01, 3.25, 0.45, 2.25, 5.2, 2.5, 0.09, 0.65, 4.6, 0.37, 0.25, 3.75, 1.7, 0.48, 5.5 ];

shuffleNumbers();

tiles = new Array();

n = 0;

for(i = 0; i < 4; i++) {



  tiles[i] = new Array();

  for(j = 0; j < 4; j++) {

    attachMovie("Tile", "tile" + i + j, n++);

    tiles[i][j] = this["tile" + i + j];

    tiles[i][j]._x = 100 * j;

    tiles[i][j]._y = 100 * i;

  }

}

 



displayNumbers();

 

function displayNumbers() {



  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(!tiles[i][j]._visible)

        continue;

      if(getRandom(0, 1))

        tiles[i][j].label.text = tray.shift();

      else

        tiles[i][j].label.text = tray.pop();

    }

  }


}

 

function shuffleNumbers() {



...

}

...



Như bạn thấy, ta có hàm mới mang tên displayNumbers chứa đoạn mã thực hiện thao tác lấy số ngẫu nhiên đưa vào các ô. Hàm displayNumbers được gọi sau khi các ô được sắp xếp hoàn chỉnh trên sân khấu. Vì vậy, ta không thực hiện thao tác lấy số ngẫu nhiên đưa vào ô khi đang sắp xếp ô trên sân khấu như trước nữa.

Trong hàm displayNumbers, để dự trù trường hợp có các ô nào đó đã biến mất, ta phải xét thuộc tính _visible của từng ô. Nếu ô nào có thuộc tính _visible là false thì bỏ qua, không xét đến nữa (diễn đạt bởi câu lệnh continue;). Các ô còn hiện diện được nhận trị số từ "cài khay" (dãy tray) một cách bình thường.

Hiện tại, các trị số lấy từ dãy nums được hiển thị trong các ô. Tuy nhiên, trò chơi sẽ bổ ích hơn (và khó hơn) nếu một số trị số được hiển thị dưới dạng biểu thức (dạng phân số hoặc biểu thức có phép tính gì đó chẳng hạn). Muốn đạt được điều đó, ta cần lưu trị số trong một thuộc tính của ô, còn nhãn label của ô được dùng để hiển thị biểu thức tương ứng. Trước hết, bạn hãy viết thêm dãy exps (tức "expression") song song với dãy nums như sau:

nums = [ 2.2, 1.2, 3.65, 0.71, 0.31, 0.01, 3.25, 0.45, 2.25, 5.2, 2.5, 0.09, 0.65, 4.6, 0.37, 0.25, 3.75, 1.7, 0.48, 5.5 ];

exps = [ "2 1/5", "1 1/5", "3,65", "0,71", "0,31", "1/100", "3,25", "45/100", "2 1/4", "5 1/5", "2 1/2", "0,09", "0,65", "4,6", "0,37", "1/4", "3 3/4", "1,7", "0,48", "5 1/2" ];

shuffleNumbers();

...

Dãy exps gọi là "song song" với dãy nums theo nghĩa: hai phần tử của hai dãy ở cùng vị trí thì tương ứng với nhau. Ví dụ, chuỗi "2 1/5" (phần tử thứ nhất của dãy exps) ứng với trị số 2.2 (phần tử thứ nhất của dãy nums). Tương tự, chuỗi "1/100" (phần tử của dãy exps có chỉ số là 5) ứng với trị số 0.01 (phần tử của dãy nums có cùng chỉ số là 5).



Khác với trước, ta sẽ đưa chuỗi "2 1/5" vào nhãn của ô, còn trị số tương ứng được lưu trong một thuộc tính mới của ô, có thể đặt tên là num. Bạn sửa lại nội dung hàm displayNumbers() như sau:

...


function displayNumbers() {

  var num, str;

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(!tiles[i][j]._visible)

        continue;

      if(getRandom(0, 1))

        num = tray.shift();

      else

        num = tray.pop();

     

      str = getString(num);



      tiles[i][j].num = num;

      tiles[i][j].label.text = str;

    }

  }


}

 

function getString(num) {



  for(var t = 0; t < nums.length; t++) {

    if(nums[t] == num)

      return exps[t];

  }


}

...


Trong hàm displayNumbers, trị số được lấy ngẫu nhiên từ "cái khay" (dãy tray) và được lưu tạm vào biến num. Để biết một trị số đã cho được biểu diễn bởi chuỗi như thế nào, ta viết thêm hàm mới mang tên getString. Hàm getString thực hiện nhiệm vụ đơn giản: dò tìm xem trị số đã cho là trị số nào trong dãy nums, khi tìm ra trị số ấy thì trả về kết quả là chuỗi tương ứng trong dãy exps. Bạn chú ý, ta viết var trước biến t nhằm tạo ra biến t tạm thời, chỉ được dùng trong hàm getString mà thôi.

Trong hàm displayNumbers, ta trao trị số trong biến num cho hàm getString để có được chuỗi biểu diễn tương ứng, lưu chuỗi ấy trong biến tạm thời str. Điều này thể hiện bởi câu lệnh str = getString(num);. Sau đó, ta lưu trị số của biến num vào thuộc tính mới của ô gọi là num: tiles[i][j].num = num; còn chuỗi biểu diễn tương ứng được dùng làm nội dung của nhãn label: tiles[i][j].label.text = str;.

Chạy thử chương trình, bạn có kết quả đại khái như hình 1. Bạn thấy rõ nhãn label của mỗi ô là chuỗi lấy từ dãy exps. Mỗi ô có thuộc tính num để lưu trị số tương ứng với nhãn label (trị số đó không được hiển thị).



Bài 45: Giải thuật tìm số nhỏ nhất



Để tạo ra trò chơi tìm số nhỏ nhất, bạn đã thực hiện xong việc hiển thị ngẫu nhiên các trị số trong các ô. Ta hãy thực hiện bước tiếp theo: diễn đạt những việc cần làm khi người chơi bấm vào một ô nào đó, nghĩa là định nghĩa hàm xử lý tình huống onPress của từng ô. Khi đó, rõ ràng ta cần đọc các trị số ở các ô đang được hiển thị, tìm trị số nhỏ nhất trong các trị số đó và so sánh trị số trong ô được bấm với trị số nhỏ nhất để biết người chơi đã chọn đúng hay không. Nếu đúng, ta cho ô được chọn biến mất.

Bạn viết thêm vào chương trình như sau:

...

n = 0;


for(i = 0; i < 4; i++) {

  tiles[i] = new Array();

  for(j = 0; j < 4; j++) {

    attachMovie("Tile", "tile" + i + j, n++);

    tiles[i][j] = this["tile" + i + j];

    tiles[i][j]._x = 100 * j;

    tiles[i][j]._y = 100 * i;

    tiles[i][j].onPress = doPress;

  }

}

 



displayNumbers();

 

function doPress() {



  tray = new Array();

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(!tiles[i][j]._visible)

        continue;

      tray.push(tiles[i][j].num);

    }

  }


 

  var min = tray[0];

  for(i = 1; i < tray.length; i++) {

    min = Math.min(min, tray[i]);

  }

 

  if(this.num == min)



    this._visible = false;

}

...



Nhân khi đang sắp xếp các ô trên sân khấu, ta quy định hàm xử lý tình huống onPress là hàm doPress: tiles[i][j].onPress = doPress;. Thay cho tên hàm doPress, bạn có thể đặt tên khác tùy ý. Trong định nghĩa hàm doPress, để thuận tiện cho việc tìm trị số nhỏ nhất, ta đặt trị số của các ô đang được hiển thị vào "cái khay" tray trống rỗng. Với câu lệnh var min = tray[0]; ta giả sử trị số nhỏ nhất min là trị số đầu tiên của dãy tray. Sau đó, ta lần lượt so sánh min với các trị số còn lại của dãy. Mỗi khi phát hiện trị số nhỏ hơn min, ta gán trị số đó cho min. Điều này được thực hiện thuận lợi nhờ hàm Math.min (hàm min của lớp Math). Khi được trao hai trị số, hàm Math.min trả về cho ta kết quả là số nhỏ hơn trong hai số đã cho. Nhờ câu lệnh min = Math.min(min, tray[i]); sau khi "duyệt" qua dãy tray, ta tìm được số nhỏ nhất trong dãy tray. Câu lệnh if(this.num == min) nhằm so sánh trị số num của ô được chọn với trị số nhỏ nhất min. Nếu trị số num của ô được chọn chính là trị số nhỏ nhất, ta gán trị false cho thuộc tính _visible của ô, làm cho ô được chọn biến mất. Bạn chú ý, trong hàm xử lý tình huống, biến this là biến trỏ đến thể hiện mà ở đó tình huống xảy ra. Trong trường hợp đang xét, biến this trong hàm doPress trỏ đến thể hiện mà tại đó xảy ra tình huống bấm chuột. Bạn hãy chạy thử chương trình để kiểm tra hiệu quả của hàm doPress mỗi khi bấm vào ô có trị số nhỏ nhất (hình 1). Việc tiếp theo cần làm là cộng điểm cho mỗi lần người chơi chọn đúng trị số nhỏ nhất. Ngoài ra, để thêm phần... căng thẳng, người chơi chọn sai sẽ bị trừ điểm và khi người chơi chọn sai quá ba lần, trò chơi trở lại từ đầu (mọi ô tái hiện và điểm số trở về 0). Bạn thấy ngay: ta cần có thêm biến score để ghi nhớ điểm và một biến để đếm số lần chọn sai, gọi là wrong chẳng hạn. Ý định vừa nêu được diễn đạt trong chương trình như sau:

...


tiles = new Array();

n = 0;


for(i = 0; i < 4; i++) {

  tiles[i] = new Array();

  for(j = 0; j < 4; j++) {

    attachMovie("Tile", "tile" + i + j, n++);

    tiles[i][j] = this["tile" + i + j];

    tiles[i][j]._x = 100 * j;

    tiles[i][j]._y = 100 * i;

    tiles[i][j].onPress = doPress;

  }

}

 



init();

 

function init() {



  score = 0;

  wrong = 0;

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      tiles[i][j]._visible = true;

    }


  }

 

  shuffleNumbers();



  displayNumbers();

}

 



function doPress() {

  tray = new Array();

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(!tiles[i][j]._visible)

        continue;

      tray.push(tiles[i][j].num);

    }


  }

 

  var min = tray[0];



  for(i = 1; i < tray.length; i++) {

    min = Math.min(min, tray[i]);

  }

 

  if(this.num == min) {



    score += 5;

    this._visible = false;

  }

  else {


    score -= 5;

    wrong++;

  }

 

  if(wrong > 3)



    init();

 

}



 

function displayNumbers() {

...

Để thuận tiện cho việc khởi động lại trò chơi (trở về tình trạng như khi trò chơi mới bắt đầu), ta viết thêm hàm init. Hàm init gán trị ban đầu 0 cho hai biến score và wrong, gán trị true cho thuộc tính _visible của mọi ô (làm cho mọi ô tái hiện) và đưa trị số ngẫu nhiên vào các ô bằng cách gọi hàm shuffleNumbers và displayNumbers. Vì hàm init làm mọi việc cần thiết để khởi động trò chơi, ta viết câu lệnh gọi hàm init thay cho hai câu lệnh gọi hàm shuffleNumbers và displayNumbers khi bắt đầu trò chơi. Trong hàm doPress, khi người chơi chọn đúng trị số nhỏ nhất, ta cộng thêm 5 điểm vào biến score: score += 5;. Nếu chọn sai, người chơi bị trừ 5 điểm: score -= 5;. Khi đó, trị số biến đếm wrong tăng thêm một: wrong++;. Ở cuối hàm doPress, ta kiểm tra biến wrong. Nếu biến wrong có trị số lớn hơn 3 (người chơi đã chọn sai quá 3 lần), hàm init được gọi, khiến trò chơi trở lại từ đầu. Để hiển thị điểm của người chơi, bạn cần tạo thêm dòng chữ tĩnh "score:" ở gần cạnh dưới sân khấu và dòng chữ động kề bên (hình 2) theo cách tương tự như trong trò chơi lật hình và ráp hình. Bạn có thể đặt tên dòng chữ động là result (bạn đừng dùng tên score vì ta đã có biến score trong chương trình). Ở cuối hàm doPress, bạn cần viết thêm câu lệnh result.text = score; để điểm số hiển thị lập tức mỗi khi người chơi bấm vào một ô.



Bài 46: Những cải tiến trước mắt



Trò chơi tìm số nhỏ nhất của ta đã "nên vóc nên hình". Cũng như trò chơi ráp hình đã thực hiện, bạn cần làm vài việc nữa để hoàn chỉnh trò chơi. Trước hết, sau khi người chơi bấm vào một ô, ta cần kiểm tra xem người chơi đã thắng hay chưa. Nếu người chơi đã làm cho mọi ô biến mất, chương trình cần hiển thị câu chào mừng. Ngược lại, ta chỉ cần hiển thị điểm số. Bạn viết thêm ở cuối hàm xử lý tình huống bấm chuột doPress như sau:

...


function doPress() {

...


 

  if(wrong > 3)

    init();

 

  if(testForWin())



    result.text = score + "  You've won!"

  else


    result.text = score;

}

 



function testForWin() {

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(tiles[i][j]._visible)

        return false;

    }


  }

  return true;

}

 

function displayNumbers() {



...

Ở cuối hàm doPress, ta kiểm tra xem người chơi đã thắng hay chưa bằng cách gọi hàm testForWin. Tùy theo hàm testForWin trả về trị true hoặc false, nội dung dòng chữ động result.text được gán chuỗi thích hợp. Nếu hàm testForWin trả về trị true, dòng chữ động sẽ hiển thị điểm số kèm theo câu chào mừng "You've won!" (Bạn đã thắng). Trong hàm testForWin vừa viết thêm, ta dùng hai vòng lặp for để lần lượt xem xét từng ô. Chỉ cần có một ô chưa biến đi (thuộc tính _visible của nó là true), ta lập tức trả về trị false. Đó là trường hợp trò chơi vẫn còn dở dang. Nếu không có ô nào còn hiển thị, câu lệnh return true; ở cuối hàm testForWin sẽ được thi hành, nghĩa là khi đó hàm testForWin trả về trị true, xác nhận rằng người chơi đã "hoàn thành nhiệm vụ". Tiếp theo, như đã làm trong trò chơi ráp hình, ta tạo thêm nút bấm Reset để người chơi có thể chủ động bắt đầu lại trò chơi bất cứ lúc nào. Cụ thể, bạn ấn Ctrl+Shift+O (hoặc chọn File > Import > Open External Library). Trong hộp thoại Open as Library vừa hiện ra, bạn tìm tập tin FLA chứa nút bấm Start (bài 24) và bấm kép vào nó. Thao tác như vậy mở ra cửa sổ Library của tập tin đã chọn, trong đó có nút bấm Start cần dùng. Bạn kéo nút bấm Start vào sân khấu, đặt ở góc dưới, bên phải, dùng công cụ Free Transform Tool  để điều chỉnh kích thước nút bấm cho phù hợp. Bạn gõ phím V để chuyển qua công cụ chọn , bấm kép vào nút bấm để chuyển qua chế độ chỉnh sửa, chọn công cụ Text Tool  (hoặc gõ phím T), bấm vào nhãn nút bấm, sửa nhãn nút bấm thành Reset. Bạn cũng sửa nhãn nút bấm thành Reset ở khung 2 và khung 3 của nút bấm. Bạn bấm vào Scene1  để thoát khỏi chế độ chỉnh sửa, ấn Ctrl + F3 để mở bảng Properties (trình bày các thuộc tính của nút bấm). Trong ô Instance Name, bạn gõ reset để đặt tên cho nút bấm (hình 1).



Bạn ấn Ctrl +F3 để dẹp cửa sổ Properties, chuyển qua công cụ chọn , bấm vào nền sân khấu để thôi chọn nút bấm Reset, mở lại bảng Actions - Frame và viết thêm vào chương trình như sau:

...

 

init();



reset.onPress = init;

 

function init() {



  score = 0;

  wrong = 0;

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      tiles[i][j]._visible = true;

    }


  }

  result.text = score;

  shuffleNumbers();

  displayNumbers();

}

 

function doPress() {



...

Ta viết thêm câu lệnh reset.onPress = init; để quy định rằng khi người chơi bấm nút Reset, hàm init sẽ được gọi. Trong hàm init, bạn cần thêm câu lệnh result.text = score; để câu chào mừng (nếu có) biến đi. Nhờ vậy, trò chơi thực sự trở về tình trạng như lúc đầu. Chạy thử chương trình và bấm nút Reset nhiều lần, chắc bạn sẽ thấy các trị số xuất hiện trong các ô chưa thực sự hỗn loạn. Nguyên nhân thuộc về cách chọn trị ngẫu nhiên. Bạn hãy xem lại hàm displayNumbers:

...

function displayNumbers() {



...

      if(getRandom(0, 1))

        num = tray.shift();

      else

        num = tray.pop();

...


Trong hàm displayNumbers, ta dùng hàm getRandom(0, 1) để chọn ngẫu nhiên một trong hai trường hợp. Tuy nhiên xác suất để có trị 0 và xác suất để có trị khác 0 trả về bởi hàm getRandom không ngang nhau. Trong đoạn mã nêu trên, hàm getRandom(0, 1) cho trị ngẫu nhiên từ 0 đến 1, nghĩa là gồm có trị 0, trị 1 và các trị trung gian. Do vậy, xác suất để có trị khác 0 lớn hơn xác suất để có trị 0.

Bạn hãy sửa lại, chọn ngẫu nhiên trị số từ dãy tray theo cách khác như sau:

...

function displayNumbers() {



  var num, str;

  var k;

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(!tiles[i][j]._visible)

        continue;

/*

      if(getRandom(0, 1))



        num = tray.shift();

      else

        num = tray.pop();

*/

      k = getRandom(0, tray.length-1);



      num = tray[k];

      tray.splice(k, 1);

 

      str = getString(num);



      tiles[i][j].num = num;

      tiles[i][j].label.text = str;

    }

  }


}

...


 

Đoạn mã thay thế nhằm chọn một chỉ số k ngẫu nhiên trong dãy tray. Bạn chú ý, chỉ số của phần tử trong dãy tray chạy từ 0 đến tray.length-1 (chiều dài của dãy trừ đi 1). Cụ thể, dãy tray có chiều dài là 20 (có 20 phần tử), chỉ số của phần tử trong dãy tray chạy từ 0 đến 19. Sau khi chọn ngẫu nhiên chỉ số k trong dãy tray, ta gán phần tử ở vị trí k cho biến num: num = tray[k]; rồi loại bỏ phần tử đó ra khỏi dãy tray: tray.splice(k, 1);. Đối mục đầu tiên của hàm splice là chỉ số của phần tử đầu tiên cần lấy ra khỏi dãy. Đối mục thứ hai của hàm splice là số lượng phần tử kể từ phần tử đầu tiên cần lấy ra khỏi dãy. Trong trường hợp đang xét, đối mục thứ hai là 1 vì ta chỉ cần lấy một phần tử ra khỏi dãy tray trong một lần lặp. Nói cho gọn, đoạn mã thay thế giúp bạn lấy ngẫu nhiên từng phần tử ở vị trí bất kỳ trong dãy tray ra khỏi dãy tray. Điều này giúp cho các ô nhận trị ngẫu nhiên tốt hơn. Phần dưới đây trình bày toàn bộ chương trình để bạn tiện tham khảo:

nums = [ 2.2, 1.2, 3.65, 0.71, 0.31, 0.01, 3.25, 0.45, 2.25, 5.2, 2.5, 0.09, 0.65, 4.6, 0.37, 0.25, 3.75, 1.7, 0.48, 5.5 ];

exps = [ "2 1/5", "1 1/5", "3,65", "0,71", "0,31", "1/100", "3,25", "45/100", "2 1/4", "5 1/5", "2 1/2", "0,09", "0,65", "4,6", "0,37", "1/4", "3 3/4", "1,7", "0,48", "5 1/2" ];

tiles = new Array();

n = 0;


for(i = 0; i < 4; i++) {

  tiles[i] = new Array();

  for(j = 0; j < 4; j++) {

    attachMovie("Tile", "tile" + i + j, n++);

    tiles[i][j] = this["tile" + i + j];

    tiles[i][j]._x = 100 * j;

    tiles[i][j]._y = 100 * i;

    tiles[i][j].onPress = doPress;

  }

}

 



init();

reset.onPress = init;

 

function init() {



  score = 0;

  wrong = 0;

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      tiles[i][j]._visible = true;

    }


  }

  result.text = score;

  shuffleNumbers();

  displayNumbers();

}

 

function doPress() {



  tray = new Array();

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(!tiles[i][j]._visible)

        continue;

      tray.push(tiles[i][j].num);

    }

  }


 

  var min = tray[0];

  for(i = 1; i < tray.length; i++) {

    min = Math.min(min, tray[i]);

  }

 

  if(this.num == min) {



    score += 5;

    this._visible = false;

  }

  else {


    score -= 5;

    wrong++;

  }

 

  if(wrong > 3)



    init();

 

  if(testForWin())



    result.text = score + "  You've won!"

  else


    result.text = score;

}

 



function testForWin() {

  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(tiles[i][j]._visible)

        return false;

    }


  }

  return true;

}

 

function displayNumbers() {



  var num, str;

  var k;


  for(i = 0; i < 4; i++) {

    for(j = 0; j < 4; j++) {

      if(!tiles[i][j]._visible)

        continue;

 

      k = getRandom(0, tray.length-1);



      num = tray[k];

      tray.splice(k, 1);

 

      str = getString(num);



      tiles[i][j].num = num;

      tiles[i][j].label.text = str;

    }

  }


}

 

function getString(num) {



  for(var t = 0; t < nums.length; t++) {

    if(nums[t] == num)

      return exps[t];

  }


}

 

function shuffleNumbers() {



  tray = new Array();

  for(i = 0; i < nums.length; i++)

    if(getRandom(0, 1))

      tray.push(nums[i]);

    else

      tray.unshift(nums[i]);

}

 

function getRandom(min, max) {



  return Math.floor(Math.random()*(max - min + 1) + min);

}






Каталог: files -> 2012
files -> PHỤ LỤC 2 TỔng hợp danh mục tài liệu tham khảO
files -> BÁo cáo quy hoạch vùng sản xuất vải an toàn tỉnh bắc giang đẾn năM 2020 (Thuộc dự án nâng cao chất lượng, an toàn sản phẩm nông nghiệp và phát triển chương trình khí sinh học ) Cơ quan chủ trì
files -> BỘ TÀi nguyên và MÔi trưỜng
files -> 1. Mục tiêu đào tạo: Mục tiêu chung
2012 -> Số Hồ sơ: 50 / /cs-bhyt cộng hòa xã HỘi chủ nghĩa việt nam
2012 -> HÌnh ảnh thao tác dữ liệu máy toàN ĐẠc nts 310 CỦa hãng south
2012 -> Khóa học 2010 -2012 (TT10C/1) (Ban hành theo quyết định số /QĐ-bgh ngày …tháng…năm của Hiệu trưởng trường Đại học Hoa Sen)
2012 -> Thông báo về việc xét thông qua đề tài luận văn và người hướng dẫn cho hvch k56

tải về 0.86 Mb.

Chia sẻ với bạn bè của bạn:
1   ...   19   20   21   22   23   24   25   26   27




Cơ sở dữ liệu được bảo vệ bởi bản quyền ©hocday.com 2024
được sử dụng cho việc quản lý

    Quê hương