Based on the names of the functions I believe the functions
drawBoard();
verifyWinner();
changePlayer();
are already at a different abstraction layer than tryToMakeAMove()
which seems like a much lower level, yet also appears to be a mix of responsibilities.
If your program is asking for input in a loop until a valid move is provided, then that whole process should be it's own function existing at the same level as the functions I mentioned. That process can be organized into:
- Collect player input
- Validate the input
- If invalid/show message, else perform the move
- Repeat until there's a valid move
function move(player, board) {
let moveIsValid == false;
while(!moveIsValid) {
const {line, column} = collectUserInput(player);
const moveIsValid = isMoveValid(line, column, board);
if(!moveIsValid) {
changeStatusMessage("Invalid Move!");
} else {
updateBoardWithMove(line, column, board);
}
}
}
And isMoveValid could be:
function(line, column, board) {
return board[line][column] === EMPTY
}
And finally the top level would look like this:
let currentPlayer = 'Player1';
let winner = undefined;
const board = new Board();
while (!winner) {
move(currentPlayer, board);
drawBoard(board);
winner = verifyWinner(board);
currentPlayer = changePlayer(currentPlayer);
}
celebrate(winner);