1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Bài tập lớn trí tuệ nhân tạo Đề tài mã Đi tuần

32 0 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Bài tập lớn Trí tuệ nhân tạo: Mã đi tuần
Tác giả Nguyễn Vũ Xuân Kiên, Trần Việt Dương, Nguyễn Huy Toàn
Người hướng dẫn Đào Việt Anh
Trường học Trường Đại học Hải Phòng, Khoa Công nghệ thông tin
Chuyên ngành Trí tuệ nhân tạo
Thể loại Bài tập lớn
Năm xuất bản 2024
Thành phố Hải Phòng
Định dạng
Số trang 32
Dung lượng 471,04 KB

Nội dung

Giới thiệuTrong cờ vua có các quân cờ chính và cách đi như sau : · Xe di chuyển theo các đường thẳng dọc theo cột hay hàng tới ô còn trống mà không có quân nào cản trên đường đi hay tới

Trang 1

TRƯỜNG ĐẠI HỌC HẢI PHÒNG

Khoa Công nghệ thông tin



BÀI TẬP LỚN TRÍ TUỆ NHÂN TẠO

Đề tài: Mã đi tuần

SVTH: Nguyễn Vũ Xuân Kiên

Trần Việt Dương Nguyễn Huy Toàn

GVHD: Đào Việt Anh

 Năm 2024 

Trang 2

MỤC LỤC

Giới thiệu

I Cài đặt môi trường code Game với C++, IDE visual studio (2012 - 2019)……

II Tổng quan trò chơi………

1 Đối với Quân Xe………

2 Đối với quân tượng………

3 Đối với quân mã………

4 Đối với vua………

5 Đối với Tốt………

6 Với Hậu………

7 Hàm tìm với tham số n :………

III Các hàm Đánh cờ và Undo………

IV: cây trò chơi, chiến lược Minimax, cắt tỉa Alpha-Beta………

1 Lý Thuyết………

2 Ứng dụng trong cờ vua:………

Trang 3

Giới thiệu

Trong cờ vua có các quân cờ chính và cách đi như sau :

· Xe di chuyển theo các đường thẳng dọc theo cột hay hàng tới ô còn trống mà không có quân nào cản trên đường đi hay tới ô bị quân đối phương chiếm giữ (ăn quân) nhưng không thể vượt qua quân đang đứng ở ô đó · Tượng di chuyển theo đường chéo tới ô có cùng màu với nguyên lý tương tự như Xe tới ô còn trống hay ô

bị quân đối phương chiếm giữ (ăn quân)

· Hậu có nước đi là tổ hợp đơn giản của chuyển động của Xe và Tượng Trong một nước đi nó có thể di chuyển theo đường chéo hoặc đường thẳng dọc theo cột hay hàng, với nguyên lý đi và ăn quân giống như Tượng và Xe

· Mã có thể di chuyển tới ô còn trống hay ô bị quân đối phương chiếm giữ (ăn quân) theo dạng hình chữ L (hình chữ nhật 3×2 hay 2×3)

· Tốt có thể di chuyển thẳng về phía trước chỉ một ô một lần tới ô còn trống (đi mà không ăn quân), nhưng khi di chuyển quân để ăn quân đối phương thì đi chéo

Nó có thể di chuyển 1 hoặc 2 ô nếu nó đi từ vị trí xuất phát ban đầu tới ô chưa bị chiếm giữ, nhưng không thể nhảy qua một quân khác để tới ô đó

Tốt còn một đặc điểm nữa là khi nó di chuyển đến hàng cuối cùng thì người chơi cóquyền phong cấp cho nó thành bất kỳ quân nặng hay nhẹ nào (Hậu, Xe, Tượng, Mã).(trong game mặc định là Hậu) · Vua là quân quan trọng nhất, nếu mất Vua thì người chơi thua cuộc Mỗi lần đi nó có thể ăn quân hoặc di chuyển sang các ô bao quanh ô mà nó hiện tại đang chiếm giữ, nhưng không thể tới ô mà quân của mình đang chiếm giữ

I.Cài đặt môi trường code Game với C++, IDE visual studio (2012 - 2019)

Sơ bộ: ngôn ngữ: visual C++ và thư viện đồ họa SFML Tham khảo:

Trang 4

II Tổng quan trò chơi

 Mặc định bên người chơi là quân trắng đi trước, thao tác là click chuột vào quân minh, hiện ra các nước đk đi rồi click vào các nước đó=> quân cờ sẽ dichuyển đến vị trí mới

 Đã có: các chức năng di chuyển, ăn các quân, phong hậu cho tốt

 Hạn chế: chưa có chức năng nhập thành,chiếu bí, hàm đánh giá đơn giản, thiếu chiến thuật, mức độ sơ cấp

 Lớp quản lý toàn bộ trò chơi:

classGameManager

{

public:

QuanCo f[33]; //mang lưu các quân cờ

Vector2f positiveMove[32];//vi tri cac nuoc co the di chuyen

int positiveCount;// so nuoc co the di chuyen

stack<Vector2f> posS;//lưu vị trí các nước đã đi

stack<int> nS;//lưu index của các quân đã đi ,tương ứng với vị trí bên trên

void move(int n,Vector2f oldPos,Vector2f newPos);//đánh cờ

void Undo();//quay lại nước trước

void Create();// khởi tạo mảng quân cờ và các giá trị cần thiết

void Play(); // mọi thao tác trong game xử lý tại đây

void PositiveXe(int n,int x,int y,int grid[9][9]);//tim cac nuoc co the di Xe

void PositiveTuong(int n,int x,int y,int grid[9][9]);

void PositiveMa(int n,int x,int y,int grid[9][9]);

void PositiveVua(int n,int x,int y,int grid[9][9]);

void PositiveTot(int n,int x,int y,int grid[9][9]);

void IncreasePositive(int i,int j);//tang thêm 1 nước có thể đi ở vị tri i,j

void PositiveMoving(int n);//tim cac nuoc co the di ung voi index n

//AI

intCostMove();//tính điểm nước đi( hàm đánh giá)

//int Minimax(int depth,bool luot);// Chien luoc Minimax

intAlpha_Beta(int depth,bool luot,int alpha,int beta);//cat tia alpha beta

Vector2f getNextMove(bool luot);// tra ve nuoc di tot nhat theo chien luoc

Trang 5

 sử dụng mảng Quan cờ: f[32]: lưu trữ 32 quân trong bàn cờ mỗi quân có 1 hình ảnh Sprite(kích thước size*size) ,1 index: trị số sử dụng, 1 cost: giá trị

sử dụng trong hàm đánh giá

Trang 6

 bảng giá trị index tương ứng trên bàn cờ lúc xuất phat: mặc định: f[0],f[7] là

xe đen ứng với index=-1 ,f[1],f[6] là mã đen(index=-2), tương tự như vậy với các quân còn lại

f[k].s.setTextureRect( IntRect(size*x,size*y,size,size) );

f[k].s.setPosition(size*j+offset.x,size*i+offset.y);

Xây dựng các hàm tính các nước được phép đi

 Vì hàm này tìm các ô có thể đi nên để kiểm tra dễ dàng ta sử dụng 1 mảng ô

cờ grid[8][8] lưu trữ index của bàn cờ (ô nào ko có quân grid=0,, có grid= index của quân cờ)

Trang 7

 Ví dụ: nếu grid[x][y] => vị trí tương ứng quân cờ:

Vector2f(xsize+offsetX,ysize+ offsetY)

 Hàm tăng số vị trí các nước có thể đi:

void GameManager::IncreasePositive(int i,int j)

{

positiveMove[positiveCount]=Vector2f(i*size,j*size)+offset;

positiveCount++;

}

1 Đối với Quân Xe

 xuất phát từ vị trí ô cờ ứng với quân xe đang chọn, duyệt theo 4 hướng ngang,dọc :nếu ko gặp vật cản(index=0) đánh dấu ô có thể đi, nếu gặp vật cản(index !=0) thì dừng lại, nếu vật cản đó là quân đối phương, đánh dấu ô

đó có thể đi ð Các nước đi phải nằm trong phạm vi bàn cờ

void GameManager::PositiveXe(int x,int y,int grid[9][9])//tu vi tri (x,y) xet ra

Trang 8

2 Đối với quân tượng

 Tương tự xe nhưng theo 4 hướng chéo:

void GameManager::PositiveTuong(int x,int y,int grid[9][9])//tu vi tri (x,y) xet ra

Trang 9

3 Đối với quân mã

 Ứng với vị trí x,y nó đang đứng có 8 vị trí nó có thể di chuyển nếu các nước này nằm trong bàn cờ và không có quân nào hoặc quân đối thủ:

void GameManager::PositiveMa(int x,int y,int grid[9][9])//xet 8 vi tri co the di

Trang 10

if((grid[x-1][y-2]==0||grid[x][y]*grid[x-1][y-2]<0) && x-1>=0 && y-2>=0)

 Lúc xuất phát có thể đi thẳng 2 ô với điều kiện ô đầu ko có quân nào

 ngoài ra đi thẳng 1 ô, ăn chéo 1 ô

void GameManager::PositiveTot(int x,int y,int grid[9][9])

{

int k=grid[x][y]/abs(grid[x][y]);// 1 hoac -1

if((y==1 || y==6) &&grid[x][y-k]==0 && grid[x][y-2*k]==0 && y-2*k>=0

&& y-2*k<8) IncreasePositive(x,y-2*k);

if(grid[x][y-k]==0 && y-k>=0 && y-k<8) IncreasePositive(x,y-k);

Trang 11

if(grid[x+1][y-k]*grid[x][y]<0 && y-k>=0 && y-k<8 && x+1<8)

Vector2f pos=f[n].s.getPosition()-offset;

int x=pos.x/size;

int y=pos.y/size;

int grid[9][9];//mang luoi(8x8) luu lai cac vi tri ban co:

vtri=Vector2i( f[j].s.getPosition()-offset);

grid[vtri.x/size][vtri.y/size]=f[j].index;// neu co = index cua quan co

}

if(abs(f[n].index)==1) PositiveXe(x,y,grid);//xe

elseif(abs(f[n].index)==2) PositiveMa(x,y,grid);//ma

elseif(abs(f[n].index)==3) PositiveTuong(x,y,grid);//tuong

elseif(abs(f[n].index)==4)//hau: hop lai cac nuoc cua ca xe va tuong

{

PositiveXe(x,y,grid);

PositiveTuong(x,y,grid);

}

elseif(abs(f[n].index)==5) PositiveVua(x,y,grid);//vua

else PositiveTot(x,y,grid); //tot

Trang 12

III Các hàm Đánh cờ và Undo

Để dễ dàng em chia làm 3 bước: đi có ăn( quân bị ăn biến mất) và đi có phong hậu

 đi ko ăn: khi ta ăn phải di chuyển con bị ăn vào sau mh vậy lúc undo phải làm sao

{

posS.push(oldPos);

posS.push(newPos);

nS.push(n);

for(int i=0;i<32;i++){//đoạn này ko thể undo

if (f[i].s.getPosition()==newPos)

{

posS.push(oldPos);

posS.push(newPos);

nS.push(n);

int y=int((newPos-offset).y/size);//kiem tra xem co phong hau hay khong

for(int i=0;i<32;i++){

if (f[i].s.getPosition()==newPos) {

Trang 13

f[i].s.setPosition( 100,-100);//di chuyen con bị ăn ra khỏi mh

posS.push(newPos);

posS.push(Vector2f( 100,-100));

posS.push(oldPos);

posS.push(newPos);

nS.push(n);

int y=int((newPos-offset).y/size);//kiem tra xem co phong hau hay khong

//phong hau cho tot

Trang 14

}

//di chuyen em an vao vi tri moi

for(int i=0;i<32;i++){

if (f[i].s.getPosition()==newPos) {

f[i].s.setPosition( 100,-100);//

posS.push(newPos);

posS.push(Vector2f( 100,-100));

Trang 15

o Chiến lược Minimax:

Lượt quân trắng : tìm trong số các nước đi có thể của nó nước đi nào là tốt nhất,, tương tự với quân đen ð Làm sao để tính đk

Trang 16

Ta đi đến mức thấp nhất của cây + hàm đánh giá tính điểm sau đó xác định điểm của các nhánh trên: với quân trắng(max trong các nước đi),đen thì ngược lại

ð Đương nhiên dùng duyệt theo chiều sâu để tìm Thực tế để làm như vậy mà đi đến nước cuôi cùng thì máy tính không thể xử lý nôi => giải pháp: Giới hạn độ sâu

Từ a-> b-> e(hết =-3) chuyển sang f => k… đúng theo DFS

Tầng min chọn đỉnh bé nhất trong số các đỉnh con, max ngược lại

 Cắt tỉa Alpha Beta Ở chiến thuật minimax dù đã giảm độ cao của cây nhưng không gian vẫn quá lớn, ở phương pháp này ta cắt đi không xét đến những nhánh không cần thiết để giảm không gian TT

Trang 17

Alpha = giá trị tại các nút max, Beta ………… min

Ví dụ:đi từ A-> E: (alpha=3) lên lại B(gán tạm Beta=3(thực chất<=3) ) xét đến F(cónhánh con =5) (alpha=5(thực chất >=5)) Lúc này (Beta<=alpha) khỏi phait xet tiếp nut F làm gì Tương tự như vậy tại A ta cắt bơt đk tạiC và D

Trang 18

 Cắt tỉa Alpha Beta: trả về giá trị điểm cho trạng thái gốc muốn xét

int GameManager::Alpha_Beta(int depth,bool luot,int alpha,int beta)

int bestMove=-10000;//gia cua bestMove ban dau

for(int j=16;j<32;j++)//cac quan cua nguoi choi

alpha=max(alpha,bestMove);

if(beta<=alpha) return bestMove;

int bestMove=10000;//gia cua bestMove ban dau

for(int j=0;j<16;j++)//quan cua may

{

if(f[j].s.getPosition()==Vector2f( 100,-100)) continue;

Trang 19

move(j,f[j].s.getPosition(),positiveMovetemp[i]);

bestMove=min(bestMove,Alpha_Beta(depth-1,!luot,alpha,beta)); //undo

Undo();

beta=min(beta,bestMove);

if(beta<=alpha) return bestMove;

Vector2f oldPos,newPos,oldPostemp,newPostemp;// ta can tim vi tri co

minimax nho nhat de ung voi may( quan den)

int minimaxtemp=10000,minimax=10000;

int count1,n;

Vector2f positiveMovetemp[32];

Trang 20

for(int i=0;i<16;i++)

int alpha=-9999,beta=9999;

int temp=Alpha_Beta(3,!luot,alpha,beta);

Trang 21

//lay cac thong tin nuoc di

posS.push(oldPos);//luu tam o trong stack ty ra ngoai xoa di

nS.push(n);

return newPos;

}

 Trong hàm main phần xử lý computerMove:

else //computer moving

{

newPos= getNextMove(LuotChoi);

int c=nS.top(); nS.pop();//lay dk thong tin roi xoa di

oldPos=posS.top(); posS.pop();//vi ham move tu nhet trong stack roi

Trang 22

QuanCo f[ 33 ]; //mang luu cac quan co

Vector2f positiveMove[ 32 ];//vi tri cac nuoc co the di chuyen

int positiveCount;// so nuoc co the di chuyen

stack < Vector2f > posS;//luu tru vi tri cac nuoc di

stack <int> nS;//luu tru index cua quan di

void move ( int n,Vector2f oldPos,Vector2f newPos);//ham danh co

void Undo ();//ham quay lai

void Create ();

void Play ();// choi: moi thao tac o day

void PositiveXe ( int n, int x, int y, int grid[ 9 ][ 9 ]);//tim cac nuoc co the di cua Quan Xe

void PositiveTuong ( int n, int x, int y, int grid[ 9 ][ 9 ]);

Trang 23

void PositiveMa ( int n, int x, int y, int grid[ 9 ][ 9 ]);

void PositiveVua ( int n, int x, int y, int grid[ 9 ][ 9 ]);

void PositiveTot ( int n, int x, int y, int grid[ 9 ][ 9 ]);

void IncreasePositive ( int i, int j);//tang so nuoc co the di

void PositiveMoving ( int n);//tim cac nuoc co the di ung voi index n

//AI

int CostMove ();//gia tri diem cua toan bo ban co ung voi gia tri moi quan

//int Minimax(int depth,bool luot);// Chien luoc Minimax

int Alpha_Beta ( int depth, bool luot, int alpha, int beta);//cat tia alpha beta

Vector2f getNextMove ( bool luot);// tra ve nuoc di tot nhat theo chien luoc phia tren

int bestMove =- 10000 ;//gia cua bestMove ban dau

for ( int j = 16 ;j < 32 ;j ++ )//cac quan cua nguoi choi

for ( int i = 0 ; i < coun; i ++ ) positiveMovetemp[i] = positiveMove[i];

for ( int i = 0 ;i coun;i ++ )

{

move (j,f[j].s getPosition (),positiveMovetemp[i]);

bestMove = max (bestMove, Alpha_Beta (depth - 1 , ! luot,alpha,beta));

//undo

Undo ();

alpha = max (alpha,bestMove);

if (beta <= alpha) return bestMove;

int bestMove = 10000 ;//gia cua bestMove ban dau

for ( int j = 0 ;j < 16 ;j ++ )//quan cua may

Trang 24

for ( int i = 0 ; i < coun; i ++ ) positiveMovetemp[i] = positiveMove[i];

for ( int i = 0 ;i coun;i ++ )

{

move (j,f[j].s getPosition (),positiveMovetemp[i]);

bestMove = min (bestMove, Alpha_Beta (depth - 1 , ! luot,alpha,beta));

//undo

Undo ();

beta = min (beta,bestMove);

if (beta <= alpha) return bestMove;

void GameManager :: IncreasePositive ( int i, int j){

positiveMove[positiveCount] = Vector2f (i * size,j * size) + offset;

positiveCount ++ ;

}

void GameManager :: move ( int n,Vector2f oldPos,Vector2f newPos)

{

posS push (oldPos);

posS push (newPos);

nS push (n);

int y =int ((newPos - offset).y / size);//kiem tra xem co phong hau hay khong

//phong hau cho tot

if (f[i].s getPosition () == newPos) {

f[i].s setPosition ( 100 , - 100 );//di chuyen em bi an ra khoi man hinh

posS push (newPos);

posS push ( Vector2f ( 100 , - 100 ));

nS push (i);

break ;//neu ta dat f[n].s.setPosition(newPos) len truoc ma ko co break=> bi mat not con nay }

Trang 25

f[k].s setTextureRect ( IntRect (size * x,size * y,size,size) );

f[k].s setPosition (size * j + offset.x,size * i + offset.y);

//cost

int v = 0 ,g;

g = abs (f[k].index);

Trang 26

for ( int k = 0 ; k < count1; k ++ ) positiveMovetemp[k] = positiveMove[k];

//set oldPos va newPos tam thoi

oldPostemp = f[i].s getPosition ();

//newPostemp=positiveMove[0];

for ( int j = 0 ;j < count1;j ++ )

{

move (i,oldPostemp,positiveMovetemp[j]);

int alpha =- 9999 ,beta = 9999 ;

int temp = Alpha_Beta ( 3 , ! luot,alpha,beta);

Trang 27

}

//lay cac thong tin nuoc di

posS push (oldPos);//luu tam o trong stack ty ra ngoai xoa di

int k = grid[x][y] / abs (grid[x][y]);// 1 hoac -1

if ((y == 1 || y == 6 ) && grid[x][y - k] == 0 && grid[x][y - 2 k] == 0 && y - 2 k >= 0 && y - 2 k < 8 )

IncreasePositive (x,y - 2 k);

if (grid[x][y - k] == 0 && y - k >= 0 && y - k < 8 ) IncreasePositive (x,y - k);

if (grid[x + 1 ][y - k] * grid[x][y] < 0 && y - k >= 0 && y - k < 8 && x + 1 < 8 ) IncreasePositive (x + 1 ,y - k);

if (grid[x - 1 ][y - k] * grid[x][y] < 0 && y - k >= 0 && y - k < 8 && x - 1 >= 0 ) IncreasePositive (x - 1 ,y - k); }

void GameManager :: PositiveVua ( int n, int x, int y, int grid[ 9 ][ 9 ])//xet 8 vi tri co the di cua vua

{

if ((grid[x + 1 ][y] == 0 || grid[x][y] * grid[x + 1 ][y] < 0 ) && x + 1 < 8 ) IncreasePositive (x + 1 ,y);

if ((grid[x - 1 ][y] == 0 || grid[x][y] * grid[x - 1 ][y] < 0 ) && x - 1 >= 0 ) IncreasePositive (x - 1 ,y);

if ((grid[x + 1 ][y + 1 ] == 0 || grid[x][y] * grid[x + 1 ][y + 1 ] < 0 ) && x + 1 < 8 && y + 1 < 8 )

IncreasePositive (x + 1 ,y + 1 );

if ((grid[x - 1 ][y + 1 ] == 0 || grid[x][y] * grid[x - 1 ][y + 1 ] < 0 ) && x - 1 >= 0 && y + 1 < 8 ) IncreasePositive (x

-1 ,y + 1 );

if ((grid[x][y + 1 ] == 0 || grid[x][y] * grid[x][y + 1 ] < 0 ) && y + 1 < 8 ) IncreasePositive (x,y + 1 );

if ((grid[x - 1 ][y - 1 ] == 0 || grid[x][y] * grid[x - 1 ][y - 1 ] < 0 ) && x - 1 >= 0 && y - 1 >= 0 ) IncreasePositive (x - 1 ,y

Ngày đăng: 12/11/2024, 06:36

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w