تسجيل الحركات بتعديل القوائم المتداخلة
تعلمنا استقبال إدخال المستخدم. الآن سنستخدم ذلك لوضع القطع فعلًا على اللوحة والبدء في اللعب.
جرّب هذا الكود أولًا:
def play_move(board, player):
board[1] = player
def play_game():
game_board = [' ', ' ', ' ']
play_move(game_board, 'X')
print(game_board)
play_game()
لاحظ أن استدعاء play_move(game_board, 'X') يعدّل game_board نفسها مباشرة. المتغير board داخل استدعاء play_move والمتغير game_board في الدالة المستدعية يشيران إلى كائن القائمة نفسه؛ لا تُنشأ نسخة جديدة.
لذلك لا تحتاج play_move في هذه الحالة إلى إعادة شيء. يكفي أن تعدّل board، وسيرى المستدعي التغيير.
لكن اللوحة ثنائية الأبعاد وممثلة بقائمة متداخلة، لذلك نحتاج إلى إسناد player إلى عنصر داخل قائمة داخلية. يمكن فعل ذلك مثل:
def play_move(board, player):
row = board[1]
row[0] = player
def play_game():
board = [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
play_move(board, 'X')
print(board)
play_game()
يمكن دمج السطرين:
row = board[1]
row[0] = player
في سطر واحد:
board[1][0] = player
الكودان متكافئان تقريبًا. يقيّم بايثون أولًا board[1] للحصول على القائمة الداخلية، ثم يطبق [0] = ... لتعديل عنصر داخل تلك القائمة.
الآن اجعل الحركة تفاعلية. اكتب نسختك من play_move بحيث تستدعي input() مرتين: مرة لرقم الصف ومرة لرقم العمود. المستخدم يعد من 1، بينما فهارس القوائم تبدأ من 0.
إذا أدخل المستخدم:
2
1
فهذا يعني الصف الثاني والعمود الأول، أي الموضع نفسه الذي استخدمناه في المثال السابق.
إليك كود البداية:
def format_board(board):
first_row = ' '
for i in range(len(board)):
first_row += str(i + 1)
joined_rows = [first_row]
for i in range(len(board)):
joined_row = str(i + 1) + ''.join(board[i])
joined_rows.append(joined_row)
return "\n".join(joined_rows)
def play_game():
board = [
[' ', ' ', ' '],
[' ', ' ', ' '],
[' ', ' ', ' '],
]
print(format_board(board))
print('\nX to play:\n')
play_move(board, 'X')
print(format_board(board))
print('\nO to play:\n')
play_move(board, 'O')
print(format_board(board))
def play_move(board, player):
...
play_game()
يستدعي المثال play_move مرتين، لذلك سيدخل المستخدم زوجين من الأرقام. المهم أن تعدّل دالتك board في المكان الصحيح؛ لا تحتاج إلى طباعة أو إعادة قيمة من play_move نفسها.
يمكنك افتراض أن المستخدم سيدخل أرقامًا صحيحة وصالحة. سنتعامل مع الإدخال غير الصالح لاحقًا. تذكّر أن input() تعيد نصًا، وأنك تحتاج إلى تحويله إلى عدد ثم تحويل 1..n إلى فهارس 0..n-1 قبل استخدام الفهرسة المتداخلة.
def format_board(board):
first_row = ' '
for i in range(len(board)):
first_row += str(i + 1)
joined_rows = [first_row]
for i in range(len(board)):
joined_row = str(i + 1) + ''.join(board[i])
joined_rows.append(joined_row)
return "
".join(joined_rows)
def play_game():
board = [
[' ', ' ', ' '],
[' ', ' ', ' '],
[' ', ' ', ' '],
]
print(format_board(board))
print('
X to play:
')
play_move(board, 'X')
print(format_board(board))
print('
O to play:
')
play_move(board, 'O')
print(format_board(board))
def play_move(board, player):
...
play_game()
دالتك تحتاج إلى استدعاء
input()مرتين. الإدخال لا يُمرر إلىplay_moveكوسيط.input()تعيد نصًا دائمًا.حتى لو بدا النص كرقم، فهو يظل نصًا.
فهارس القوائم يجب أن تكون أعدادًا، لا نصوصًا.
إذا كانت اللوحة 3×3، فقد يدخل المستخدم 1 أو 2 أو 3 لكل إحداثي.
ما الفهارس الصالحة لقائمة طولها 3؟
تحتاج إلى تحويل إدخال 1 أو 2 أو 3 إلى 0 أو 1 أو 2.
ويجب أن يعمل الحل أيضًا مع لوحات أكبر مثل 9×9 وما بعدها.
لا يمكنك إجراء حسابات على النصوص؛ تحتاج إلى أعداد.
كيف تحوّل نصًا إلى عدد؟
بعد حصولك على عددين، استخدمهما لتعديل القائمة المتداخلة
board.الكود اللازم لذلك ظهر لك أعلاه.
استخدم فقط الأعداد القادمة من إدخال المستخدم بدل القيمتين الثابتتين 1 و0.
يمكنك استخدام فهرسة متداخلة في سطر واحد، أو تنفيذها على خطوتين.
رائع! اقتربت جدًا من تجميع أجزاء اللعبة كلها معًا. واصل.