Submission for tic tac toe lab.

What I changed
I completed checkpoints 1-3. I would have submitted all three separately, but a bug prohibited my initial submissions.
I also started working on the nim section of the lab.

Why I changed it
I made these changes in order to make a functions tic tac toe and nim game.

Estimate for remaining time to finish assignment: 15 minutes
This commit is contained in:
Danielle Tear 2024-02-10 12:01:44 -05:00
parent 8f32985ecb
commit 736cba0006
8 changed files with 94 additions and 14 deletions

50
nim/game.py Normal file
View File

@ -0,0 +1,50 @@
class NimGame:
def get_initial_state(self):
return {
"board": [1, 3, 5, 7],
"first_player": True
}
def get_next_state(self, state, action):
board = state["board"].copy()
row = action[0]
number_to_remove = action[1]
board[row] = board[row] - number_to_remove
next_state = {
"board": board,
"first_player": not state["first_player"],
}
return next_state
def get_actions(self, state):
options = []
for num in range(4):
row = state["board"][num]
if row >=3:
options.append((num, 1))
options.append((num, 2))
options.append((num, 3))
elif row == 2:
options.append((num, 1))
options.append((num, 2))
elif row == 1:
options.append((num, 1))
return options
def get_reward(self, state):
if state["first_player"]:
return 1
elif not state["first_player"]:
return -1
else:
return 0
def is_over(self, state):
for row in state["board"]:
if row != 0:
return False
return True
def get_objective(self, state):
return max if state["first_player"] else min

View File

@ -1,10 +1,10 @@
from nim.game_stub import NimGameStub
from nim.game import NimGame
from strategy.lookahead_strategy import LookaheadStrategy
class HumanNimPlayer:
def __init__(self, name):
self.name = name
self.game = NimGameStub()
self.game = NimGame()
def choose_action(self, state):
actions = self.game.get_actions(state)
@ -26,7 +26,7 @@ class HumanNimPlayer:
class ComputerNimPlayer:
def __init__(self, name):
self.name = name
self.strategy = LookaheadStrategy(NimGameStub(), max_depth=3, deterministic=False)
self.strategy = LookaheadStrategy(NimGame(), max_depth=3, deterministic=False)
def choose_action(self, state):
action = self.strategy.choose_action(state)

View File

@ -1,9 +1,9 @@
from nim.game_stub import NimGameStub
from nim.game import NimGame
class NimView:
def __init__(self, player0, player1):
self.players = [player0, player1]
self.game = NimGameStub()
self.game = NimGame()
def greet(self):
print(f"{self.players[0].name} and {self.players[1].name}, welcome to Nim.")

View File

@ -6,16 +6,21 @@ Which class is responsible for each of the following behaviors?
For each, explain how the behavior is accomplished.
### Checking to see whether the game is over
The game class is responsible for checking to see if the game is over. The method is_over checks the current
state of the game to see if the board is full or if either X or O has won. If any of these three things are true,
the game is over.
### Determining which actions are available at a particular state
The game class is responsible for determining which actions are available at a particular state. The get_actions
method returns a list of the indices of open spaces. These are the actions that are available at that state.
### Showing the board
The view class is responsible for showing the board. The format_row and format_value methods are responsible for formatting, and the print_board method displays the board to the user. The board is actually shown when the get_action method is called.
### Choosing which action to play on a turn
The player class is responsible for choosing which action to play on a turn. The choose_action method prompts the player to choose the action.
## Checkpoint 2 Notes
For Checkpoint 2, I just programmed the method to check every possible winning combination in the game.
### TTT Strategy
For each of the following board states, if you are playing as X
@ -27,9 +32,15 @@ and it's your turn, which action would you take? Why?
---+---+--- ---+---+--- ---+---+--- ---+---+---
| | | | O | | | |
For the first board I would choose the middle row right column because that would result in a win.
For the second board, I would choose the middle row right column to prevent the other player from winning next turn.
For the third board, I would choose the top row left column because it would guarantee a win on my next turn.
For the last board, I would choose the middle space. That would force my opponent to take the bottom right. Then I could take the bottom left and win on my next turn.
### Initial game state
You can get the inital game state using game.get_initial_state().
What is the current and future reward for this state? What does this mean?
The current and future reward for this state is 0. That means that if both players play optimally, the game will result in a tie.

View File

@ -1,11 +1,11 @@
from nim.game_stub import NimGameStub
from nim.game import NimGame
from nim.view import NimView
from nim.player import HumanNimPlayer, ComputerNimPlayer
player0 = HumanNimPlayer(input("What's your name? "))
player1 = ComputerNimPlayer("Robot")
view = NimView(player0, player1)
game = NimGameStub()
game = NimGame()
view.greet()
state = game.get_initial_state()

View File

@ -3,7 +3,7 @@ from ttt.view import TTTView
from ttt.player import TTTHumanPlayer, TTTComputerPlayer
player0 = TTTHumanPlayer("Player 1")
player1 = TTTHumanPlayer("Player 2")
player1 = TTTComputerPlayer("Robot")
game = TTTGame()
view = TTTView(player0, player1)

View File

@ -58,4 +58,22 @@ class TTTGame:
def check_winner(self, state, symbol):
"Checks whether the player with `symbol` has won the game."
return False
board = state["board"]
if board[0] == symbol and board[1] == symbol and board[2] == symbol:
return True
elif board[3] == symbol and board[4] == symbol and board[5] == symbol:
return True
elif board[6] == symbol and board[7] == symbol and board[8] == symbol:
return True
elif board[0] == symbol and board[3] == symbol and board[6] == symbol:
return True
elif board[1] == symbol and board[4] == symbol and board[7] == symbol:
return True
elif board[2] == symbol and board[5] == symbol and board[8] == symbol:
return True
elif board[0] == symbol and board[4] == symbol and board[8] == symbol:
return True
elif board[2] == symbol and board[4] == symbol and board[6] == symbol:
return True
else:
return False

View File

@ -1,5 +1,6 @@
from click import Choice, prompt
from strategy.random_strategy import RandomStrategy
from strategy.lookahead_strategy import LookaheadStrategy
from ttt.game import TTTGame
import random
@ -24,7 +25,7 @@ class TTTComputerPlayer:
def __init__(self, name):
"Sets up the player."
self.name = name
self.strategy = RandomStrategy(TTTGame())
self.strategy = LookaheadStrategy(TTTGame(), deterministic=False)
def choose_action(self, state):
"Chooses a random move from the moves available."