مسئلهای که باید حل میکردم
در یک بازی کارتی، مرتبشدن دست برای خوانایی خوب هست؛ در بازی دیگر ممکنه اطلاعات بدهد. نمیخواستم اضافهکردن هر کارت خودکار ترتیب دست را عوض کنه.
پیادهسازی در نسخهٔ فعلی
CardHand افزودن، حذف، پاککردن و Sort را جدا نگه میدارد. RemoveCardByInstanceId شناسه را جستوجو میکنه و همان نمونهٔ حذفشده را به فراخواننده برمیگرداند.
تصمیم و هزینهٔ طراحی
ICardSortStrategy قابل تعویض هست و راهبرد پیشفرض فقط وقتی Sort صدا زده بشه اجرا میشود. این اختیار را به جریان بازی دادم، نه به خود فهرست کارتها.
مرزهای فعلی
AddCard تکراریبودن نمونه را بررسی نمیکنه و AddCards در میانهٔ پیمایش ممکنه با ورودی نامعتبر متوقف بشه. این کلاس بهتنهایی تضمین همهٔ ناورداهای بازی نیست.
مالکیت کارت جدا از جای آن در دست
یک سناریوی حساس، انتخاب کارت درست بعد از اضافه شدن چند کارت تازه هست. CardHand.AddCard تنها ورودی null را رد میکنه و نمونه را به انتهای فهرست میافزاید؛ Sort خودکار اجرا نمیشود. این رفتار اجازه میدهد ترتیب دریافت کارت برای مرحلهای از بازی حفظ بشه، سپس بازی در زمان مناسب تصمیم به مرتبسازی بگیرد. در حکم ممکنه خواندن خالها مهم باشد، اما در جوکر ترتیب دست میتواند بر نحوهٔ انتخاب از بازیکن دیگر اثر بگذارد. یک مجموعهٔ عمومی نباید پیشاپیش این تصمیم نمایشی را برای هر دو بازی بگیرد.
RemoveCardByInstanceId با خروجی removedCard علاوه بر پاسخ موفق یا ناموفق، همان شیئی را تحویل میدهد که از دست خارج شده. این خروجی برای انتقال مالکیت قابل استفاده هست: فراخواننده لازم نیست دوباره از روی رتبه و خال حدس بزند کدوم کارت جابهجا شده. در مقابل، RemoveCard نمونهٔ ورودی را در فهرست پیدا میکنه و Contains نیز با همان قرارداد مجموعه کار میکنه. هیچکدام کل بازی را از نظر حضور یک کارت در دو دست بررسی نمیکنند؛ کنترل این ناوردای بزرگتر بر عهدهٔ مسیر انتقال کارت میماند.
AddCards بهصورت مرحلهای AddCard را برای اعضای ورودی اجرا میکنه. اگر عضو سوم null باشد، دو عضو قبلی قبلاً اضافه شدهاند؛ پس این عملیات همه یا هیچ نیست. این جزئیات برای مسیر بازی مهم هست، چون رسیدگی به خطا نباید فرض کنه دست بدون تغییر باقی مانده هست. از طرف دیگر، Cards با IReadOnlyList منتشر میشود و مصرفکننده را به عملیات مشخص مجموعه هدایت میکنه. این انتخاب تغییرات را قابل پیگیریتر میکنه، ولی جای اعتبارسنجی دستهٔ ورودی یا بررسی تکرار InstanceId را نمیگیرد؛ چنین بررسیهایی در این کلاس دیده نمیشوند.
چیزی که از این مرحله یاد گرفتم
درس من این بود که ترتیب نمایشی یک تصمیم واقعی هست. دست جوکر میتواند شافل بشه و دست حکم مرتب بشه، بدون اینکه تعریف مالکیت کارت برای هر بازی دوباره نوشته بشه.
مثال عملی مرتبسازی دست کارت
برای فهم عملی مرتبسازی دست کارت، یک مثال آموزشی را قدمبهقدم دنبال کنیم. بازیکن یک کارت تازه میگیرد و کارتهای دست را بر اساس خال مرتب میکند. پیش از اجرا، وضعیت آغاز را روی کاغذ بنویس؛ مشخص کن چه چیزی میتواند تغییر کند و چه چیزی باید ثابت بماند. بعد فقط همین مسیر را اجرا کن. این مثال گزارشی از آمار کاربران یا قابلیت تازهٔ منتشرشدهٔ دلو نیست؛ تمرینی برای روشن کردن تصمیم طراحی همین مطلب است.
خطای رایج و علت آن
اگر انتخاب به اندیس وابسته باشد، مرتبسازی میتواند کارت انتخابشده را عوض کند. این خطا معمولاً وقتی پنهان میماند که فقط مسیر موفق و ظاهر نهایی را ببینیم. برای پیدا کردن علت، آخرین وضعیت درست را از نخستین وضعیت نادرست جدا کن و ببین تغییر دقیقاً در کدام مرز رخ داده است. ترتیب نمایشی به خوانایی مربوط است؛ مالکیت کارت و هویت آن باید ثابت بماند. اگر این تفاوت در قرارداد مشخص نباشد، اصلاح یک نشانه ممکن است همان مسئله را در بخش دیگری دوباره ایجاد کند.
چطور نتیجه را بررسی کنیم؟
پس از مرتبسازی، همان شناسهٔ کارت باید انتخابشده بماند و هیچ کارت تکراری ساخته نشود. اجرای یکباره برای نتیجهگیری کافی نیست؛ یک بار مسیر معمول و بار دیگر همان موقعیت را با ورودی مرزی یا تکرار اقدام بررسی کن. اگر نتیجه فرق دارد، ورودی و شرایط اجرا را همراه خروجی نگه دار تا مقایسه قابل بازسازی باشد. جدول زیر خلاصهٔ مشخصات همین سناریو است و برای ثبت نتیجهٔ بررسی به کار میآید.
| بخش بررسی | آنچه باید ثبت شود |
|---|---|
| موقعیت آزمایشی | بازیکن یک کارت تازه میگیرد و کارتهای دست را بر اساس خال مرتب میکند. |
| ریسک اصلی | اگر انتخاب به اندیس وابسته باشد، مرتبسازی میتواند کارت انتخابشده را عوض کند. |
| روش بررسی | پس از مرتبسازی، همان شناسهٔ کارت باید انتخابشده بماند و هیچ کارت تکراری ساخته نشود. |
| مرز نتیجهگیری | ترتیب نمایشی به خوانایی مربوط است؛ مالکیت کارت و هویت آن باید ثابت بماند. |
پرسشهای کاربردی دربارهٔ مرتبسازی دست کارت
از کجا شروع کنم؟
از همان موقعیت محدود این مطلب شروع کن: بازیکن یک کارت تازه میگیرد و کارتهای دست را بر اساس خال مرتب میکند. ابتدا نتیجهٔ مورد انتظار را مشخص کن و بعد سراغ پیادهسازی یا ابزار برو. وقتی مسیر پایه قابل توضیح و بررسی شد، میتوان حالتهای بیشتری اضافه کرد. ساخت همهٔ حالتها از ابتدا، فهم علت خطا را سختتر میکند.
چه زمانی میتوانم بگویم این بخش درست کار میکند؟
زمانی که رفتار در موقعیت تعریفشده با قرارداد سازگار باشد و محدودیتهای آن روشن بمانند. پس از مرتبسازی، همان شناسهٔ کارت باید انتخابشده بماند و هیچ کارت تکراری ساخته نشود. موفقیت در این آزمون دربارهٔ همان سناریو شاهد میدهد؛ از آن نمیتوان بدون بررسی دربارهٔ همهٔ دستگاهها، همهٔ قوانین محلی یا همهٔ حجمهای داده نتیجه گرفت. ترتیب نمایشی به خوانایی مربوط است؛ مالکیت کارت و هویت آن باید ثابت بماند.
برای ادامهٔ همین موضوع، هستهٔ مشترک دلو؛ یک میز برای چند بازی و بازی دلو را ببین. زمینهٔ ساخت این پروژهها و معرفی سازنده در صفحهٔ کیان پاک نعمت آمده است.




