رمز السطر الجديد (\n) وتنسيق اللوحة
نريد الآن حل مشكلة عرض لوحة Tic-Tac-Toe. هذه إحدى الطرق الممكنة لطباعة اللوحة:
def print_board(board):
for row in board:
print(''.join(row))
print_board([['X', 'O', 'X'], [' ', 'O', 'O'], [' ', 'X', ' ']])
إذا لم تكن تعرف ما تفعله "".join، يمكنك البحث عنها وفهم المثال بالتجربة.
هذه بداية جيدة، لكن الأفضل أن تكون لدينا دالة تعيد نصًا بدل أن تطبعه مباشرة. عندها يستطيع أي كود آخر استخدام النص بطرق مختلفة: يمكن تعديله، أو وضع إطار حوله، أو أخذ بضعة أسطر منه، أو حفظه في ملف بدل الشاشة. وفي حالتنا نريد أيضًا اختباره باستخدام check_result.
هذا لا يعمل كما نريد:
check_result(print_board([...]), "...")
لأن print_board لا تستخدم return، ولذلك تعيد None تلقائيًا.
نريد بدل ذلك شيئًا من الشكل:
def format_board(board):
...
return ...
check_result(format_board([...]), "...")
ثم يمكن لـprint(format_board(board)) أن يطبع لوحة مثل التي رأيناها في البداية.
لكن كيف نكتب ونختبر نصًا يحتوي على عدة أسطر؟ قد نرغب في كتابة شيء كهذا:
check_result(
format_board([
['X', 'O', 'X'],
[' ', 'O', 'O'],
[' ', 'X', ' ']
]),
"XOX
OO
X "
)
جرّب وسترى أن كتابة النص بهذه الطريقة لا تعمل.
عادة يجب أن تكون السلسلة النصية المكتوبة بعلامة اقتباس واحدة أو مزدوجة في سطر واحد، لذلك هذا غير صالح:
string = "First line
Second line"
print(string)
لكن بايثون يوفر طريقة لكتابة نص يمتد على أكثر من سطر: علامات الاقتباس الثلاثية، أي ثلاث علامات اقتباس متتالية، سواء ثلاث علامات اقتباس مفردة أو ثلاث علامات اقتباس مزدوجة، حول محتوى النص.
شغّل المثال التالي:
string = 'First line\n Second line'
print(string)
string = 'First line
Second line'
print(string)
رائع! يمكن للنص ذي علامات الاقتباس الثلاثية أن يمتد على عدة أسطر، وتظهر هذه الأسطر فعلًا في الناتج.
وكما في علامات الاقتباس المفردة والمزدوجة، فهذه مجرد صيغة لكتابة النص وليست نوعًا جديدًا من البيانات. """abc""" هي القيمة نفسها التي تكتبها هكذا: "abc".
لكن المتغير string يحتوي على شيء جديد. اكتب string في الطرفية لترى التمثيل الداخلي.
هذا هو السر: \n يمثل محرف سطر جديد(newline).
هو محرف واحد، مثل الحرف العادي أو المسافة ' '. إنه المحرف الموجود بين سطرين منفصلين عندما تضغط Enter.
داخل النص الحرفي في بايثون، الصيغة \n تمثل محرف السطر الجديد. القيمة النصية نفسها لا تحتوي على حرفي \ وn منفصلين، وإنما تحتوي على محرف واحد. يمكنك التحقق من ذلك في الطرفية بقياس طول نص يحتوي على سطر جديد واحد.
استخدم الآن محرف السطر الجديد لكتابة الدالة format_board. يجب أن يعمل الحل مع لوحة مربعة board بأي حجم:
def format_board(board):
...
check_result(
format_board([
['X', 'O', 'X'],
['O', ' ', ' '],
[' ', 'X', 'O']
]),
'XOX\nO \n XO'
)
ابنِ نصًا للوحة كلها. أضف أحرف كل صف، ثم أضف \n بين الصفوف. انتبه إلى أن الصف الأخير لا يحتاج إلى سطر جديد بعده.
def format_board(board):
...
check_result(
format_board([
['X', 'O', 'X'],
['O', ' ', ' '],
[' ', 'X', 'O']
]),
'XOX
O
XO'
)
انظر جيدًا إلى حالة الاختبار التي أعطيناك إياها؛ فيها كل ما تحتاجه.
تحتاج إلى بناء نص يمثل اللوحة كلها. ابدأ بنص فارغ.
لكل صف، أضف محارف ذلك الصف إلى النص.
ستحتاج إلى حلقة متداخلة.
عند نهاية الصف، أضف سطرًا جديدًا قبل الصف التالي.
'\n'محرف مثل أي محرف آخر؛ يمكنك إضافته كالمعتاد باستخدام+.لاحظ أن نهاية الصف الأخير تختلف عن بقية الصفوف.
قبل إضافة سطر جديد، تحقق هل هذا هو الصف الأخير أم لا.
الحلقة الخارجية يجب أن تمر على طول اللوحة.
ثم تحقق هل وصلت إلى آخر فهرس أم لا.
ممتاز! حل نموذجي يمكن أن يكون:
def format_board(board):
result = ''
for i in range(len(board)):
for char in board[i]:
result += char
if i != len(board) - 1:
result += '\n'
return result
وإذا بحثت عن join واستخدمتها، فهذا ممتاز أيضًا. قد يكون الحل مثل:
def format_board(board):
joined_rows = []
for row in board:
joined_rows.append("".join(row))
return "\n".join(joined_rows)
يمكنك الانتقال إلى الصفحة التالية، أو حل تحدٍّ إضافي: اكتب نسخة محسنة من format_board تعرض فواصل الصفوف والأعمدة. إذا كانت:
board = [
['X', 'O', 'X'],
[' ', 'O', 'O'],
[' ', 'X', ' ']
]
فيجب أن يطبع print(format_board(board)):
X|O|X
-+-+-
|O|O
-+-+-
|X|
ويجب أن يعمل مع لوحة مربعة بأي حجم.
استخدام join مناسب جدًا هنا. الاختبار:
def format_board(board):
...
check_result(
format_board([
['X', 'O', 'X'],
['O', ' ', ' '],
[' ', 'X', 'O']
]),
'X|O|X\n-+-+-\nO| | \n-+-+-\n |X|O'
)
هناك نوعان من الأسطر: أسطر القطع وبينها |، وأسطر الفصل المكونة من - وبينها +. ابنِ كل نوع باستخدام join، ثم اجمع الأسطر مع محارف السطر الجديد.
def format_board(board):
result = ''
for i in range(len(board)):
for char in board[i]:
result += char
if i != len(board) - 1:
result += '
'
return result
def format_board(board):
joined_rows = []
for row in board:
joined_rows.append("".join(row))
return "
".join(joined_rows)
def format_board(board):
...
check_result(
format_board([
['X', 'O', 'X'],
['O', ' ', ' '],
[' ', 'X', 'O']
]),
'X|O|X
-+-+-
O| |
-+-+-
|X|O'
)
هناك نوعان من الأسطر: أسطر تفصل القطع فيها علامات
|، وأسطر تفصل الشرطات-فيها علامات+.يمكن بناء النوعين باستخدام
joinبالشكل المناسب.مثلًا، كيف تحول الصف
['X', 'O', 'X']إلى'X|O|X'باستخدامjoin؟وبالمثل، كيف تحصل على
'-+-+-'باستخدامjoin؟ وعلى أي قائمة ستطبقjoin؟بعد أن تعرف كيف تبني نوعي الأسطر، كيف تجمعهما للحصول على الناتج النهائي؟
لاحظ أن أسطر
+-متطابقة دائمًا.ويوجد سطر
+-واحد بين كل سطرين متتاليين من أسطر القطع.يمكنك استخدام
joinعلى الأسطر نفسها.يمكن جمع أسطر القطع مع وضع سطر
+-بينها، وإضافة محارف السطر الجديد في الأماكن المناسبة.لذلك احتفظ أولًا بأسطر القطع داخل قائمة أثناء بنائها.
ثم طبّق
joinعلى تلك القائمة واجعل سطر+-هو الفاصل.لإضافة محارف السطر الجديد إلى سطر
+-بالشكل الصحيح، انظر إلى حالة الاختبار المعطاة.
عمل ممتاز! كان هذا تحديًا حقيقيًا.
أصبحت تعرف كيف تبني نصًا مكوّنًا من عدة أسطر، وحللت مشكلة عرض لوحة اللعبة للاعبين.
بعد ذلك ستتعلم المزيد عن الأنواع في بايثون وكيفية التحويل بينها، ثم كيفية استقبال إدخال اللاعبين. أنت الآن تقريبًا في منتصف مشروع اللعبة، فواصل.