For Milestone 2, the simplest way to do it (in terms of coding) is to check the winner on a board without being aware of its last move. However, at not-too-much extra coding you can keep the winner with the board, as your current makeMove does. But you will need to find the winner of the STARTING board, which will require a generalized version of checkWinner that doesn't know the last location. It is okay if that is inefficient, cause you will only use it once.
As a someday, you should consider making an efficient checkWinner that doesn't use the last location, or making the ones that does use the last location more efficient by not indexing as much.
If Milestone 2 gets too clunky, definitely drop the "tuple-returning" makeMove. You can go back and make an efficient checkWinner if you need.
For Milestone 2, the simplest way to do it (in terms of coding) is to check the winner on a board without being aware of its last move. However, at not-too-much extra coding you can keep the winner with the board, as your current makeMove does. But you will need to find the winner of the STARTING board, which will require a generalized version of checkWinner that doesn't know the last location. It is okay if that is inefficient, cause you will only use it once.