0% found this document useful (0 votes)
71 views22 pages

Lab Assignment 02

This document contains code for a Python program that implements a dots and boxes game and a minimax algorithm for tic-tac-toe. The dots and boxes code includes functions for initializing the game board, printing the board, reading player input, updating the board based on player moves, and checking for a winner. The tic-tac-toe code includes functions for minimax game tree search, evaluating board states, checking for a winner, finding valid moves, and rendering the board.

Uploaded by

Mohsin Raza
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views22 pages

Lab Assignment 02

This document contains code for a Python program that implements a dots and boxes game and a minimax algorithm for tic-tac-toe. The dots and boxes code includes functions for initializing the game board, printing the board, reading player input, updating the board based on player moves, and checking for a winner. The tic-tac-toe code includes functions for minimax game tree search, evaluating board states, checking for a winner, finding valid moves, and rendering the board.

Uploaded by

Mohsin Raza
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 22

LAB ASSIGNMENT 02:

TASKS:
CODE:
#!/usr/bin/env python

# coding: utf-8

# # DOT AND BOXES

# In[2]:

N, M = 5, 5

n_players = 2

marks = ['X', 'O']

count_boxes = [0,0]

grid = [['.' for i in range(M-1)] for _ in range(N-1)]

horizontal_grid = [[False for i in range(M)] for j in range(N+1)]

vertical_grid = [[False for i in range(M+1)] for j in range(N)]

#This function prints the grid of Dots-and-Boxes as the game progresses

def print_grid():

for i in range(n_players):

print('Player %d: %c ' % (i+1, marks[i]), end='')

if i < n_players-1:

print('vs ', end='')

print()

print('--' + '------' * (M-1))

for i in range(N):
print(' . ', end = '')

for j in range(M):

print('---' if horizontal_grid[i][j] else ' ', end = '')

if j < M-1:

print(' . ', end = '')

print()

for j in range(M+1):

print(' | ' if vertical_grid[i][j] else ' ', end = '')

if i < N-1 and j < M-1:

print(grid[i][j] if grid[i][j] != '.' else ' ', end='')

print(' ', end = '')

print()

for i in range(n_players):

print('Player %c is %d'% (marks[i], count_boxes[i]))

print('--' + '------' * (M-1))

#This function checks if the grid is full or not

def check_full():

for i in range(N - 1):

for j in range(M - 1):

if(horizontal_grid[i][j] == False or vertical_grid[i][j] == False):

return False

return True

#This function checks if the given side is empty or not

def check_empty_side(i1, j1, i2, j2):

if(i1 == i2):

if(not horizontal_grid[i1][j1]):

return True

if(j1 == j2):

if(vertical_grid[i1][j1] == False):
return True

return False

#This function checks if the given position is valid in the grid or not

def check_valid_position(i, j):

if(i >= 0 and i < N and j >= 0 and j < M):

return True

return False

#This function checks if given side is valid or not

def check_valid_side(i1, j1, i2, j2):

if((i1 == i2 and abs(j1 - j2) == 1) or (j1 == j2 and abs(i1 - i2) == 1)):

return True

return False

#This function sets the given side

def set_side(i1, j1, i2, j2):

if(i1 == i2):

horizontal_grid[i1][j1] = True

else:

vertical_grid[i1][j1] = True

def is_complete_box(i, j):

if (horizontal_grid[i][j] and vertical_grid[i][j] and horizontal_grid[i + 1][j] and vertical_grid[i][j + 1]):

return True

return False

def set_box(i,j,player):

grid[i][j] = marks[player]

count_boxes[player] += 1

def set_neighbor_box( i1, j1, i2, j2, player):

if(i1 == i2 and i1 != 0 and i1 != N - 1):

if(is_complete_box(i1 - 1,j1)):
set_box(i1 - 1, j1, player)

return True

elif(j1 == j2 and j1 != 0 and j1 != M - 1):

if(is_complete_box(i1,j1-1)):

set_box(i1, j1-1, player)

return True

return False

#This function checks and sets the neighbor completed boxes

def set_neighbor_boxes(i1, j1, i2, j2, player):

flag = False

if (i1 == i2 and i1 == N - 1):

if (is_complete_box(i1 - 1, j1)):

set_box(i1 - 1, j1, player)

flag = True

elif (j1 == j2 and j1 == M - 1):

if (is_complete_box(i1, j1 - 1)):

set_box(i1, j1 - 1, player)

flag = True

elif (is_complete_box(i1, j1)):

set_box(i1, j1, player)

flag = True

if (set_neighbor_box(i1, j1, i2, j2, player)):

flag = True

return flag

#This function arranges the points of the side

def arrange_side_points(i1, j1, i2, j2):

mini = min(i1,i2)

maxi = max(i1,i2)
i1 = mini

i2 = maxi

mini = min(j1,j2)

maxi= max(j1,j2)

j1 = mini

j2 = maxi

return i1, j1, i2, j2

#This function clears the game structures

def grid_clear():

for i in range(N-1):

for j in range(M-1):

grid[i][j] = '.'

for i in range(N):

for j in range(M):

horizontal_grid[i][j] = False

vertical_grid[i][j] = False

count_boxes[0] = 0

count_boxes[1] = 0

#This function reads a valid and arranged side input

def read_input():

i1, j1, i2, j2 = map(int, input('enter your move: ').split())

i1, j1, i2, j2 = arrange_side_points(i1, j1, i2, j2)

while not check_valid_position(i1, j1) or not check_valid_position(i2, j2) or not


check_valid_side(i1, j1, i2, j2) or not check_empty_side(i1, j1, i2, j2):

i1, j1, i2, j2 = map(int, input('enter move: ').split())

i1, j1, i2, j2 = arrange_side_points(i1, j1, i2, j2)

return i1, j1, i2, j2

#MAIN FUNCTION
def play_game():

print("Dots Boxes Game")

print("Welcome. to the DOT BOX GAME")

print("***********")

player = 0

while True:

#Prints the grid

print_grid()

#Read an input position from the player

print('Player %s is playing now' % marks[player])

i1, j1, i2, j2 = read_input()

print(i1)

print(j2)

#Set the input position with the mark

set_side(i1, j1, i2, j2)

#Set the neighbor boxes with the mark

box_complete = set_neighbor_boxes(i1, j1, i2, j2, player)

#Check if the state of the grid has a complete state

if check_full():

#Prints the grid

print_grid()

#Announcement of the final statement

if count_boxes.count(max(count_boxes)) == 1:

idx_max_player = count_boxes.index(max(count_boxes))

print('Congrats, Player %s is won!' % marks[idx_max_player])

else:

print("Woah! That's a tie!")

break

#Keep the player if there is a complete box


if not box_complete:

#Player number changes after each turn

player = (player + 1) % n_players

while True:

grid_clear()

play_game()

c = input('Play Again [Y/N] ')

if c not in 'yY':

break

# # MINIMAX

# In[1]:

#!/usr/bin/env python3

from math import inf as infinity

from random import choice

import platform

import time

from os import system

"""

An implementation of Minimax AI Algorithm in Tic Tac Toe,

using Python.

This software is available under GPL license.

Author: Clederson Cruz

Year: 2017
License: GNU GENERAL PUBLIC LICENSE (GPL)

"""

HUMAN = -1

COMP = +1

board = [

[0, 0, 0],

[0, 0, 0],

[0, 0, 0],

def evaluate(state):

"""

Function to heuristic evaluation of state.

:param state: the state of the current board

:return: +1 if the computer wins; -1 if the human wins; 0 draw

"""

if wins(state, COMP):

score = +1

elif wins(state, HUMAN):

score = -1

else:

score = 0

return score

def wins(state, player):


"""

This function tests if a specific player wins. Possibilities:

* Three rows [X X X] or [O O O]

* Three cols [X X X] or [O O O]

* Two diagonals [X X X] or [O O O]

:param state: the state of the current board

:param player: a human or a computer

:return: True if the player wins

"""

win_state = [

[state[0][0], state[0][1], state[0][2]],

[state[1][0], state[1][1], state[1][2]],

[state[2][0], state[2][1], state[2][2]],

[state[0][0], state[1][0], state[2][0]],

[state[0][1], state[1][1], state[2][1]],

[state[0][2], state[1][2], state[2][2]],

[state[0][0], state[1][1], state[2][2]],

[state[2][0], state[1][1], state[0][2]],

if [player, player, player] in win_state:

return True

else:

return False

def game_over(state):

"""

This function test if the human or computer wins

:param state: the state of the current board


:return: True if the human or computer wins

"""

return wins(state, HUMAN) or wins(state, COMP)

def empty_cells(state):

"""

Each empty cell will be added into cells' list

:param state: the state of the current board

:return: a list of empty cells

"""

cells = []

for x, row in enumerate(state):

for y, cell in enumerate(row):

if cell == 0:

cells.append([x, y])

return cells

def valid_move(x, y):

"""

A move is valid if the chosen cell is empty

:param x: X coordinate

:param y: Y coordinate

:return: True if the board[x][y] is empty

"""

if [x, y] in empty_cells(board):
return True

else:

return False

def set_move(x, y, player):

"""

Set the move on board, if the coordinates are valid

:param x: X coordinate

:param y: Y coordinate

:param player: the current player

"""

if valid_move(x, y):

board[x][y] = player

return True

else:

return False

def minimax(state, depth, player):

if player == COMP:

best = [-1, -1, -infinity]

else:

best = [-1, -1, +infinity]

if depth == 0 or game_over(state):

score = evaluate(state)

return [-1, -1, score]


for cell in empty_cells(state):

x, y = cell[0], cell[1]

state[x][y] = player

score = minimax(state, depth - 1, -player)

state[x][y] = 0

score[0], score[1] = x, y

if player == COMP:

if score[2] > best[2]:

best = score # max value

else:

if score[2] < best[2]:

best = score # min value

return best

def clean():

"""

Clears the console

"""

os_name = platform.system().lower()

if 'windows' in os_name:

system('cls')

else:

system('clear')
def render(state, c_choice, h_choice):

"""

Print the board on console

:param state: current state of the board

"""

print(state)

chars = {

-1: h_choice,

+1: c_choice,

0: ' '

str_line = '---------------'

print('\n' + str_line)

for row in state:

for cell in row:

symbol = chars[cell]

print(f'| {symbol} |', end='')

print('\n' + str_line)

def ai_turn(c_choice, h_choice):

"""

It calls the minimax function if the depth < 9,

else it choices a random coordinate.

:param c_choice: computer's choice X or O

:param h_choice: human's choice X or O

:return:
"""

depth = len(empty_cells(board))

if depth == 0 or game_over(board):

return

clean()

print(f'Computer turn [{c_choice}]')

render(board, c_choice, h_choice)

if depth == 9:

x = choice([0, 1, 2])

y = choice([0, 1, 2])

else:

move = minimax(board, depth, COMP)

x, y = move[0], move[1]

set_move(x, y, COMP)

time.sleep(1)

def human_turn(c_choice, h_choice):

"""

The Human plays choosing a valid move.

:param c_choice: computer's choice X or O

:param h_choice: human's choice X or O

:return:

"""

depth = len(empty_cells(board))

if depth == 0 or game_over(board):
return

# Dictionary of valid moves

move = -1

moves = {

1: [0, 0], 2: [0, 1], 3: [0, 2],

4: [1, 0], 5: [1, 1], 6: [1, 2],

7: [2, 0], 8: [2, 1], 9: [2, 2],

print(move)

clean()

print(f'Human turn [{h_choice}]')

# print(moves)

render(board, c_choice, h_choice)

while move < 1 or move > 9:

try:

move = int(input('Use numpad (1..9): '))

coord = moves[move]

can_move = set_move(coord[0], coord[1], HUMAN)

if not can_move:

print('Bad move')

move = -1

except (EOFError, KeyboardInterrupt):

print('Bye')

exit()
except (KeyError, ValueError):

print('Bad choice')

def main():

"""

Main function that calls all functions

"""

clean()

h_choice = '' # X or O

c_choice = '' # X or O

first = '' # if human is the first

# Human chooses X or O to play

while h_choice != 'O' and h_choice != 'X':

try:

print('')

h_choice = input('Choose X or O\nChosen: ').upper()

except (EOFError, KeyboardInterrupt):

print('Bye')

exit()

except (KeyError, ValueError):

print('Bad choice')

# Setting computer's choice

if h_choice == 'X':

c_choice = 'O'

else:

c_choice = 'X'
# Human may starts first

clean()

while first != 'Y' and first != 'N':

try:

first = input('First to start?[y/n]: ').upper()

except (EOFError, KeyboardInterrupt):

print('Bye')

exit()

except (KeyError, ValueError):

print('Bad choice')

# Main loop of this game

while len(empty_cells(board)) > 0 and not game_over(board):

if first == 'N':

ai_turn(c_choice, h_choice)

first = ''

human_turn(c_choice, h_choice)

ai_turn(c_choice, h_choice)

# Game over message

if wins(board, HUMAN):

clean()

print(f'Human turn [{h_choice}]')

render(board, c_choice, h_choice)

print('YOU WIN!')

elif wins(board, COMP):

clean()
print(f'Computer turn [{c_choice}]')

render(board, c_choice, h_choice)

print('YOU LOSE!')

else:

clean()

render(board, c_choice, h_choice)

print('DRAW!')

exit()

if _name_ == '_main_':

main()

# # game.py

# In[4]:

#Using wikipedia pseudocode without depth

def alphabeta(game_state, alpha=-2, beta=2, our_turn=True):

if game_state.is_gameover():

return game_state.score(), None

if our_turn:

score = -2 #worst non-possible score. A win, tie, or even a loss will change this

for move in game_state.get_possible_moves():

child = game_state.get_next_state(move, True)

temp_max, _ = alphabeta(child, alpha, beta, False)


print(temp_max)

if temp_max > score:

score = temp_max

best_move = move

alpha = max(alpha, score)

# print(alpha)

if beta <= alpha:

break

return score, best_move

else:

score = 2 #worst non-possible score. A win, tie, or even a loss will change this

for move in game_state.get_possible_moves():

child = game_state.get_next_state(move, False)

temp_min, _ = alphabeta(child, alpha, beta, True)

print(temp_min)

if temp_min < score:

score = temp_min

best_move = move

beta = min(beta, score)

# print(beta)

if beta <= alpha:

break

return score, best_move

# In[5]:
#!/usr/bin/env python3

import random

from time import sleep

import alphabeta as ab

import gamestate as gs

def get_p_move(game):

while True:

raw_move = input('Your move (1-9) > ')

if raw_move.isdigit():

p_move = int(raw_move) - 1

if p_move > -1 and p_move < 9:

if game.board[p_move] == '_':

break

return p_move

def run_game(game, player_goes_first):

if player_goes_first:

while True:

game.pretty_print()

p_move = get_p_move(game)

game = game.get_next_state(p_move, False)

if game.is_gameover(): break

score, ai_move = ab.alphabeta(game)

game = game.get_next_state(ai_move, True)

if game.is_gameover(): break

else:

while True:
score, ai_move = ab.alphabeta(game)

game = game.get_next_state(ai_move, True)

if game.is_gameover(): break

game.pretty_print()

p_move = get_p_move(game)

game = game.get_next_state(p_move, False)

if game.is_gameover(): break

game.pretty_print()

print('The computer ' + game.return_state(score))

def get_symbols():

human_char = input('Pick your symbol > ')

if len(human_char) > 1 or human_char == '' or human_char == ' ' or human_char == '_':

exit()

elif human_char == 'X' or human_char == 'x':

ai_char = 'O'

else:

ai_char = 'X'

return human_char, ai_char

if _name_ == '_main_':

try:

human_char, ai_char = get_symbols()

start_board = ['_'] * 9

player_goes_first = bool(random.randint(0,2))

input('You go first:{}\nenter to continue\n'.format(player_goes_first))

game = gs.GameState(start_board,char=ai_char, oppchar=human_char)

run_game(game, player_goes_first)

except KeyboardInterrupt:
print('\n')

exit()

# In[ ]

You might also like