1. Trang chủ
  2. » Luận Văn - Báo Cáo

Báo cáo môn nhập môn trí tuệ nhân tạo Đ ti áp dụng thuật toán quay lui Để giải bi toán sudoku

19 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 đề Áp Dụng Thuật Toán Quay Lui Để Giải Bài Toán Sudoku
Tác giả Đỗ Văn Phong, Nguyễn Duy Nam
Người hướng dẫn Nguyễn Hà Nam
Trường học Trường Đại Học Điện Lực
Chuyên ngành Công Nghệ Thông Tin
Thể loại báo cáo
Thành phố Hà Nội
Định dạng
Số trang 19
Dung lượng 1,51 MB

Nội dung

LỜI MỞ ĐẦU Đề tài Sudoku 9x9 sử dụng ngôn ngữ lập trình C thể hiện các thuật toán đệ quy và quay lui bằng công cụ lập trình DEV C++ để giải một bài toán Sudoku 9x9 cho trước... Bằng việc

Trang 1

TRƯỜNG ĐẠI HỌC ĐIỆN LỰC

KHOA CÔNG NGHỆ THÔNG TIN

BÁO CÁO MÔN NHẬP MÔN TRÍ TUỆ NHÂN TẠO

Đ TI:

ÁP DỤNG THUẬT TOÁN QUAY LUI ĐỂ GIẢI BI

TOÁN SUDOKU

Sinh viên thực hiện : ĐỖ VĂN PHONG

NGUYỄN DUY NAM Giảng viên hướng dẫn : NGUYỄN H NAM

Hà Nội, tháng năm

LỜI MỞ ĐẦU

Đề tài Sudoku 9x9 sử dụng ngôn ngữ lập trình C thể hiện các thuật toán đệ quy

và quay lui bằng công cụ lập trình DEV C++ để giải một bài toán Sudoku 9x9 cho trước

Trang 2

Thông qua báo cáo này, chúng em xin gửi lời cảm ơn đến thầy Nguyễn Hà Nam – giảng viên hướng dẫn đã hỗ trợ tận tình và giải đáp các thắc mắc trong suốt quá trình làm đồ án Giải thuật và Lập trình

Tuy nhiên, do kiến thức còn hạn hẹp, mặc dù đã nỗ lực hết sức mình, nhưng chắc rằng đồ án khó tránh khỏi thiếu sót Chúng em rất mong nhận được sự thông cảm và chỉ bảo tận tình của quý Thầy cô và các bạn

Xin chân thành và cảm ơn

Trang 3

DANH MỤC HÌNH ẢNH

Hình 1 Ví dụ một đề bài Sudoku 9x9.

Hình 2 Đáp án câu đố.

Hình 3 Cây tìm kiếm quay lui.

Hình 4 Mảng S.

Hình 5 Giao diện chương trình chính.

Hình 6 Đầu vào input.txt

Hình 7 Lựa chọn 1: Giải từng bước – Xem tiến trình bước 1 – Đáp án 1 Hình 8 Lựa chọn 1: Giải từng bước - Xem tiến trình bước 2 – Đáp án 2 Hình 9 Lựa chọn 2: Xem đáp án 1

Hình 10 Lựa chọn 2: Xem đáp án 2

Hình 11.So sánh kết quả và đầu ra output.

Trang 4

1 GIỚI THIỆU Đ TI

Sudoku là một từ Nhật, có thể dịch tạm là con số độc nhất, (Thật ra nó có nguồn gốc từ Mỹ với tên gọi là "đặt con số vào vị trí đúng") Đây là một trò chơi trí tuệ nổi tiếng, thu hút nhiều người tham gia thuộc nhiều tầng lớp, độ tuổi khác nhau Sudoku có nhiều biến thể khác nhau: 3x3, 4x4, 6x6, 8x8, 9x9, 12x12, 16x16,… Đối với đề tài này, chúng em áp dụng cho sudoku dạng chuẩn 9x9

Bảng câu đố hình vuông, mỗi chiều có 9 ô nhỏ, hợp thành 9 cột, 9 hàng và được chia thành 9 ô lớn 3x3 Một vài ô nhỏ được đánh số, đó là những manh mối duy nhất để bạn tìm lời giải Tuỳ theo mức độ nhiều hay ít của các manh mối, các câu đố được xếp loại dễ, trung bình, khó hay cực khó

Hình 1 Ví dụ một đề bài Sudoku 9x9

Cách chơi Sudoku là điền các số từ 1 đến 9 vào các ô trống theo quy luật đơn giản:

- Các ô ở mỗi hàng (ngang) phải có đủ các con số từ 1 đến 9 không cần theo thứ tự

- Các ô ở mỗi hàng (dọc) phải có đủ các con số từ 1 đến 9 không cần theo thứ tự

- Mỗi miền 3x3 được viền đậm phải có đủ các số từ 1 đến 9

Trang 5

Hình 2 Đáp án câu đố

2 CƠ SỞ LÝ THUYẾT

2.1 Ý tưởng

Chương trình giải dựa trên thuật toán quay lui Bằng việc liệt kê các tình huống, thử các khả năng có thể cho đến khi tìm thấy một lời giải đúng, thuật toán quay lui chia nhỏ bài toán, lời giải của bài toán lớn sẽ là kết quả của việc tìm kiếm theo chiều sâu của tập hợp các bài toán phần tử Trong suốt quá trình tìm kiếm nếu gặp phải một hướng nào đó mà biết chắc không thể tìm thấy đáp

án thì quay lại bước trước đó và tìm hướng khác kế tiếp hướng vừa tìm kiếm đó Trong trường hợp không còn một hướng nào khác nữa thì thuật toán kết thúc

2.2 Cơ sở lý thuyết

2.2.1 Thuật toán Quay lui (Backtracking)

Quay lui là một chiến lược tìm kiếm lời giải cho các bài toán thỏa mãn ràng buộc.Các bài toán thỏa mãn ràng buộc là các bài toán có một lời giải đầy đủ, trong đó thứ tự các phần tử không quan trọng Các bài toán này bao gồm một tập các biến mà mỗi biến cần được gán một giá trị tùy theo các ràng buộc cụ thể của bài toán Việc quay lui là thử tất cả các tổ hợp để tìm một lời giải Thế mạnh của phương pháp này là nhiều cài đặt tránh được việc phải thử nhiều tổ hợp chưa hoàn chỉnh, và nhờ đó giảm thời gian chạy, tìm được nhiều đáp án cho những bài toán có nhiều cách giải

Đó là một quá trình tìm kiếm độ sâu trong một tập hợp các lời giải Trong quá trình tìm kiếm, nếu ta gặp một hướng lựa chọn không thỏa mãn, ta quay lui về điểm lựa chọn nơi có các hướng khác và thử hướng lựa chọ tiếp theo Khi đã thử

Trang 6

hết các lựa chọn xuất phát từ điểm lựa chọn đó, ta quay lại điểm lựa chọn trước

đó và thử hướng lựa chọn tiếp theo tại đó Quá trình tìm kiếm thất bại khi không còn điểm lựa chọn nào nữa

Quy trình đó thường được cài đặt bằng một hàm đệ quy mà trong đó mỗi thể hiện của hàm lấy thêm một biến và lần lượt gán tất cả các giá trị có thể cho biến

đó, với mỗi lần gán giá trị lại gọi chuỗi đệ quy tiếp theo để thử các biến tiếp theo Chiến lược quay lui tương tự với tìm kiếm theo độ sâu nhưng sử dụng ít không gian bộ nhớ hơn, nó chỉ lưu trữ trạng thái của một lười giải hiện tại và cập nhật nó

Hình 3 Cây tìm kiếm quay lui

-Ở một bài toán hiện tại (mỗi nốt), ta đi tìm lời giả cho bài toán đó Ứng với lờigiải, ta đi giải bài toán kế tiếp cho đến khi bài toán gốc trở nên đầy đủ

-Lời giải của bài toán gốc thường là một lối đi từ gốc đến nốt cuối cùng

3 TỔ CHỨC CẤU TRÚC DỮ LIỆU VÀ THUẬT TOÁN

3.1 Phát biểu bài toán

- Đầu vào : Đề Sudoku đọc bảng từ file , hoặc do người dùng nhập

- Đầu ra (Kết quả): Đáp án có thể là các bước giải Sudoku của chương trình hoặc đáp án toàn bộ chương trình (có thể ra nhiều đáp án nếu đầu vào có nhiều đáp án)

3.2 Cấu trúc dữ liệu

1 Biến

Sử dụng biến kiểu mảng hai chiều để thể hiện vị trí của các phần tử đang xét

Trang 7

Mảng hai chiều là một mảng mà các phần tử của nó là mảng một chiều, giống như một bảng gồm có dòng và cột, được đánh dấu vị trí là các chỉ số bao gồm chỉ số dòng và chỉ số cột trong đó

Trong ngôn ngữ C, mảng hai chiều được khai báo theo cú pháp: data_type array_name[num1][num2];

- với data_type là kiểu dữ liệu của các phần tử trong mảng

- num1 số mảng một chiều có trong mảng

- num2 số phần tử có trong mỗi mảng một chiều Ví dụ mảng hai chiều S trong bài được khai báo như sau:

int S[9][9];

Khi đó mảng S giống như một bảng có 9 hàng và 9 cột (mỗi hàng có 9 phần tử),

và mỗi phần tử trong mảng là một số kiểu int

Hình 4 Mảng S

Muốn truy cập đến một phần tử trong mảng ta dùng cú pháp S[i][j] Khi đó S[i] [j] chứa giá trị của ô ở vị trí hàng i cột j

2 Hàm

Trong mảng hai chiều đưa vào chương trình, các phần tử trong mảng tương ứng với các ô trong đề Sudoku Trong mảng này, các ô chưa được điền nhận giá trị bằng 0, các ô đã được điền mang giá trị đã được điền vào Với mỗi ô chưa được điền, giá trị của ô đó bằng 0

Khi đó để kiểm tra khả năng điền giá trị của ô đó ta dùng hàm check() như sau:

Trang 8

- Kiểm tra hàng: Kiểm tra giá trị k (với k có thể nhận giá trị từ 1-9) có thể điền vào ô trên hay không Kiểm tra xem trên hàng đó đã có ô nào có giá trị bằng k hay chưa bằng cách duyệt hết tất cả các phần tử trên hàng đó, nếu đã có thì loại bỏ khả năng ô đó nhận giá trị k

- Kiểm tra cột: Kiểm tra giá trị k (với k có thể nhận giá trị từ 1-9) có thể điền vào ô đó không Kiểm tra xem trên cột đó đã có ô nào mang giá trị k chưa bằng cách duyệt hết tất cả các phần tử có trong cột, nếu đã có thì loại

bỏ khả năng ô đó nhận giá trị k

- Kiểm tra trong vùng 9 ô: với giá trị k có thể có giá trị từ 1 đến 9 Kiểm tra xem trong vùng 9 ô có ô nào chứa giá trị k chưa, nếu có thì loại trừ khả năng nhận giá trị k của ô đó

- Nếu với một số k sau khi kiểm tra đạt cả 3 khả năng trên thì có thể gán giá trị k cho ô đó

Trong đó các tham số truyền vào là:

+ Mảng S[][] là mảng chúng ta đang xét

+ Số nguyên x chứa vị trí dòng của ô đang xét trong mảng + Số nguyên y chứa vị trí cột của ô đang xét

+ k là giá trị muốn kiểm tra xem có thể điền vào ô đang xét hay không

Hàm trên sẽ trả về giá trị 1 nếu k được điền vào ô đang xét và trả về 0 nếu không được điền vào ô đang xét

Hàm sovle() thực hiện thuật toán quay lui Hàm có 3 tham số đầu vào: mảng dữ liệu S, biến vị trí x,y Chương trình sẽ duyệt trên từng ô của mảng hai chiều, trên từng ô chương trình sẽ kiểm tra xem ô đó đã được điền hay chưa, nếu chưa được điền thì chương trình sẽ duyệt hết tất cả các giá trị k chạy từ 1- 9 xem những giá trị nào có thể điền vào ô đang xét Tại đây ứng với mỗi giá trị có thể điền vào ô đang xét chương trình sẽ gọi đệ quy đến ô tiếp theo trong hàng Nếu trường hợp

do giá trị điền ô trước đó mà ô tiếp theo không thể điền giá trị thì chương trình

sẽ quay lui lại và thử với giá trị khác Cứ như thế cho đến khi xét xong ô cuối cùng trong mảng (ô thứ 81) Tại đây chương trình sẽ xuất ra kết quả và kết thúc chương trình

Trang 9

3.3 Thuật toán

3.3.1 Thuật toán quay lui

Thuật toán quay lui (backtracking) như tên gọi của nó, là một quá trình tìm kiếm

mà trong quá trình tìm kiếm, nếu ta gặp một hướng lựa chọn không thỏa mãn, ta quay lui về điểm lựa chọn nơi có các hướng khác và thừ hướng lựa chọn tiếp theo Quá trình tìm kiếm thất bại khi không còn điểm lựa chọn nào nữa

Độ phức tạp:

Trong trường hợp xấu nhất độ phức tạp của quay lui vẫn là cấp số mũ Vì

nó mắc phải các nhược điểm sau:

• Rơi vào tình trạng "thrashing": quá trình tìm kiếm gặp phải bế tắc với cùng một nguyên nhân

• Thực hiện các công việc dư thừa: Mỗi lần chúng ta quay lui, chúng ta cần phải đánh giá lại lời giải trong khi đôi lúc điều đó không cần thiết

• Không sớm phát hiện được các khả năng bị bế tắc trong tương lai Quay lui chuẩn, không có cơ chế nhìn về tương lai để nhận biết được nhánh tìm kiếm sẽ đi vào bế tắc

4.CHƯƠNG TRÌNH VÀ KẾT QUẢ

4.1 Tổ chức chương trình

#include <time.h>

#include <stdio.h>

#include <window

s.h> int c=0;

char N[10] = { '_' '1' '2' '3' '4' '5' '6' '7' '8' '9' , , , , , , , , , };

Trang 10

int S[9][9];

show(

void int S [][9]);

gotoxy( ,

void int x int y );

setcolor( );

void int color

void tientrinh( , int int int int i , j k , color );

readFile(FILE * ); int f

void getData( int S [][9]);

option1_solve_sudoku( [9][9], , );

void option2_solve_sudoku( int S [9][9], int x , int y );

int check( int S [][9], int x , int y , int k );

Output(

void int S [][9]);

resuilt(

void int S [][9]);

main( ){ getData(S); index; t=1; show(S); printf( );

while (t)

{ printf( " -SUDOKU -\n" ); printf( "1 Xem tien trinh : \n" ); printf( "2 Xem dap an : \n" ); printf( " -\n" );

printf( "Nhap lua chon:" ); scanf( "%d" ,&index);

switch (index)

{

case 1: option1_solve_sudoku(S,0,0); break case ; 2:

option2_solve_sudoku(S,0,0); c=0;

break case ; 0: t=0; break ;

default :

break;

}

}

Trang 11

// ham gotoxy

void gotoxy( , ) int x int y

{ static HANDLE h = NULL;

if(!h)

h = GetStdHandle(STD_OUTPUT_HANDLE);

COORD c = { , }; x y

SetConsoleCursorPosition(h,c);

}

// ham thiet lap mau chu

void setcolor( int color )

{

HANDLE hConsoleColor; hConsoleColor =

GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleTextAttribute(hConsoleColor, color );

}

// ham tien trinh

void tientrinh( , int int int i , j k , int color )

{ size= 4; gotoxy( *size, int j i *(size-2));

setcolor( color ); printf( "%c" , N[ ]); } k

// ham doc file

int readFile(FILE * ){ n; fscanf( f int f , "%d" , &n);

return n;

}

// ham chuyen du lieu file qua mang S

void getData( int S [][9])

{ A[81]; count = 0; FILE *f; f = fopen( int int "Input.txt" "r" , ); while (!feof(f)){ A[count] = readFile(f); count++; } t = 0; i, j; int int for (i = 0; i < 9; i++)

{ for (j = 0; j < 9; j++) {

S [i][j] = A[t]; t++;

} } fclose(f);

Trang 12

// lua chon tien trinh giai sudoku

void option1_solve_sudoku( [9][9], , ){ Sleep(400); int S int x int y

== 9){ == 8){

setcolor(12); gotoxy(60, c*20+1); printf( "DAP AN

%d:\n\n" ,c+1); resuilt( ); system( S "pause" ); Output( ); c+ S +;

} else { option1_solve_sudoku( , S x +1,0);

}

} else if( S [ x y ][ ] == 0){ k = 0; int for (k = 1; k <=9; k++){

if(check( , , S x y ,k)){ tientrinh( x y , k,12);

S x y [ ][ ] = k; option1_solve_sudoku( , , +1); S x y tientrinh( x y , 0, 5); S x y [ ][ ] = 0;

Sleep(400);

} }

} else { option1_solve_sudoku( S x y , , +1);

}

}

// lua chon xuat tat ca dap an ra man hinh

void option2_solve_sudoku( int S [9][9], int x , int y ){

== 9){ == 8){ setcolor(12); gotoxy(60, c*20+1); printf(

%d:\n\n" ,c+1); resuilt( S );

Output( S ); c++;

} else { option2_solve_sudoku( , S x +1,0);

}

} else if( S [ x y ][ ] == 0){ k = 0; int for (k = 1; k <=9; k++){

if(check( , , ,k)){ S x y

Trang 13

S x y [ ][ ] = k; option2_solve_sudoku( , , +1); S x y

S x y [ ][ ] = 0;

} }

} else { option2_solve_sudoku( S x y , , +1);

}

}

// ham kiem tra so k co dien duoc vao vi tri x y hay ko

int check( int S [][9], int x , int y , int k ){

i = 0, j = 0; int for (i = 0; i <9 ; i++){ if( S x [ ][i] == ) k return 0; } for (i = 0; i <9 ; i++){ if( S [i][ y ] == ) k return 0;

} a = /3, b = /3; int x y for (i = 3*a; i < 3*a+3; i++){ for (j = 3*b; j < 3*b+3; j++){ if( S [i][j] == ) k return 0;

}

} return 1;

} // ham xuat mang

void show( int S [][9]){ setcolor(10);

i = 0, j = 0; size= 4; int int for ( i= 0; i<9 ; i++)

{

for (j= 0; j<9; j++)

{

gotoxy(j*size,i*(size-2)); printf( "%c" ,N[ [i][j]]); S }

}

}

//ham xuat dap an ra man hinh

void resuilt( [][9]){ setcolor(3); int S

i = 0, j = 0; size= 4; int int for ( i= 0; i<9 ; i++)

{

Trang 14

for (j= 0; j<9; j++)

{

gotoxy(j*size+60,i*(size-2)+3+c*20); printf( "%c" ,N[ [i] S [j]]);

}

}

gotoxy(0, 21); printf( "\n" );

}

// ham xuat ra file dap an

void Output( int S [][9]){

FILE *p = fopen( "Output.TXT" "w+" , ); int

i, j;

for (i = 0; i < 9; i++)

{ for (j = 0; j < 9; j++)

{ a = [i][j]; fprintf(p, int S "%2d" ,

S [i][j]);

} fprintf(p, "\n" );

} fclose(p);

system( "pause" );

}

4.2 Ngôn ngữ cài đặt

Chương trình sử dụng ngôn ngữ C

4.3 Kết quả

4.3.1 Giao diện chính của chương trình

Đây là màn hình hiển thị các lựa chọn khi chạy chương trình sudoku 9x9

1 Lựa chọn 1: Xem các bước giải sudoku

2 Lựa chọn 2: Xem đáp án

Trang 15

Hình 5 Giao diện chương trình chính

4.3.2.

Hình 6 Đầu vào Input.txt

4.3.3 Kết quả thực thi của chương trình

Trang 16

Hình 7 Lựa chọn 1: Giải từng bước – Xem tiến trình bước 1 – Đáp án 1

Hình 8 Lựa chọn 1: Giải từng bước - Xem tiến trình bước 2 – Đáp án 2

Trang 17

Hình 9 Lựa chọn 2: Xem đáp án 1

Hình 10 Lựa chọn 2: Xem đáp án 2

Trang 18

Hình 11 So sánh kết quả và đầu ra output

4.3.4 Nhận xét

Chương trình giải được ô số sudoku có kích thước 9x9 có mức độ từ dễ đến khó Hạn chế của chương trình là chỉ đưa ra được một đáp án và nếu dữ liệu đầu vào quá ít thì chương trình có thề không đưa ra được kết quả Bài toán sudoku là bài toán phức tạp nên nhóm chỉ thao tác với chế độ văn bản

5 KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN

5.1 Kết luận

- Ưu điểm:

+ Cài đặt được thuật toán quay lui để giải bài toán

+ Chương trình đạt được yêu cầu đề ra (giải bài toán sudoku 9x9)

- Nhược điểm:

+ Chỉ giải được Sudoku 9x9, chưa mở rộng được bài toán với các dạng các nhau

5.2 Hướng phát triển

Sudoku ngày nay có rất nhiều biến thể, vì vậy cần phải phát triển chương trình theo hướng có thể giải nhiều dạng sudoku khác nhau, áp dụng nhiều thuật toán nhằm giải tối ưu hơn

Ngày đăng: 20/01/2025, 14:09

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

TÀI LIỆU LIÊN QUAN