بازه فاصلهای بین دو مقدار را نشان میدهد.
رایجترین نوعهایی که از بازه پشتیبانی میکنند Int، Char و String هستند.
از بازهها میتوان برای کارهای زیادی استفاده کرد؛ مثل ساختن سریع یک مجموعه، برش دادن رشتهها، بررسی اینکه یک مقدار درون یک بازه قرار دارد یا نه، و پیمایش.
بازهها با عملگر بازه .. یا ... ساخته میشوند (بهترتیب شامل و غیرشامل).
1..5 # A range containing 1, 2, 3, 4, 5
1...5 # A range containing 1, 2, 3, 4
دلیل وجود دو عملگر بازه این است که بتوان بازههایی ساخت که مقدار پایانی را شامل شوند یا نه، که مثلاً هنگام کار با ایندکسهای صفرمبنا به کار میآید.
بازهها را میتوان با سازندهی Range هم ساخت.
Range.new(1, 5) # A range containing 1, 2, 3, 4, 5
وقتی در Crystal با عملگرهای بازهی .. یا ... یک بازه میسازید و میخواهید متدی را روی آن فراخوانی کنید، باید بازه را داخل پرانتز بگذارید.
چون در غیر این صورت، متد روی آرگومان دومِ عملگر بازه فراخوانی میشود.
(1..5).size # => 5
1..5.size # => Error: undefined method 'size' for Int32
وقتی میخواهید رشتهای را برش دهید، میتوانید از عملگر بازه برای گرفتن زیررشته استفاده کنید. یعنی با ساختن بازهای که ایندکس شروع و پایان زیررشته را مشخص میکند.
"Hello World"[0..4] # => "Hello"
"Hello World"[6..10] # => "World"
همچنین میتوانید از ایندکسهای منفی استفاده کنید تا زیررشته را از انتهای رشته بگیرید.
"Hello World"[-5..-1] # => "World"
"Hello World"[6..-4] # => "Wo"
بازهها مجموعهای از متدها دارند که میتوان برای کار با آنها از آنها استفاده کرد. برای مثال، با این متدها میتوان مجموع همهی مقادیر بازه را به دست آورد یا بررسی کرد که آیا بازه مقدار مشخصی را شامل میشود یا نه.
| متد | توضیح | مثال |
|---|---|---|
sum |
مجموع همهی مقادیر بازه را برمیگرداند | (1..5).sum # => 15 |
size |
اندازهی بازه را برمیگرداند | (1..5).size # => 5 |
includes? |
اگر بازه مقدار دادهشده را شامل شود true و در غیر این صورت false را برمیگرداند |
(1..5).includes?(3) # => true |
یک بازه میتواند بیپایان یا بیآغاز باشد.
در بازهی بیپایان یا بیآغاز، مقدار شروع یا پایانش nil است، اما هنگام تعریف بازه میتوان nil را حذف کرد.
استفاده از بازههای بیآغاز و بیپایان وقتی مفید است که مثلاً بخواهید رشتهای را از ابتدا یا تا انتها برش دهید.
"Hello World"[0..] # => "Hello World"
"Hello World"[4..] # => "o World"
"Hello World"[..5] # => "Hello"
اگر بازهی بیپایان روی یک مجموعه استفاده نشود، در صورت بیاحتیاطی میتواند به یک دنبالهی بیپایان منجر شود.
Char
میتوان از کاراکترها در بازهها استفاده کرد و این امکان را دارد که فاصلهای از کاراکترها بین دو کاراکتر به دست آورید. برای مثال، وقتی بخواهید الفبا را به دست آورید، این کار به کار میآید.
'a'..'z' # A range containing ['a', 'b', 'c', ..., 'z']
String
از رشتهها هم میتوان در بازهها استفاده کرد و به این ترتیب فاصلهای از رشتهها بین دو رشته به دست میآید.
اما رفتارش وقتی در یک بازهی رشتهای چند کاراکتر به کار میرود، کمی با رفتار Char فرق دارد.
رفتارش در بازههای رشتهای پیچیدهتر میتواند گیجکننده شود، پس احتیاط کنید.
("aa".."az") # A range containing ["aa", "ab", "ac", ..., "az"]
به عنوان یک علاقهمند به شطرنج، میخواهید نسخهی خودتان از این بازی را بنویسید. درست است که شاید همین حالا پیادهسازیهای زیادی از شطرنج به صورت آنلاین در دسترس باشد، اما نسخهی شما یگانه خواهد بود!
شما کار را با پیادهسازی یک سیستم حرکت پایه برای مهرهها شروع میکنید.
بازی شطرنج روی صفحهای به عرض هشت خانه و طول هشت خانه انجام میشود. خانهها با یک حرف و یک عدد مشخص میشوند.
بازی باید رتبههای صفحه را نگه دارد. رتبهها همان سطرهای صفحه هستند و از ۱ تا ۸ شمارهگذاری میشوند.
بازی همچنین باید فایلهای صفحه را نگه دارد. فایلها همان ستونهای صفحه هستند و با حروف A تا H مشخص میشوند.
ثابتهای Chess::RANKS و Chess::FILES را تعریف کنید که به ترتیب بازهی رتبهها و فایلها را نگه میدارند.
Chess::RANKS
# => 1..8
Chess::FILES
# => 'A'..'H'
بازی باید بررسی کند که آیا یک خانه معتبر است. یک خانه زمانی معتبر است که رتبه و فایل آن در محدودهی رتبهها و فایلها باشند.
متد Chess.valid_square? را تعریف کنید که دو آرگومان میگیرد: rank که عددی صحیح از رتبه را نگه میدارد و file که کاراکتری از فایل را نگه میدارد.
متد باید اگر رتبه و فایل در محدودهی رتبهها و فایلها باشند true را برگرداند و در غیر این صورت false را.
Chess.valid_square?(1, 'A')
# => true
بازی باید اسم مستعار بازیکن را به دست آورد. اسم مستعار از دو کاراکتر اول اسم کوچک بازیکن و دو کاراکتر آخر اسم خانوادگی او ساخته میشود. اسم مستعار باید با حروف بزرگ نوشته شود.
متد Chess.nickname را تعریف کنید که دو آرگومان میگیرد: first_name که رشتهای از اسم کوچک بازیکن را نگه میدارد و last_name که رشتهای از اسم خانوادگی بازیکن را نگه میدارد.
متد باید اسم مستعار بازیکن را به صورت یک رشته با حروف بزرگ برگرداند.
Chess.nickname("John", "Doe")
# => "JOOE"
بازی باید برای هر حرکت پیامی بسازد تا بگوید کدام بازیکن به کدام خانه حرکت کرده است. این پیام باید از اسم مستعار بازیکن و خانهای که به آن حرکت کرده استفاده کند. بازی همچنین باید با بررسی اینکه آیا فایل و رتبهی خانه در محدودهی فایلها و رتبهها هستند یا نه، معتبر بودن حرکت را مشخص کند.
اگر حرکت معتبر باشد، پیام باید این باشد: "{nickname} moved to {square}"
اگر حرکت معتبر نباشد، پیام باید این باشد: "{nickname} attempted to move to {square}, but that is not a valid square"
متد Chess.move_message را تعریف کنید که سه آرگومان میگیرد: first_name که رشتهای از اسم کوچک بازیکن را نگه میدارد، last_name که رشتهای از اسم خانوادگی بازیکن را نگه میدارد و square که رشتهای از خانهای را نگه میدارد که بازیکن به آن حرکت کرده است.
متد باید پیام حرکت را به صورت یک رشته برگرداند.
Chess.move_message("John", "Doe", "A1")
# => "JOOE moved to A1"