التجميع النهائي: تشغيل لعبة إكس-أو المتكاملة
حان وقت جمع كل الأجزاء في لعبة كاملة.
الكود التالي يحتوي على تنفيذات للدوال التي بنيناها في الصفحات السابقة، وبعضها يستخدم اختصارات لم تتعلمها بعد لجعل الكود أقصر. لا تغيّر هذه الدوال. مهمتك هي تنفيذ play_game بصورة صحيحة.
التنفيذ الحالي يوضح بداية اللعبة فقط، لكنه غير مكتمل. يجب أن يعمل الحل مع أي حجم لوحة، ويستمر حتى تنتهي اللعبة. آخر شيء تفعله play_game يجب أن يكون أحد أمرين:
- استدعاء
print_winner(player)إذا أصبحتwinner(board)هيTrue. - أو استدعاء
print_draw()إذا امتلأت اللوحة من دون فائز.
يمكنك افتراض أن المستخدم سيدخل مدخلات صالحة فقط: أرقامًا من 1 إلى board_size لاختيار خانة غير مشغولة.
def winning_line(strings):
strings = set(strings)
return len(strings) == 1 and ' ' not in strings
def row_winner(board):
return any(winning_line(row) for row in board)
def column_winner(board):
return row_winner(zip(*board))
def main_diagonal_winner(board):
return winning_line(row[i] for i, row in enumerate(board))
def diagonal_winner(board):
return main_diagonal_winner(board) or main_diagonal_winner(reversed(board))
def winner(board):
return row_winner(board) or column_winner(board) or diagonal_winner(board)
def format_board(board):
size = len(board)
line = f'\n {"+".join("-" * size)}\n'
rows = [f'{i + 1} {"|".join(row)}' for i, row in enumerate(board)]
return f' {" ".join(str(i + 1) for i in range(size))}\n{line.join(rows)}'
def play_move(board, player):
print(f'{player} to play:')
row = int(input()) - 1
col = int(input()) - 1
board[row][col] = player
print(format_board(board))
def make_board(size):
return [[' '] * size for _ in range(size)]
def print_winner(player):
print(f'{player} wins!')
def print_draw():
print("It's a draw!")
def play_game(board_size, player1, player2):
board = make_board(board_size)
print(format_board(board))
play_move(board, player1)
play_move(board, player2)
play_move(board, player1)
play_move(board, player2)
play_game(3, 'X', 'O')
استخدم الدوال winner وformat_board وplay_move وmake_board وprint_winner وprint_draw بدل إعادة تنفيذ عملها. تحتاج إلى حلقة تلعب عددًا أقصى من الحركات يساوي عدد خانات اللوحة. في كل دورة تُنفذ حركة لاعب واحد فقط، ثم تتحقق من الفوز، وتبدّل اللاعب إذا استمرت اللعبة.
إذا ظهر فائز، اطبع الفائز وأنهِ play_game فورًا باستخدام return. وإذا انتهت كل الحركات من دون فائز، استدعِ print_draw() بعد الحلقة مرة واحدة فقط. تأكد أن player1 يبدأ أولًا، وأنك لا تطبع التعادل داخل الحلقة قبل امتلاء اللوحة.
You should use all of the functions
winner,format_board(not counting its use inplay_move),play_move,make_board,print_winner, andprint_drawsomewhere.You only need to mention each of those functions once in your code, although some of them will be called several times as the program runs.
You will need a for loop to repeatedly play moves.
You don't need to check if the board has been filled up, because you can always calculate how many moves it takes to fill up the board.
So you can just use a loop that will run a fixed number of iterations, and inside the loop check if the loop needs to be ended early.
What's the maximum number of moves that can be played in a 3x3 board? 4x4?
A loop over a
rangeis an easy way to iterate a fixed number of times.So you can use
for _ in range(N):to play at mostNmoves.Once there's a winner, you need to end the loop and the game.
Either
print_winnerorprint_drawshould be called, not both.Whichever function is called, it must be called exactly once.
One easy way to make sure you don't call a function multiple times is to call it outside of any loop.
We've learned about two ways to make a loop stop.
One way is
break, which specifically ends one loop and no more.The second way ends not just the loop but the whole function call.
The second way is
return.Don't play moves in pairs like
play_move(board, player1)andplay_move(board, player2)in the sample code.Instead, each loop iteration should play one move.
You need a variable to keep track of which player's turn it is.
The player should be switched in each loop iteration.
An
ifstatement is a good way to do this.Especially combined with an
else.Make sure
player1plays the first move.Only call
print_winnerafter checkingwinnerwith anifstatement.You need to check for the winner inside the loop since you don't know when a player might win.
Once you call
print_winner, you can usereturnto end the function.Just
returnby itself is fine,play_gameisn't meant to return a value.Don't use
elseafter checking for a winner to callprint_drawif there isn't a winner. Just because no one has won yet doesn't mean it's a draw already.print_drawshould only be called after all moves have been played and there's still no winner.So it should be called after the loop, outside of it.
Check the indentation to make sure
print_drawisn't in the body of the for loop.
تهانينا!
لقد أنهيت اللعبة بنجاح!