Saturday, May 31, 2014

Pawn Tutorial - Các Bài Tập Cơ Bản Với Pawn

Pawn Tutorial



Note: This guide is rather hardcoded to AMX Mod X. It needs to be mode generic.
This guide is designed to give you a more in-depth overview of the basics of programming in Pawn.
Bỏ mấy cái phần đầu đi. Xem phần chính là oke rồi :v

Contents

 [hide

Giới Thiệu

Pawn is an embeddable, (almost) typeless, easy to use scripting language that is compiled for a virtual machine. AMX Mod X uses Pawn to route scripting functions to the Half-Life engine, using the Pawn Virtual Machine and Metamod (Pawn is written in C, Metamod is written in C++). While you write Pawn scripts in a text editor, the scripts must be compiled with a "Compiler", which produces a binary for AMX Mod X. The AMX Mod X team distributes a specially modified Pawn compiler.
Programming scripts in Pawn is relatively easy, and does not have concepts in other languages that are unnecessary for general use, such as pointers, vectors, structs, classes, allocation, et cetera.

Language Paradigms

Pawn was originally named "Small" to emphasize the size of the language specification. The language sacrifices many features found in modern languages to achieve simplicity and speed, which are required for embedded uses.
  • No typing
    • Pawn only has one data type -- the "cell". It is the size of the processor's integral pointer (4 bytes for 32bit processor, 8 bytes for 64bit processors). This has two major implications - Pawn bytecode is processor specific, and pointers can fit inside a cell.
    • Tagging - Pawn lets you create weakly statically typed "tags", which can be associated with variables for primitive operator overloading. For example, Pawn has no concept of floating point numbers (only integers). Instead, operators are overloaded with the Float: tag to redirect computation to new functions. Tag-checking is only enforced as a warning. If you're using SourcePawn (for SourceMod), there is actually a second type: String. In a String, letters are stored as separate bytes... essentially having 4 characters stored in every cell.
    • Since Pawn only has one datatype, it does not support structs, records, objects, or anything else.
    • Pawn does support arrays of cells, which leads to C-style arrays for strings.
  • No garbage collection
    • Pawn has no "heap" allocation built-in. All variables are stored on the stack or in the data section. Therefore, no garbage collection is necessary and memory leaks are not possible from the language specification alone.
  • Procedural
    • Pawn is entirely comprised of single, non-nested subroutines. There are no lambda functions, member functions, constructors, et cetera. Functions can either be internal (within the script) or public (exposed to the VM by name, like C's "extern").
  • No thread-safety
    • Pawn is targetted toward single-thread instances.

Implementation Features

  • Cross-platform compatible compiler, which outputs bytecode and debug browsing information.
  • Cross-platform compatible Virtual Machine (VM), with support for debug browsing, halting/stopping execution, and interacting with scripts from C/C++ libraries.
  • IA32 JIT Compiler for vastly increasing script execution time.
Because the footprints of the VM and JIT are so small, Pawn is ideal inside games which need a simple and highly fast event system, embedded devices or applications, and realtime systems.

License

Pawn is licensed under the ZLib/libpng_License license.

Variables

Variables are simple structures for holding data throughout a period of time in your script.

Types

Small has just three data types for declaring variables. The default variable type is a regular whole number, or integer. A variable name, for backwards compatibility, should be 19 characters or less, and MUST start with a letter. It can contain the symbols A-Z, a-z, 0-9, and the underscore ("_"). It is important to note that variable names are case sensitive - "myvar", "MyVaR", and "MYVAR" are three separate symbols.

Integers - Số Nguyên

Các kiểu dữ liệu đơn giản nhất trong Pawn là một "số nguyên". Integers là số nguyên. Để khai báo một biến số nguyên mới, sử dụng toán tử "new" như vậy:
new a            //Khai báo biến rỗng "a"
new b=5          //Khai báo biến b và gán 5 cho nó
new c=5.0        //Cái này không hợp lệ, về mặt kỹ thuật thì không phải là số nguyên!
new d="hello"    //"hello" không phải một số nó là một chuỗi, Điều này là không hợp lệ với số nguyên.
 
//Bạn có thể khai báo nhiều biến trên một dòng
new e,f,g,h
new x=7, y=3
new z = 1_000_000 // Pawn hỗ trợ số như thế này, vì vậy giá trị lớn dễ dàng hơn để đọc.

Floats - Sô thực

Bạn cũng có thể khai báo một biến như là một "Float", có nghĩa là nó có thể lưu trữ các số với chữ số thập phân. Chúng được gọi là "số thực" :
new Float:a            //Khai báo một biến thực rỗng "a"
new Float:b=5.3        //Khai báo một biến thực "b" và gán "5.3" cho nó.
new Float:c=5          //Cái này là hợp lệ nhưng trình biên dịch sẽ đưa ra một cảnh báo.
new Float:d="hello"    //Cái này không hợp lệ. "hello" không phải số thập phân.
Bạn cũng có thể làm như sau:
//float(n) là một hàm chuyển số n thành số thực.
new Float:var = float(5)
new Float:var2 = 5.0     
new Float:var3 = 1.0*5
new var4 = floatround(5.0)     
//Note: floatround(n) là một hàm làm tròn số n thành số nguyên.
//  điều này gán cho một biến nguyên là hợp lệ.
Lưu ý - Khoảng cách không thường không quan trọng, miễn là trình biên dịch có thể nói với các ký hiệu xa nhau. Nếu khoảng cách của bạn là thực sự xấu, bạn sẽ nhận được lỗi hoặc thậm chí có cảnh báo. Ví dụ, "var new = 5" và "new var = 5" là như nhau, nhưng "newvar = 5" là hoàn toàn sai.

Booleans - True/False

Kiểu biến cuối cùng là "boolean". Nó rất đơn giản - đó là một trong hai "đúng" hoặc "sai". Cả hai "đúng" và "sai" là cấu trúc dữ liệu được xác định trước.
new bool:IsItOn        //Khai báo một biến mới "IsItOn", mặc định được gán bằng False
new bool:xyz=true      //Khai báo một biến mới "xyz" gán bằng True

Arrays - Mảng

Pawn tính năng cơ bản "mảng". Một mảng là một loại đơn giản của dữ liệu tổng hợp. Điều này có nghĩa bạn có thể lưu trữ nhiều giá trị trong một biến! Một mảng theo quy tắc tương tự như là một biến thông thường, và nó có cùng loại. Nó chỉ đơn giản có thể chứa nhiều giá trị. Bạn xác định một mảng với dấu ngoặc, và bao nhiêu giá trị nó có thể giữ. Ví dụ:
//Điều này sẽ khai báo một biến được gọi là "Player" nắm giữ 32 con số.
new Players[32]
 
// Bây giờ bạn có thể lưu trữ các giá trị trong bất kỳ của 32 "khe" mảng này có. 
// Các khe được đánh số từ 0 đến n-1, hoặc trong trường hợp này, 0-31. 
// Mỗi khe bắt đầu là 0.
 
//Gán khe 0 bằng 5
Players[0] = 5
 
//Gán khe 1 bằng khe 0, ở đây là 5
Players[1] = Players[0]
 
// Điều này là không hợp lệ! 
// Mặc dù có 32 khe, họ được đánh số 0-31. 
// Làm kết quả này trong AMX Native Error 4 - AMX_ERR_BOUNDS 
// Hoặc, nó chỉ đơn giản là sẽ không biên dịch!
Players[32] = 15
 
//Đây cũng là hoàn toàn không hợp lệ          
Players[-1] = 6
 
new a = 3
// Đây cũng là hoàn toàn hợp lệ. 
// a phải là một số không đổi.
new BadArray[a]
 
//Cái này là hợp lệ:
const b = 3
new GoodArray[b]
 
//Bạn cũng có thể sử dụng trình biên dịch chỉ thị (xem phần cuối)
 
#define ARRAY_SIZE 3
new Array[ARRAY_SIZE]
Mảng cũng có thể được khai báo với nhóm dữ liệu mặc định, chẳng hạn như:
new Numbers[4] = {0,1,2,3}
// Lưu ý: điều quan trọng là bạn chắc chắn rằng số lượng các con số 
// Bạn vượt qua và kích thước của mảng trận đấu

Bạn cũng có thể sử dụng bất kỳ loại dữ liệu với các mảng:
//Một mảng số thực:
new Float:Numbers[4] = {0.0, 1.2, 2.4, 3.8}
//Mảng boolean.  Lưu ý là các khe đều được gán bằng True
new bool:playerHasGun[33] = {true, ...}

Strings - Chuỗi

Bạn có thể thấy rằng một loại dữ liệu quan trọng là mất tích - ký tự (chữ và biểu tượng). Chúng được gọi là "chuỗi", và trong Pawn, họ có kỹ thuật số! Một chuỗi là một mảng các số mà dịch để ASCII (nhân vật) ký tự. Ví dụ:
//Điều này sẽ khai báo một mảng số "myString" có chứa dữ liệu "Hello".  
// Nó sẽ có 6 khe cắm, bởi vì có 5 ký tự. 
// Khe cắm cuối cùng được dành riêng cho các số 0, mà cho công cụ Pawn rằng đó là một chuỗi.
new myString[] = "Hello"
// Nếu bạn đang sử dụng SourcePawn, làm điều này thay vì:
new String:myString[] = "Hello"
Lưu ý: bất cứ điều gì ở giữa / * và * / cũng là một nhận xét. Bạn không thể sử dụng / ** / bên trong một / ** /. Các lệnh sau đạt được cùng một mục đích, tuy nhiên, nó dài hơn và không được khuyến khích. Các công trình này bởi vì mỗi ký tự của chuỗi "Hello" được lưu trữ trong một khe cắm trong mảng.
new myString[6]
myString[0] = 'H'
myString[1] = 'e'
myString[2] = 'l'
myString[3] = 'l'
myString[4] = 'o'
myString[5] = 0
Lưu ý: Mảng có nghĩa là để được chuỗi phải kết thúc bằng một 0, hoặc các ký tự null. Đây là để bạn biết nơi kết thúc chuỗi.
Bạn KHÔNG THỂ làm được điều này! Trong khi nó có thể biên dịch, nó rất nguy hiểm vì nó có thể gây ra lỗi tràn bộ nhớ:
new myString[6]
myString = "Hello"     //KHÔNG HỢP LỆ!
myString[0] = "Hello"  //KHÔNG HỢP LỆ!
//Thêm dữ liệu vào một chuỗi, bạn có thể làm điều này:
new goodString[7]
copy(goodString, 6, "Hello")
Lưu ý: Trong SourcePawn, copy được đổi tên thành strcopy và tránh vấn đề với bản sao lưu ý dưới đây.
Lưu ý rằng chúng tôi sao chép 6 cells của mảng vào một mảng có thể chứa 7. Nếu chúng ta sao chép 7 byte vào mảng này, copy () đều có thể sao chép một byte thêm cho nhân vật Null, tràn mảng. Này được gọi là một lỗi tràn bộ đệm và phải tránh cẩn thận.
Nhiều ví dụ:
//Copy là một hàm có 3 thông số:
copy(destination[], length, source[])
//Nó sao chép chuỗi trong mảng nguồn và những nơi 
// nó vào mảng đích, nhưng chỉ có bản sao lên đến chiều dài ký tự.
 
//Cuối cùng, để chứng minh rằng một chuỗi thực sự là một mảng các số, điều này là hoàn toàn hợp lệ:
new weird[6]
weird[0] = 68
weird[1] = 65
weird[2] = 73
weird[3] = 86
weird[4] = 68
weird[5] = 0
// Điều này sẽ thiết lập biến "weird" với chuỗi "DAVID". 
// Để xem cách các chữ cái và các ký hiệu chuyển thành số, hãy truy cập www.asctiitable.com

Functions - Hàm

Pawn cho phép bạn xác định chức năng của riêng bạn. Điều này có ích để loại bỏ mã được sử dụng ở nhiều nơi. Lưu ý rằng tất cả các chức năng phải trả lại một giá trị. Để làm điều này, bạn sử dụng "Return" lệnh, mà ngay lập tức tạm dừng hàm và trả về giá trị của biểu thức được truyền cho nó. Không có mã được thực hiện trong một hàm một lần trở lại được tìm thấy. Dưới đây là một số ví dụ:
//Đây là một hàm không có tham số và trả về 1.
//Khi được gọi, nó sử dụng (không tồn tại) hàm Print.
show()
{
   print("Hello!")
 
   return 1   //End, return 1
}
 
//Cách để gọi một hàm:
show()
Bạn cũng có thể khai báo các hàm với các thông số.
//Khai báo một hàm được gọi là "add_two_numbers", trong đó có tham số và trả về tổng của chúng.
add_two_numbers(first, second)
{
   new sum = first + second
 
   return sum  //trả về sum
}
//Sau đó, bạn có thể sử dụng hàm mới của bạn như thế này:
 
new a,b
a = 5
b = 12
new c = add_two_numbers(a,b)
//c bây giờ sẽ bằng 17.
Bạn không bị giới hạn bởi những loại thông số dữ liệu có thể chấp nhận. Khi bạn đưa ra các thông số cho một hàm, nó được gọi là "đi qua". Bạn có thể vượt qua hoặc dữ liệu hoặc một biến với một hàm.
//định nghĩa một hàm mới được gọi là "add_two_floats"
// trong đó có 2 số thực và trả về tổn của chúng
Float:add_two_floats(Float:first, Float:second)
{
   new Float:sum = first + second
 
   return sum
}
 
new Float:a
new Float:b
a = 5.0
b = 6.3
new Float:c
c = add_two_floats( a+b )
//c bây giờ sẽ bằng 11.3
Bạn thậm chí có thể thêm mảng vào tham số của hàm ! Bạn không cần phải xác định kích thước của mảng. Nếu bạn làm thế, bạn phải chắc chắn rằng bạn đang kêu gọi các hàm với một loạt các kích thước bằng nhau và loại.
add_two_from_array(array[], a, b)
{
   new first = array[a]
   new second = array[b]
   new sum = add_two_numbers(first, second)   //sử dụng chức năng của chúng tôi từ trước đó
 
   return sum
}
Lưu ý rằng, khi bạn vượt qua các mảng thông qua một hàm chúng được truyền thông qua những gì được gọi là "tham chiếu". Khi một biến bình thường được thông qua với một hàm, nó được sao chép trong bộ nhớ, và các bản sao được gửi và sau đó xóa ngay sau đó. Đây không phải là trường hợp với một mảng. Bởi vì các mảng có thể rất lớn, mảng là "tham chiếu" thay vì sao chép. Điều này có nghĩa nếu bạn thay đổi các mảng, sau đó nó sẽ ở lại thay đổi. Ví dụ:
// Hàm này sẽ đổi vị trí a và b trong bất kỳ mảng thông qua chức năng này.
swap_slots(array[], a, b)
{
// Lưu ý, bạn cần phải tạm giữ một trong các khe trước khi trao đổi chúng 
// Nếu không, bạn có thể không trao đổi cả hai giá trị! Đây là một vấn đề kinh điển. 
// Nếu bạn có a, b​​, thiết b bằng một loại bỏ các giá trị ban đầu trong b.
   new temp
 
   temp = array[b]
   array[b] = array[a]
   array[a] = temp
}
 
new myArray[2]
myArray[0] = 5
myArray[1] = 6
swap_slots(myArray, 0, 1)
//myArray[0] bằng 6, myArray[1] bằng 5
Bạn có thể ngăn chặn các mảng đã được thay đổi bằng cách khai báo mảng "constant", như vậy:
add_two_from_array(const array[], a, b)
{
   new first = array[a]
   new second = array[b]
   new sum = add_two_from_array(first, second)
   return sum
}
//Lưu ý, bây giờ khi bạn sử dụng hàm, bạn được đảm bảo rằng các mảng sẽ không được sửa đổi.
hàm này sửa đổi một mảng thông qua như là một hằng số. Nó sẽ không làm việc.
bad_function(const array[])
{
   array[0] = 0
}

Expressions - Biểu Thức

Biểu thức chỉ là những gì chúng kêu nghe như từ toán học. Họ là nhóm các biểu tượng mà trả lại một phần dữ liệu. Biểu thức thường bao gồm các biểu thức trong dấu ngoặc đơn, và được đánh giá theo một thứ tự nhất định (từ bên trong nhất để ngoài cùng, parenthesis đầu tiên, sau đó nhân, chia, cộng, trừ, vân vân). Bạn có thể đặt bất cứ nơi nào biểu thức. Bạn có thể thiết lập các biến bằng họ hoặc vượt qua họ để các hàm.
//Đây là biểu hiện đơn giản nhất. Nó trả về số không.
0
//Tuy nhiên, để làm cho nó dễ dàng hơn để đọc, điều này cũng là hợp lệ:
(0)
Nếu một biểu thức không phải là không hay nó không phải là sai, nó không chỉ trả về một giá trị, nó cũng trả về "true". Nếu không, nó sẽ trở về 0, đó cũng là "false".
// Dưới đây là biểu thức toán học. Các toán tử toán học:
// + Bổ sung
// - Cho phép trừ
// * Cho phép nhân
// / Phân chia
// % Chia lấy dư
(5+6)                       //Kết quả 11
((5*6)+3)                   //Kết quả 33
((((5+3)/2)*4)-9)           //Kết quả 7
((5*6) % 7)                 //Kết quả 2
//Dưới đây là một số biểu thức khác:
(true)                      //Kết quả true
(5.0 + 2.3)                 //Kết quả 7.3 là một số thực
Ngoài ra còn có phần mở rộng của các toán tử này sử dụng trực tiếp trên các biến.
new a = 5
new b = 6
//Đầu tiên là những bài post/pre và giảm bớt toán tử.
a++          //trả về a+1, hoặc 6.  Đây là tăng kiểu post.
++a          //cũng trả về a+1, or 6.  Đây là tăng kiểu pre.
Sự khác biệt giữa hai là tinh vi nhưng quan trọng. a + + được đánh giá CUỐI trong một biểu thức, trong khi + + a được đánh giá đầu tiên. Sự khác biệt này có ích với mã có sử dụng vòng trong những cách nhất định. Nó cũng quan trọng để biết rằng các toán tử tăng / giảm sẽ không chỉ trả lại a+ 1, nhưng đặt biến a đến a+ 1.
a--          //trả về 4, giảm kiểu post 
--a          //trả về 4, giảm kiểu pre
Lưu ý rằng a + + cơ bản rút gọn xuống mã này:
a = a + 1
Tuy nhiên, có một cách khác để viết dòng mã của mẫu này:
a = a OP y
Nơi OP là một toán tử toán. Nó có thể được rút ngắn:
a OP= x
Ví dụ:
a += 1       //tương đương với a = a + 1
a -= b       //tương đương với a = a - b
a *= 0       //nhân a bằng 0
a /= 2       //Chia a cho 2.
Tuy nhiên, các nhà khai thác toán học không phải là nhà khai thác duy nhất mà bạn nhận được. Có các toán tử logic để giúp bạn với các mạch logic hoặc quyết định hợp lý. 

Và toán tử có trong biểu thức bên trái và bên phải biểu hiện. Nếu cả hai đều là "true", sau đó nó trả về true.
//Điều này là sai, bởi vì 1 trả về true và 0 trả về false.  
//Vì cả hai đều không đúng, && trả về false.
(1 && 0)
(1 && 2)                    //Cả hai con số này là "true", do đó biểu thức là đúng.
(true && false)             //false
(false && false)            //false
(true && true)              //true
Toán tử quan trọng khác là "Or". Nó trả về đúng nếu một trong hai biểu thức là đúng.
(1 || 0)                    //true, vì một trong những giá trị đúng.
(1 || 2)                    //true
(true || false)             //true
(false || false)            //false
(true || true)              //true
Có toán tử khác là tốt, mà bạn có thể không sử dụng thường xuyên. Các "toán trên bit và" nhà điều hành trả về cho dù a chuỗi bit nhị phân được chứa trong chuỗi khác. Trong thuật ngữ kỹ thuật, nó là một "và (&&)" hoạt động trên mỗi bit trong cả hai con số. Ví dụ, bạn có số "9", mà là "1001" trong hệ nhị phân. Nếu bạn muốn biết nếu chuỗi có chứa các số "8" (1000), bạn có thể làm:
//Điều này sẽ trả 8, có nghĩa là 8 thực sự là một chút trong 9.
(9 & 8)
//4 (00100) không một chút trong 16 (10000) và điều này sẽ trở về 0.
(16 & 4)
// Toán tử tiếp theo là "toán trên bit hay" 
// mà không một "hoặc | hoạt động của 'trên mỗi bit trong cả hai con số (|). 
// Điều này sẽ mất 9 (1001) và kết hợp nó với 3 (0011), kết quả là 1011, hoặc 11.
(9 | 3)
Hai toán tử cũng rất quan trọng, nhưng không được sử dụng thường xuyên. Họ là những nhà khai thác dịch chuyển toán trên bit, << là một sự thay đổi trái và >> là một sự thay đổi ngay. Họ chuyển các bit trong một số để một hướng.
//Này có số lượng 3 (00011) và thay đổi nó ba nơi để nhị phân (11000), hoặc 24.
(3 << 3)
//Này có số 24 (11000) và thay đổi nó ba nơi để nhị phân (00.011), hoặc 3.
(24 >> 3)
Toán tử cuối cùng là "phép toán không". Nó trả ngược lại của bất cứ điều gì cho nó. Khi được sử dụng trên một số, nó sẽ trở lại mỗi bit lộn (1-0, 0-1).
//Trả về false
(!true)
//Trả về true
(!false)
// Này có 9 (nhị phân 1001) và làm cho nó 6 (nhị phân 0110). 
// Đây là "phép toán bổ sung" nhà điều hành, thực hiện một (không) trên mỗi bit.
(~(9))

Conditionals - Điều Kiện

Điều kiện cho phép bạn kiểm tra một biểu thức đáp ứng một tiêu chuẩn, và để thực thi mã dựa trên quyết định đó.
If Statements
Câu lệnh If đơn giản nhất là "If...then". Kiểm tra biểu thức đã cho là đúng hay sai. Nếu đúng thì thực hiện khối mã còn nếu không đúng thì không làm gì cả.
Ví dụ bên dưới kiểm tra xem một biến có bằng 5 hay không. Nếu biến bằng 5 thì biến đó sẽ được gán bằng 6
if (a == 5)
{
   a = 6
}
Tuy nhiên, những gì sẽ xảy ra nếu a không bằng 5? Sau đó mã sẽ không được thực thi. Tuy nhiên, bạn có thể nói cho nó để thực thi mã nếu các điều kiện không được đáp ứng. Bây giờ, nếu a bằng 5, a sẽ được gán bằng 6. Nếu không, nó sẽ được gán bằng 7.
if (a == 5)
{
   a = 6
} else {
   a = 7
}
Có rất nhiều toán tử khác nhau mà bạn có thể sử dụng bên trong if () tuyên bố. Trong thực tế, bạn có thể sử dụng bất kỳ biểu hiện mà đánh giá True (Khác 0 ) hoặc sai (bằng 0).
//Điều này sẽ trở về đúng nếu a không bằng 5
if (a != 5) {}
//Trả về true nếu a lớn hơn 5
if (a > 5) {}
//Trả về true nếu a nhỏ hơn 5
if (a < 5) {}
//Trả về true nếu a lớn hơn hoặc bằng 5
if (a >= 5) {}
//Trả về true nếu a nhỏ hơn hoặc bằng 5
if (a <= 5) {}
//Trả về True vì 11 là đúng
if (5+6) {}
//Trả về True nếu cả a và b điều đúng
if (a && b) {}
//Trả về true nếu 7.5 lớn hơn c
if ( ((5*3)/2) > c) {}
//Luôn luôn trả về đúng không có vấn đề gì
if (true) {}
//không bao giờ trả về true
if (false) {}
Lưu ý rằng so sánh mảng có những hạn chế. Điều này là không hợp lệ:
my arrayOne[3]
my arrayTwo[3]
if (arrayOne == arrayTwo) {
Bạn phải làm:
if ((arrayOne[0] == arrayTwo[0]) && 
    (arrayOne[1] == arrayTwo[1]) && 
    (arrayOne[2] == arrayTwo[2])) {
Rõ ràng, điều này sẽ trở nên rất mệt mỏi với các mảng lớn. Bạn sẽ thấy sau này làm thế nào để dễ dàng so sánh chuỗi và mảng.
 if...then mô hình chuyển đổi có điều kiện có thể được đưa đến một cấp độ khác. Pawn cung cấp một cách để bạn có thể cung cấp nhiều cấp độ của các biểu thức đúng và sai.
//Ví dụ cho "if...else if"
if (a == 5) {
   //Mã này sẽ chạy nếu a là 5.
} else if (a < 6) {
   //Mã này sẽ chạy nếu a nhỏ hơn 6
} else if (a == 7) {
   //Mã này sẽ chạy nếu a bằng 7.
} else {
   //Nếu không có các điều kiện trên được đáp ứng, mã này sẽ được chạy.
}

Điều quan trọng cần lưu ý là trong ví dụ trên, mỗi khối mã không phải là "mùa thu thông qua". Điều đó có nghĩa mỗi điều kiện sẽ được kiểm tra theo thứ tự, và nếu một là đúng, mã sẽ được thực hiện và câu lệnh if được thực hiện. Nó sẽ không thực hiện nhiều điều kiện đúng.

Switch Statements - Câu lệnh Switch

Cuối cùng, có một loại cuối cùng của câu lệnh điều kiện. Nó được gọi là  câu lệnh "switch", Nó cho phép bạn so sánh một biểu thức với nhiều giá trị khác nhau
//Ví dụ cho câu lệnh Switch
switch (a)
{
    case 5:
    {
       //Mã này sẽ chạy nếu a = 5
    }
 
    case 6:
    {
        //Mã này sẽ chạy nếu a = 6
    }
 
    case 7:
    {
        //Mã này sẽ chạy nếu a = 7
    }
 
    default:
    {
       // Đoạn mã này sẽ chạy nếu tất cả các trường hợp khác không đúng
    }
}
Nhiều điều kiện cũng có thể có trong pawn:
//Ví dụ:
switch (a)
{
    case 1, 2, 3:
    {
       //Mã này sẽ chạy nếu a = 1 hoặc =2 hoặc = 3
    }
 
    case 4, 5, 6:
    {
       //Mã này sẽ chạy nếu a = 4 hoặc a=5 hoặc a=6
    }
 
    case 7, 8, 9:
    {
       //Mã này sẽ chạy nếu a = 7 hoặc a=8 hoặc a=9
    }
 
    default:
    {
       // Đoạn mã này sẽ chạy nếu tất cả các trường hợp khác không đúng
    }
}
Bạn có thể sử dụng câu lệnh switch này cho các phạm vi:
//Ví Dụ:
switch (a)
{
    case 0 .. 50:
    {
       //Đoạn mã này sẽ chạy nếu 0 <= a <= 50
    }
 
    case 51 .. 100:
    {
       //Đoạn mã này sẽ chạy nếu 51 <= a <= 100
    }
 
    case 101 .. 200:
    {
       //Đoạn mã này sẽ chạy nếu 101 <= a <= 200
    }
 
    default:
    {
       // Đoạn mã này sẽ chạy nếu tất cả các trường hợp khác không đúng
    }
}
Lưu ý rằng khi câu lệnh Switch được chạy thì chỉ có một trường hợp xảy ra.

Looping - Vòng Lặp

Vòng lặp là điều cần thiết cho bất kỳ ngôn ngữ. Nó cho phép bạn thực hiện cùng một khối mã hơn và hơn, bằng cách xây dựng điều kiện mà mã nên được lặp đi lặp lại.

For Loops - Vòng Lặp For

Vòng đầu tiên và được sử dụng rộng rãi nhất được gọi là "vòng lặp for". Phải mất một giá trị ban đầu, một điều kiện mà trên đó nó sẽ dừng lại, và một bước. Sau đó nó thực hiện mã cho đến khi nó là điều kiện không còn đúng nữa. Điều này cho phép bạn lặp lại cùng một khối mã bất kỳ số lần. Ví dụ:
/*Một vòng lặp For có 3 thông số:
  for (initial; condition; increment)
  {
    //Mã của bạn
  }
 
  Trước khi vòng lặp đầu tiên thực hiện, nó chạy điều kiện ban đầu của bạn. 
   Sau đó, nó bắt đầu lặp mã của bạn với các bước sau: 
   1. Kiểm tra điều kiện là đúng. Nếu như vậy, tiếp tục. Nếu không, dừng lại.
   2. Chạy mã. 
   3. Khởi động "tăng" tham số. 
   4. Tới bước 1.
*/
 
//Ví dụ:
new i
new sum
for (i=1; i<=10; i++)
{
   sum += i
}
giải thích:
  1. Tham số đầu tiên, i = 1, ấn định biến i một. Điều này xảy ra trước khi bắt đầu vòng lặp.
  2. Tiếp theo, "tăng" thông số được kiểm tra. Tham số này là một nhà điều hành sau tăng, do đó 1 sẽ được thêm vào i sau khi toàn bộ khối mã được đánh giá.
  3. Sau đó, điều kiện được kiểm tra. Là i <= 10? Hôm nay là 1, do đó, nó thực sự là nhỏ hơn hoặc bằng 10.
  4. Kể từ khi điều kiện là đúng, Sum + = i được thực hiện. Điều này có nghĩa là i được thêm vào tổng.
  5. Khối mã kết thúc, và i + gia tăng + i đến 2.
  6. Bây giờ nó lặp đi lặp lại.
  7. Là i <= 10? Vâng, đó là 2. Bây giờ Sum + = i chạy một lần nữa, và bây giờ Sum tương đương với 3.
  8. Khối mã kết thúc, và bây giờ tôi tăng giá trị 3.
  9. Điều này xảy ra cho đến khi ...
  10. Các bộ tham số tăng i đến 11. Điều kiện là không còn đúng nữa, và cho vòng lặp kết thúc.
  11. Biến Sum hiện đang nắm giữ số 55, đó là số tiền của 1 đến 10.
Cung cấp một cách tốt đẹp của việc quản lý mảng!
// Lưu ý: điều này cung cấp một cách tốt đẹp để lặp qua mảng! Quan sát hàm này dưới đây.
sum_of_array(myArray[], size)
{
   // Lưu ý: Hãy chắc chắn rằng người sử dụng vượt qua kích thước của mảng, vì vậy chúng tôi không tràn nó.
   new i, sum
 
   //Vòng lặp này sẽ bắt đầu từ 0 và dừng lại khi vừa hết mảng. 
   // Vòng lặp đi từ 0 đến size-1
   for  (i=0; i<size; i++)
   {
      // Đối với mỗi vòng lặp này thực hiện, 
       // i sẽ là một số từ 0 đến size-1 
       // Thêm giá trị của các phần tử trong mảng vào biến Sum. 
       // Một khi điều này được hoàn tất, Biến Sum này sẽ chứa 
       // Tổng của tất cả phần tử trong mảng.
      sum += myArray[i]
   }
 
   return sum
}
 
new NumberArray[4]
NumberArray[0] = 3
NumberArray[1] = 1
NumberArray[2] = 4
NumberArray[3] = 1
 
new answer = sum_of_array(NumberArray, 4)
//Kết quả sẽ là 3+1+4+1, hay là 9
 
//Đây là một hàm để so sánh nếu một mảng bằng mảng khác (tức là một chuỗi)
bool:compare_arrays(array1[], array2[], size)
{
   new i
   for (i=0; i<size, i++)
   {
      / / Nếu một phần tử của mảng này không bằng mảng kia, Dừng hàm và trả về False
      if (array1[i] != array2[i])
      {
         return false
      }
   }
 
   // Nếu hàm đã đến thời điểm này mà không trở về sai, Kết quả sẽ là True.
   return true
}

While Loops - Vòng Lặp While

Các loại tiếp theo của vòng lặp cũng rất quan trọng, và đơn giản hơn một vòng lặp for. Gọi là  vòng lặp "while", nó chỉ mất một tham số: một điều kiện. Miễn là điều kiện là đúng, nó thực thi mã. Xem các ví dụ trên được viết lại với vòng lặp "while".
//vòng lặp cơ bản
new i=0
new sum
 
while (++i <= 10)
{
   sum+=i
}
 
sum_of_array(array[], size)
{
   new i=0, sum
 
   //Thực hiện vòng lặp trong khi i còn nhỏ hơn Size
   //i được tăng lên vào cuối vòng lặp.
   while (i++ < size)
   {
      sum += array[i]
   }
 
   return sum
}
 
bool:compare_arrays(array1[], array2[], size)
{
   new i
   while (i++ < size)
   {
      if (array1[i] != array2[i])
      {
         return false
      }
   }
 
   return true
}

Two Dimensional Arrays - Mảng 2 chiều

Trong Pawn có thể có mảng nơi mỗi phần tử là một mảng khác. Điều này là rất hữu ích để lưu trữ một bảng dữ liệu, nơi mà phần đầu tiên của khe cắm là một hàng và phần thứ hai của khe cắm là một cột. Hai mảng chiều được khai báo như sau:
// Khai báo một mảng với 50 hàng và 50 cột.
new BigArray[50][50]
// Khai báo một mảng số thực với 25 dòng và 10 cột.
new Float:BigArray[25][10]
Mỗi phần tử trong mảng trở thành mảng riêng của mình.
new BigArray[3][3]
BigArray[0][0] = 10
BigArray[0][1] = 20
BigArray[0][2] = 30
BigArray[1][0] = 40
BigArray[1][1] = 50
BigArray[1][2] = 60
BigArray[2][0] = 70
BigArray[2][1] = 80
BigArray[2][2] = 90
Sẽ cho kết quả BigArray như thế này:
BigArray012
0102030
1405060
2708090
Lưu ý rằng hàm sum_of_array() cũ của chúng tôi vẫn có thể làm việc! Chúng tôi có thể làm:
new sum = sum_of_array(BigArray[2], 3)
Bởi vì BigArray[2] cũng là một mảng nó chứa {30,60,90} nên điều này vẫn hợp lệ. Ví dụ dưới đây sẽ tính tổng mảng hai chiều:

sum_of_table(array[][], rows, cols)
{
   new i, j, sum
 
   // Lưu ý, có một vòng lặp bên trong vòng lặp. 
    / / Điều này cho phép bạn đi qua từng mảng bên trong Mảng lớn hơn.
   for (i=0; i<rows; i++)
   {
      for (j=0; j<cols; j++)
      {
         sum += array[i][j]
      }
   }
 
   return sum
}
Lưu ý, nó cũng có thể lưu trữ một mảng các chuỗi sử dụng hai mảng chiều.
new StringList[3][] = {"Hello", "my", "friend"}
/*
  StringList[0][0] through [0][5] contains "Hello"
  StringList[1][0] through [1][2] contains "my"
  StringList[2][0] through [2][6] contains "friend"
*/
So sánh chuỗi trong mảng đa chiều cũng tương tự:
if (StringList[0] == "Hello")       //KHÔNG HỢP LỆ
if (StringList[0][0] == "Hello")    //KHÔNG HỢP LỆ
if (equali(StringList[0], "Hello")) //HỢP LỆ

Compiler Pre-processor Directives - Chỉ thị biên dịch trước xử lý

Chỉ thị biên dịch cho phép bạn thay đổi cách mã của bạn đọc. Điều này là khá cao và sẽ chỉ được chạy trên một thời gian ngắn.
// Để liên kết một biểu tượng cho giá trị, bạn có thể làm như sau: 
#define SYMBOL VALUE
//Ví dụ:
 
#define MAX_STRING 250
new String[MAX_STRING]
 
#define HELLO "Xin Chào. Đây là một lời chào chung" 
new Hello[MAX_STRING] = HELLO
- Bạn cũng có thể sử dụng #define để thay đổi mã của trình biên dịch mã tạo ra.
#if defined LINUX
   // Phần này sẽ được biên dịch nếu #define LINUX tồn tại 
   execute_command("ls -l")
#else
   // Phần này sẽ được biên dịch nếu #define LINUX không tòn tại 
   execute_command("dir")
#endif
- Bạn cũng có thể thay đổi bao nhiêu bộ nhớ của bạn để sử dụng Script.
#pragma dynamic 4096
// Cái này tạo ra một 16K stack của bộ nhớ (mặc định). 
// Nó được đo bằng các khối cells của 4 byte.  
Bạn cũng có thể chỉ định sử dụng dấu chấm phẩy là cần thiết để chấm dứt một dòng mã (mặc định. Nó không phải là yêu cầu).
#pragma semicolon 1
 - Bạn cũng có thể thay đổi các ký tự điều khiển (amxx std: ‘^’)
#pragma ctrlchar '\'
// bây giờ bạn phải sử dụng "" thay vì "^" 
// ví dụ: "This is ^": D ^ "" bây giờ là "This is ": D  ""  

Conclusion - Kết Luận

Hướng dẫn này nên đã đưa cho bạn một giới thiệu ngắn gọn VERY để lập trình Pawn cơ bản. Nó không có nghĩa là toàn diện và không nên tạo thành toàn bộ của một người hiểu biết Pawn. Để đọc các tài liệu hướng dẫn Pawn chính thức và ngôn ngữ hướng dẫn, đi trang web này:. Http://www.compuphase.com/pawn/Pawn_Language_Guide.pdf (Lưu ý, hướng dẫn này là rất dài và cần được sử dụng như một tài liệu tham khảo Bạn có thể muốn thử các diễn đàn nhỏ hoặc các diễn đàn AMX Mod X). Tiếp tục các mục tiếp theo để xem làm thế nào để áp dụng chương trình nhỏ cho Half-Life và AMX Mod X!

0 nhận xét:

Post a Comment