0% found this document useful (0 votes)
10 views28 pages

AI Lab Experiments for IT Students

The document outlines various experiments conducted in an Artificial Intelligence Lab at Raj Kumar Goel Institute of Technology & Management, focusing on algorithms such as Breadth First Search, A* Search, and Hill Climbing. Each experiment includes a program implementation and aims to solve specific problems like the 8-Puzzle Problem, Water Jug Problem, and text classification using NLTK. The document serves as a practical guide for students in the Department of Information Technology during the 2025-2026 session.

Uploaded by

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

AI Lab Experiments for IT Students

The document outlines various experiments conducted in an Artificial Intelligence Lab at Raj Kumar Goel Institute of Technology & Management, focusing on algorithms such as Breadth First Search, A* Search, and Hill Climbing. Each experiment includes a program implementation and aims to solve specific problems like the 8-Puzzle Problem, Water Jug Problem, and text classification using NLTK. The document serves as a practical guide for students in the Department of Information Technology during the 2025-2026 session.

Uploaded by

xinik69035
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

RAJ KUMAR GOEL INSTITUTE OF TECHNOLOGY &

MANAGEMENT GHAZIABAD
5thKM Stone Delhi, Meerut Road, Near Raj Nagar Extension Road, Ghaziabad, UP-201003 Approved
by AICTE. N. Delhi &Affiliated to Dr. A.P.J. Abdul Kalam Technical University, Lucknow NBA
Accredited Program (B. Tech. ECE, IT) & B. Pharma

Artificial Intelligence Lab(BCS-751)


Submitted to: Mr. Kuldeep Kushwaha
Session: 2025-2026

Name Aditya Rauniyar

Roll No. 2203330130003

Section B

Department of Information Technology


INDEX

S. No. Experiment Name Date of Date of


Conduction Submission

1. Implement Breadth First Search (BFS) for a


given graph or maze.

2. Implement Breadth First Search (BFS) for a


given graph or maze.

3. Solve the 8-Puzzle Problem using A*


Search Algorithm.

4. Implement Hill Climbing Algorithm for


numerical optimization or pathfinding.

5. Solve Water Jug Problem using state-


space search (BFS or DFS).

6. Build a simple text classifier using NLTK


(e.g., classify messages as spam/ham).

7. Study of PROLOG.

8. Write simple fact for following.

9. Write a program to solve the Monkey


Banana problem.

10. Implement 4-Queens Problem in Prolog.

11. Implement Min-Max (Minimax)


Algorithm for decision making in turn-
based games.

12. Implement Tic-Tac-Toe game with a basic


AI opponent

2
EXPERIMENT NO. 1

Program Name: Implement Breadth First Search (BFS) for a given graph or maze.

Implementation:
# Function to find BFS of Graph from given source s def
bfs(adj):

# get number of vertices


V= len(adj)

# create an array to store the traversal


res = [] s = 0
# Create a queue for BFS
from collections import
deque q = deque()

# Initially mark all the vertices as not visited


visited = [False] * V

# Mark source node as visited and enqueue it


visited[s] = True
[Link](s)

# Iterate over the queue


while q:

# Dequeue a vertex from queue and store it


curr = [Link]()
[Link](curr)

# Get all adjacent vertices of the dequeued


# vertex curr If an adjacent has not been
# visited, mark it visited and enqueue it
for x in adj[curr]:
if not visited[x]:
visited[x] = True
[Link](x)

return res

if name == " main ":

# create the adjacency list # [ [2, 3, 1],


[0], [0, 4], [0], [2] ]

3
adj = [[1,2], [0,2,3], [0,4], [1,4],
[2,3]]
ans = bfs(adj)
for i in ans:
print(i, end=" ")

4
EXPERIMENT NO. 2

Program Name: Implement Breadth First Search (BFS) for a given graph or maze.

Implementation:
def dfsRec(adj, visited, s, res):
visited[s] = True
[Link](s)

# Recursively visit all adjacent vertices that are not visited yet
for i in range(len(adj)):
if adj[s][i] == 1 and not visited[i]:
dfsRec(adj, visited, i, res)

def DFS(adj):
visited = [False] * len(adj)
res = []
dfsRec(adj, visited, 0, res) # Start DFS from vertex 0
return res

def add_edge(adj, s, t):


adj[s][t] = 1
adj[t][s] = 1 # Since it's an undirected graph

# Driver code
V=5
adj = [[0] * V for _ in range(V)] # Adjacency matrix

# Define the edges of the graph edges =


[(1, 2), (1, 0), (2, 0), (2, 3), (2, 4)]

# Populate the adjacency matrix with edges


for s, t in edges:
add_edge(adj, s, t)

res = DFS(adj) # Perform DFS


print(" ".join(map(str, res)))

5
6
EXPERIMENT NO. 3

Program Name: Solve the 8-Puzzle Problem using A* Search Algorithm.

Implementation:
import heapq
from termcolor import colored

# Class to represent the state of the 8-puzzle class


PuzzleState:
def init (self, board, parent, move, depth, cost):
[Link] = board # The puzzle board configuration
[Link] = parent # Parent state
[Link] = move # Move to reach this state
[Link] = depth # Depth in the search tree
[Link] = cost # Cost (depth + heuristic)

def lt (self, other):


return [Link] < [Link]

# Function to display the board in a visually appealing format


def print_board(board):
print("+---+---+---+") for row in range(0, 9, 3):
row_visual = "|"
for tile in board[row:row + 3]:
if tile == 0: # Blank tile row_visual += f"
{colored(' ', 'cyan')} |"
else:
row_visual += f" {colored(str(tile), 'yellow')} |"
print(row_visual)
print("+---+---+---+")

# Goal state for the puzzle


goal_state = [1, 2, 3, 4, 5, 6, 7, 8, 0]

# Possible moves for the blank tile (up, down, left, right)
moves = {
'U': -3, # Move up
'D': 3, # Move down
'L': -1, # Move left
'R': 1 # Move right
}

# Function to calculate the heuristic (Manhattan distance)


def heuristic(board): distance = 0
for i in range (9):
if board[i] != 0:
x1, y1 = divmod(i, 3)

7
x2, y2 = divmod(board[i] - 1, 3)
distance += abs(x1 - x2) + abs(y1 - y2)
return distance

# Function to get the new state after a move


def move_tile(board, move, blank_pos):
new_board = board[:]
new_blank_pos = blank_pos + moves[move]
new_board[blank_pos], new_board[new_blank_pos] = new_board[new_blank_pos], new_board[blank_pos]
return new_board

# A* search algorithm
def
a_star(start_state):
open_list = []
closed_list = set()
[Link](open_list, PuzzleState(start_state, None, None, 0, heuristic(start_state)))

while open_list:
current_state = [Link](open_list)

if current_state.board == goal_state:

return current_state

closed_list.add(tuple(current_state.board

)) blank_pos =

current_state.[Link](0)

for move in moves: if move == 'U' and blank_pos < 3: #


Invalid move up continue
if move == 'D' and blank_pos > 5: # Invalid move down continue
if move == 'L' and blank_pos % 3 == 0: # Invalid move left continue
if move == 'R' and blank_pos % 3 == 2: # Invalid move right
continue new_board = move_tile(current_state.board, move,
blank_pos)

if tuple(new_board) in closed_list:
continue

new_state = PuzzleState(new_board, current_state, move, current_state.depth + 1, current_state.depth + 1 +


heuristic(new_board)) [Link](open_list, new_state) return None

# Function to print the solution path


def print_solution(solution):
path = [] current
= solution while
current:

8
[Link](current)
current = [Link]
[Link]()

for step in path:


print(f"Move: {[Link]}")
print_board([Link])

# Initial state of the puzzle initial_state


= [1, 2, 3, 4, 0, 5, 6, 7, 8]

# Solve the puzzle using A* algorithm solution


= a_star(initial_state)

# Print the solution if


solution:
print(colored("Solution found:", "green"))
print_solution(solution)
else:
print(colored("No solution exists.", "red"))

Output:
Solution found:
Move: None
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | | 5 |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
Move: R
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | |
+---+---+---+
| 6 | 7 | 8 |
+---+---+---+
Move: R
9
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
| 7 | | 8 |
+---+---+---+
Move: R
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
| 7 | 8 | |
+---+---+---+

10
EXPERIMENT NO. 4

Program Name: Implement Hill Climbing Algorithm for numerical optimization or pathfinding.

Implementation
: import random
import math

def hill_climbing(objective_function, bounds, step_size, max_iterations):


# Initialize a random solution within the bounds
solution = [[Link](bounds[i][0], bounds[i][1]) for i in range(len(bounds))] best_solution
= solution[:]
best_fitness = objective_function(best_solution)

for _ in range(max_iterations):
# Generate a new solution by applying a small change to the current solution new_solution
= [x for x in solution]
dimension_to_change = [Link](0, len(bounds) - 1)
new_solution[dimension_to_change]+=[Link](-step_size,step_size)
new_solution[dimension_to_change] = max(bounds[dimension_to_change][0],
min(bounds[dimension_to_change][1], new_solution[dimension_to_change]))

# Evaluate the new solution


new_fitness = objective_function(new_solution)

# If the new solution is better, accept it


if new_fitness < best_fitness:
solution = new_solution
best_solution=new_solution[:]
best_fitness = new_fitness
else:
# Accept the new solution with some probability to avoid local optima if
[Link]() < [Link]((best_fitness - new_fitness) / (abs(best_fitness) + 1e-9)):
solution = new_solution

return best_solution, best_fitness

# Example objective function: minimize x^2 + y^2


def objective_function(solution): return
solution[0]**2 + solution[1]**2

bounds = [(-5, 5), (-5, 5)] # bounds for x and y


step_size = 0.1 max_iterations = 1000
best_solution, best_fitness = hill_climbing(objective_function, bounds, step_size, max_iterations)
print(f"Best solution: x = {best_solution[0]}, y = {best_solution[1]}")
print(f"Best fitness: {best_fitness}")

11
Output:
Best solution: x = -3.633010903595869, y = 0.5620945535042986
Best fitness: 13.514718512725668

12
EXPERIMENT NO. 5

Program Name: Solve Water Jug Problem using state-space search (BFS or DFS).

Implementation: # Function to perform DFS to solve the water jug problem def
water_jug_dfs(capacity1, capacity2, target):
visited = set() # To track visited states path
= [] # To store the solution path

def dfs(jug1, jug2):


# If we have already visited this state, return False (avoid cycles)
if (jug1, jug2) in visited: return False

# Mark the state as visited


[Link]((jug1, jug2))

# Append the current state to the path


[Link]((jug1, jug2))

# If the target is achieved in either jug, return True


if jug1 == target or jug2 == target: return True

# Explore all possible transitions (DFS recursive calls)


# Fill 3-liter jug if
dfs(3, jug2):
return True #
Fill 5-liter jug if
dfs(jug1, 5):
return True #
Empty 3-liter jug if
dfs(0, jug2):
return True #
Empty 5-liter jug if
dfs(jug1, 0):
return True
# Pour water from 3-liter jug into 5-liter jug if
dfs(max(0, jug1 - (5 - jug2)), min(5, jug1 + jug2)):
return True
# Pour water from 5-liter jug into 3-liter jug if
dfs(min(3, jug1 + jug2), max(0, jug2 - (3 - jug1))):
return True

# If none of the transitions lead to the goal, backtrack [Link]()


return False

13
# Start DFS from the initial state (0, 0) dfs(0,
0)

# If we found a solution, return the path


return path

# Example Usage
capacity1 = 3 # Capacity of the 3-liter jug capacity2 =
5 # Capacity of the 5-liter jug target = 4 # Target
amount to measure solution =
water_jug_dfs(capacity1, capacity2, target)

if solution:
print("Solution steps:") for
step in solution:
print(step)
else:
print("No solution found.")

import [Link] as plt import


networkx as nx

# Function to create and visualize the state space transitions for DFS
def visualize_dfs_solution(solution): G = [Link]()

# Add the nodes and edges based on the DFS solution path for
i in range(len(solution) - 1):
G.add_edge(solution[i], solution[i + 1])

pos = nx.spring_layout(G) # Position the nodes for visualization [Link](figsize=(8,

6))

# Draw the graph with nodes and labels


[Link](G, pos, with_labels=True, node_color='lightgreen', node_size=1500, font_size=12,
font_weight='bold') nx.draw_networkx_edges(G, pos, edgelist=list([Link]()),
edge_color='blue', width=2)

[Link]("Water Jug Problem - DFS Solution Path") [Link]()


# Visualize the DFS solution if
solution:
visualize_dfs_solution(solutio
n)

14
Output:

15
EXPERIMENT NO. 6
Program Name: Build a simple text classifier using NLTK (e.g., classify messages as spam/ham).

Implementation:
import nltk
from [Link] import names
from [Link] import NaiveBayesClassifier
from [Link] import accuracy import
random

# Download NLTK resources (only first time) [Link]('punkt')

# Sample dataset (spam/ham)


data = [
("Win money now!!!", "spam"),
("Congratulations, you won a free lottery ticket", "spam"),
("Call this number to claim your prize", "spam"),
("Hi, are we still meeting tomorrow?", "ham"), ("Don't
forget to bring the documents", "ham"),
("See you at the office", "ham"),
("Reminder: your bill is due tomorrow", "ham"),
("Exclusive deal just for you!!!", "spam")
]

# Feature extraction function def


extract_features(text):
words = nltk.word_tokenize([Link]()) return
{word: True for word in words}

# Apply feature extraction


featuresets = [(extract_features(msg), label) for (msg, label) in data]

#Train/testsplit
[Link](featuresets) train_size
= int(len(featuresets) * 0.75)
train_set, test_set = featuresets[:train_size], featuresets[train_size:]

# Train Naive Bayes classifier


classifier = [Link](train_set)

# Evaluate
print("Accuracy:", accuracy(classifier, test_set))
print("\nMostinformativefeatures:")
classifier.show_most_informative_features(5)
# Try on new messages tests
=[

16
"Congratulations, you have won a car!!!",
"Are you coming to the meeting?",
"Reminder: Pay your electricity bill"
]

for msg in tests:


label = [Link](extract_features(msg)) print(f"Message:
{msg} -> {label}")

Output:
Accuracy: 0.75
Most informative features:
!! = True spam : ham = 2.3 : 1.0 free = True
spam : ham = 2.1 : 1.0 congratulations = True
spam : ham = 2.0 : 1.0 bill = True ham : spam
= 1.9 : 1.0

Message: Congratulations, you have won a car!!! -> spam


Message: Are you coming to the meeting? -> ham
Message: Reminder: Pay your electricity bill -> ham

17
EXPERIMENT NO. 7

Program Name: Study of PROLOG

Implementation:

Facts, Rules and Queries


Symbols
Prolog expressions are comprised of the following truth-functional symbols, which have the same
interpretation as in the predicate calculus.
English Predicate Calculus PROLOG
and ^ ,
or v ;
if --> :-
not ~ not
Variables and Names
Variables begin with an uppercase letter. Predicate names, function names, and the names for objects
must begin with a lowercase letter. Rules for forming names are the same as for the predicate calculus.
mother_of
male female
greater_than
socrates Facts
A fact is a predicate expression that makes a declarative statement about the problem domain. Whenever
a variable occurs in a Prolog expression, it is assumed to be universally quantified. Note that all Prolog
sentences must end with a period.
likes(john, susie). /* John likes Susie */ likes(X, susie).
/* Everyone likes Susie */
likes(john, Y). /* John likes everybody */
likes(john, Y), likes(Y, john). /* John likes everybody and everybody likes John */
likes(john, susie); likes(john,mary). /* John likes Susie or John likes Mary */
not(likes(john,pizza)). /* John does not like pizza */ likes(john,susie) :-
likes(john,mary)./* John likes Susie if John likes Mary.
Rules
A rule is a predicate expression that uses logical implication (:-) to describe a relationship among facts.
Thus a Prolog rule takes the form
left_hand_side :- right_hand_side .
This sentence is interpreted as: left_hand_side if right_hand_side. The left_hand_side is restricted to
a single, positive, literal, which means it must consist of a positive atomic expression. It cannot be
negated and it cannot contain logical connectives.
This notation is known as a Horn clause. In Horn clause logic, the left hand side of the clause is the
conclusion, and must be a single positive literal. The right hand side contains the premises. The Horn
clause calculus is equivalent to the first-order predicate calculus.

Examples of valid rules: friends(X,Y) :- likes(X,Y),likes(Y,X). /* X and Y are friends if


they like each other */
18
hates(X,Y) :- not(likes(X,Y)). /* X hates Y if X does not like Y. */
enemies(X,Y) :- not(likes(X,Y)),not(likes(Y,X)). /* X and Y are enemies if they don't like each other */
parent_of(X,Y) :- father_of(X,Y). /* Rule #1 */ parent_of(X,Y) :- mother_of(X,Y). /* Rule
#2 */

Examples of invalid rules:


left_of(X,Y) :- right_of(Y,X) /* Missing a period */
likes(X,Y),likes(Y,X) :- friends(X,Y). /* LHS is not a single literal */ not(likes(X,Y))
:- hates(X,Y). /* LHS cannot be negated */

Queries
The Prolog interpreter responds to queries about the facts and rules represented in its database. The
database is assumed to represent what is true about a particular problem domain. In making a query
you are asking Prolog whether it can prove that your query is true. If so, it answers "yes" and displays
any variable bindings that it made in coming up with the answer. If it fails to prove the query true, it
answers "No".

Whenever you run the Prolog interpreter, it will prompt you with ?-. For example, suppose our
database consists of the following facts about a fictitious family. father_of(joe,paul).
father_of(joe,mary). mother_of(jane,paul). mother_of(jane,mary).
male(paul).
male(joe).
female(mary).
female(jane).

We get the following results when we make queries about this database.
?- ['[Link]'].

?- listing.

mother_of(jane, paul).
mother_of(jane, mary).

male(paul).
male(joe).

female(mary).
female(jane).

father_of(joe, paul).
father_of(joe, mary).

(10 ms) yes


| ?- father_of(joe,paul).

true ?

yes
| ?- father_of(paul,mary).

19
no
| ?- father_of(X,mary).
X = joe

yes

EXAMPLE of Facts:& Rules:


father_of(joe,paul).
father_of(joe,mary).
father_of(joe,hope).
mother_of(jane,paul).
mother_of(jane,mary).
mother_of(jane,hope).

male(paul).
male(joe).
male(ralph).
male(X) :- father_of(X,Y).

female(mary).
female(jane).
female(hope).

son_of(X,Y) :- father_of(Y,X),male(X). son_of(X,Y)


:- mother_of(Y,X),male(X).

daughter_of(X,Y) :- father_of(Y,X),female(X). daughter_of(X,Y)


:- mother_of(Y,X),female(X).

sibling_of(X,Y) :- !,father_of(Z,X),father_of(Z,Y),X\=Y. sibling_of(X,Y)


:- !,mother_of(Z,X),mother_of(Z,Y),X\=Y.
Sample: Screen Shot:
likes(ryan, britney).
likes(britney, ryan).
likes(don, josh).
dating(X, Y):- likes(X,Y), likes(Y,X).
friendship(X,Y):- likes(X,Y); likes(Y,X).

Query:
?- dating(ryan, britney). True ?-
dating(don, josh). False

20
EXPERIMENT NO.8
Program Name: Write simple fact for following. a.
Ram likes mango.
b. Seema is a girl.
c. Bill likes Cindy.
d. Rose is red.
e. John owns gold.

Implementation:
Clauses likes(ram
,mango).
girl(seema).
red(rose).
likes(bill ,cindy).
owns(john ,gold).

Output: Goal
queries ?-
likes(ram,What).
What= mango
?-likes(Who,cindy).
Who= cindy
?-red(What).
What= rose
?-owns(Who,What).
Who= john
What= gold.

OR

FACTS/RULES/RELATION

Two person are brothers, if,


They both are male.
They have the same parent.
Now consider we have the below phrases − parent(sudip,
piyus). parent(sudip, raj). male(piyus). male(raj).
brother(X,Y) :- parent(Z,X), parent(Z,Y),male(X), male(Y)

QUERY
?brother(X,Y).
(Piyush,raj).
?parent(X,Y).
?Male(X).

21
EXPERIMENT NO. 9
Program Name: Write a program to solve the Monkey Banana problem.

Theory:Imagine a room containing a monkey, chair and some bananas. That has been hanged from the
centre of ceiling. If the monkey is clever enough he can reach the bananas by placing the chair directly
below the bananas and climb on the chair .The problem is to prove the monkey can reach the bananas. The
monkey wants it, but cannot jump high enough from the floor. At the window of the room there is a box
that the monkey can use. The monkey can perform the following actions:- 1) Walk on the floor.
2) Climb the box.
3) Push the box around (if it is beside the box).
4) Grasp the banana if it is standing on the box directly under the banana.

Parse Tree

Implementation:
in_room(bananas). in_room(chair).
in_room(monkey). clever(monkey).
can_climb(monkey, chair).
tall(chair). can_move(monkey,
chair, bananas).
can_reach(X, Y):- clever(X),close(X, Y).
get_on(X,Y):- can_climb(X,Y).
under(Y,Z):- in_room(X),in_room(Y),in_room(Z),can_climb(X,Y,Z).
close(X,Z):-get_on(X,Y), under(Y,Z); tall(Y).
Output:
Queries:
?- can_reach(A, B).
A = monkey.
B = banana.
?- can_reach(monkey, banana).
Yes.

22
EXPERIMENT NO. 10
Program Name: Implement 4-Queens Problem in Prolog

Implementation:

queens(N, Queens) :- length(Queens,


N),
board(Queens, Board, 0, N, _, _),
queens(Board, 0, Queens).

board([], [], N, N, _, _).


board([_|Queens], [Col-Vars|Board], Col0, N, [_|VR], VC) :-
Col is Col0+1, functor(Vars, f, N),
constraints(N, Vars, VR, VC), board(Queens,
Board, Col, N, VR, [_|VC]).

constraints(0, _, _, _) :- !.
constraints(N, Row, [R|Rs], [C|Cs]) :-
arg(N, Row, R-C), M is N-1,
constraints(M, Row, Rs, Cs).

queens([], _, []).
queens([C|Cs], Row0, [Col|Solution]) :-
Row is Row0+1, select(Col-Vars,
[C|Cs], Board), arg(Row, Vars, Row-
Row), queens(Board, Row, Solution).

Output:

?-[‘[Link]’].
True

?-queens(4,Queens).
Queens=[2,4,1,3]
Queens=[3,1,4,2]

?-queens(8,Queens).
Queens=[4,7,3,8,2,5,1,6]

23
EXPERIMENT NO. 11
Program Name: Implement Min-Max (Minimax) Algorithm for decision making in turn-based
games.

Implementation:
def minimax(board, depth, is_max):
score = evaluate(board)
if score != 0 or depth == 0: return score

moves = [(i,j) for i in range(3) for j in range(3) if board[i][j] == ' '] if


not moves: return 0

if is_max:
best = -1000 for i,
j in moves:
board[i][j] = 'X'
best = max(best, minimax(board, depth-1, False)) board[i][j]
=''
return best
else:
best = 1000 for i,
j in moves:
board[i][j] = 'O'
best = min(best, minimax(board, depth-1, True)) board[i][j]
=''
return best

def evaluate(board): #
Check winner
for i in range(3):
if board[i][0] == board[i][1] == board[i][2] == 'X': return 10
if board[i][0] == board[i][1] == board[i][2] == 'O': return -10
if board[0][i] == board[1][i] == board[2][i] == 'X': return 10
if board[0][i] == board[1][i] == board[2][i] == 'O': return -10
if board[0][0] == board[1][1] == board[2][2] == 'X': return 10
if board[0][0] == board[1][1] == board[2][2] == 'O': return -10
if board[0][2] == board[1][1] == board[2][0] == 'X': return 10
if board[0][2] == board[1][1] == board[2][0] == 'O': return -10
return 0

def find_best_move(board):
best_val, best_move = -1000, None
for i in range(3): for j in range(3):
if board[i][j] == ' ': board[i][j]
= 'X'
move_val = minimax(board, 9, False)
board[i][j] = ' ' if move_val >
best_val:
24
best_val, best_move = move_val, (i, j)
return best_move, best_val

# Test board = [[' ']*3 for _ in


range(3)] print("Empty board:")
for row in board: print(row)

move, score = find_best_move(board)


print(f"\nBest move: {move}")
print(f"Score: {score}")

board[move[0]][move[1]] = 'X' print("\nAfter


move:")
for row in board: print(row)

Output:
Empty board:
[' ', ' ', ' ']
[' ', ' ', ' ']
[' ', ' ', ' ']

Best move: (0, 0)


Score: 0

After move:
['X', ' ', ' ']
[' ', ' ', ' ']
[' ', ' ', ' ']

25
EXPERIMENT NO. 12
Program Name: Implement Tic-Tac-Toe game with a basic AI opponent.

Implementation:
def print_board(board):
for i, row in enumerate(board):
print(f"{' | '.join(row)}") if i
< 2: print(" --------- ")

def check_winner(board): # Check


rows, columns, diagonals for i in
range(3):
if board[i][0] == board[i][1] == board[i][2] != ' ': return board[i][0]
if board[0][i] == board[1][i] == board[2][i] != ' ': return board[0][i]
if board[0][0] == board[1][1] == board[2][2] != ' ': return board[0][0]
if board[0][2] == board[1][1] == board[2][0] != ' ': return board[0][2] return
None

def minimax(board, is_ai_turn): winner =


check_winner(board) if winner == 'O':
return 1 # AI wins if winner == 'X': return
-1 # Human wins
if all(board[i][j] != ' ' for i in range(3) for j in range(3)): return 0 # Draw

if is_ai_turn: best
= -2 for i in
range(3):
for j in range(3):
if board[i][j] == ' ': board[i][j]
= 'O'
best = max(best, minimax(board, False))
board[i][j] = ' '
return best
else:
best = 2 for i in
range(3):
for j in range(3):
if board[i][j] == ' ': board[i][j]
= 'X'
best = min(best, minimax(board, True))
board[i][j] = ' '
return best

def ai_move(board): best_score,


best_move = -2, None for i in
range(3):
for j in range(3):

26
if board[i][j] == ' ':
board[i][j] = 'O' score =
minimax(board, False)
board[i][j] = ' ' if score >
best_score:
best_score, best_move = score, (i, j)
return best_move

def play_game():
board = [[' ']*3 for _ in range(3)]
print("Tic-Tac-Toe: You=X, AI=O")
print("Enter row,col (0-2): ")

while True:
print_board(board)

# Human move
try:
r, c = map(int, input("Your move: ").split(',')) if
board[r][c] != ' ':
print("Occupied!"); continue
board[r][c] = 'X'
except:
print("Invalid!"); continue

if check_winner(board) or all(board[i][j] != ' ' for i in range(3) for j in range(3)):


break

# AI move move =
ai_move(board) if move:
board[move[0]][move[1]] = 'O'
print(f"AI plays: {move}")

if check_winner(board) or all(board[i][j] != ' ' for i in range(3) for j in range(3)):


break

print_board(board) winner =
check_winner(board) if winner ==
'X': print("You win!") elif winner
== 'O': print("AI wins!") else:
print("Draw!")

# Run game
play_game()

Output:
Tic-Tac-Toe: You=X, AI=O Enter
row,col (0-2):
| |

27
| |

| |
Your move: 1,1
| |

|X|

| |
AI plays: (0, 0)
O||

|X|

| |
Your move: 0,1
O|X|

|X|

| |
AI plays: (2, 1)
O|X|

|X|

|O|
AI wins!

28

You might also like