From 9f9cf7924865fe861d5cb904af4ad33079d49c78 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Sat, 6 Mar 2021 23:53:24 +0800 Subject: [PATCH 01/21] The first homework test --- level1/p01_runningLetter/runningLetter.c | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 level1/p01_runningLetter/runningLetter.c diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c new file mode 100644 index 00000000..c06ef5c5 --- /dev/null +++ b/level1/p01_runningLetter/runningLetter.c @@ -0,0 +1,31 @@ +#include +#include + +void main() { + int n = 0; + char value = 1;//value为1时向右移动,否则向左移动 + while (1) { + if (value) { + for (int i = 0; i < n; i++) { + printf(" "); + } + printf("Running Word"); + n++; + system("cls");//清屏 + if (n == 105) { + value = 0; + } + } + else { + for (int i = 0; i < n; i++) { + printf(" "); + } + printf("Running Word"); + n--; + system("cls"); + if (n == 0) { + value = 1; + } + } + } +} From c9d89ec9e05e9ec42e7bbca860211eaa4b4d1984 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Sun, 7 Mar 2021 00:21:58 +0800 Subject: [PATCH 02/21] p02 The second homework --- level1/p02_isPrime/isprime.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 level1/p02_isPrime/isprime.c diff --git a/level1/p02_isPrime/isprime.c b/level1/p02_isPrime/isprime.c new file mode 100644 index 00000000..7423b3af --- /dev/null +++ b/level1/p02_isPrime/isprime.c @@ -0,0 +1,23 @@ +#include +#include + +int is_prime(int n){ + int i; + for(i=2;i<=sqrt(n);i++){ + if(n%i==0){ + return 0; + } + } + return 1; +} + +int main(){ + int n; + printf("Please enter a number: "); + scanf("%d",&n); + if(is_prime(n)&&n>1){ + printf("It is a prime number."); + }else{ + printf("It isn't a prime number.'"); + } +} From 519c7baa07684faf10d40c5067258c4862c7ffd0 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Sun, 7 Mar 2021 15:49:31 +0800 Subject: [PATCH 03/21] The third homework. --- level1/p03_Diophantus/Diophantus.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 level1/p03_Diophantus/Diophantus.c diff --git a/level1/p03_Diophantus/Diophantus.c b/level1/p03_Diophantus/Diophantus.c new file mode 100644 index 00000000..bf96ae4a --- /dev/null +++ b/level1/p03_Diophantus/Diophantus.c @@ -0,0 +1,12 @@ +#include +//丢番图问题 +int main(){ + float x; + for(x=1;x<200;x++){ + if((x/6+x/12+x/7+5+x/2+4)==x){ + printf("%.0f",x); + break; + } + } + return 0; +} From 7140d57dbed692348ceaacfb2fe0fc93d3e6c983 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Sun, 7 Mar 2021 16:09:13 +0800 Subject: [PATCH 04/21] The forth homework --- level1/p04_ narcissus/narcissus.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 level1/p04_ narcissus/narcissus.c diff --git a/level1/p04_ narcissus/narcissus.c b/level1/p04_ narcissus/narcissus.c new file mode 100644 index 00000000..30a39470 --- /dev/null +++ b/level1/p04_ narcissus/narcissus.c @@ -0,0 +1,14 @@ +#include + +int main(){ + int n; + int a,b,c; + for(n=100;n<1000;n++){ + c = n%10;//个位数 + b = n/10%10;//十位数 + a = n/100;//百位数 + if((a*a*a+b*b*b+c*c*c)==n){ + printf("%d\n",n); + } + } +} From 2431678e0202e16df3d987a3bb267bd74a8b0624 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Mon, 8 Mar 2021 22:12:09 +0800 Subject: [PATCH 05/21] The fifith homework --- level1/p05_allPrimes/allPrimes.c | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 level1/p05_allPrimes/allPrimes.c diff --git a/level1/p05_allPrimes/allPrimes.c b/level1/p05_allPrimes/allPrimes.c new file mode 100644 index 00000000..b2a70a7e --- /dev/null +++ b/level1/p05_allPrimes/allPrimes.c @@ -0,0 +1,64 @@ +#include +#include +#include + +//常规做法 +int is_prime1(){ + int i,n,m,t = 0; + for(n = 2;n < 1000;n ++){ + m = 1; + for(i = 2;i <= sqrt(n);i ++){ + if(n % i == 0){ + m = 0; + break; + } + } + if(m == 1){ + printf("%d\t",n); + t ++; + } + if(t == 15){ + printf("\n"); + t = 0; + } + } + return 0; +} + +//埃氏筛 +int is_prime2(){ + char a[1000] = {1}; + int i,x,m = 0; + for(i = 2;i < 1000;i ++){ + if(a[i] == 0){ + for(x = i*i;x < 1000;x = x + i)a[x] = 1; + printf("%d\t",i); + m ++; + if(m == 15){ + printf("\n"); + m = 0; + } + } + } +} + +int main(){ + int n,m = 0; + clock_t start_t,end_t; + double total_t; + + //常规做法 + start_t = clock(); + is_prime1(); + end_t=clock(); + total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC; + printf("\n程序运行的总时间为: %fs\n",total_t); + + //埃氏筛 + start_t = clock(); + is_prime2(); + end_t = clock(); + total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC; + printf("\n程序运行的总时间为: %fs",total_t); + return 0; +} From 7324072e48c9040c9d793dbac0beeb1b347026b8 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Mon, 8 Mar 2021 22:27:24 +0800 Subject: [PATCH 06/21] The sixth homework --- level1/p06_Goldbach/Goldbach.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 level1/p06_Goldbach/Goldbach.c diff --git a/level1/p06_Goldbach/Goldbach.c b/level1/p06_Goldbach/Goldbach.c new file mode 100644 index 00000000..8defbe72 --- /dev/null +++ b/level1/p06_Goldbach/Goldbach.c @@ -0,0 +1,26 @@ +#include +#include +#include + +bool is_prime(int n){ + int i; + for(i=2;i<=sqrt(n);i++){ + if(n%i==0)return false; + } + return true; +} + +int main(){ + int n,m,x=0; + for(n = 4;n <= 100;n += 2){ + for(m = 2;m <= n;m ++){ + if(is_prime(m) && is_prime(n - m)){ + printf("%3d = %2d + %2d\n",n,m,n - m); + x++; + break; + } + } + if(x==49)printf("The Goldbach is true"); + } + return 0; +} From 40ac36d484d1fe42d7b985b9cea648658bd1c042 Mon Sep 17 00:00:00 2001 From: Tian Jun <72535794+Crazycat-tj@users.noreply.github.com> Date: Tue, 9 Mar 2021 16:50:01 +0800 Subject: [PATCH 07/21] update runningLetter.c change 105 and 0 into const int --- level1/p01_runningLetter/runningLetter.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c index c06ef5c5..5c6e2aee 100644 --- a/level1/p01_runningLetter/runningLetter.c +++ b/level1/p01_runningLetter/runningLetter.c @@ -1,9 +1,11 @@ #include #include + void main() { int n = 0; - char value = 1;//value为1时向右移动,否则向左移动 + const int right_border = 105, left_border = 0; + char value = 1;//value涓1鏃跺悜鍙崇Щ鍔紝鍚﹀垯鍚戝乏绉诲姩 while (1) { if (value) { for (int i = 0; i < n; i++) { @@ -11,8 +13,8 @@ void main() { } printf("Running Word"); n++; - system("cls");//清屏 - if (n == 105) { + system("cls");//娓呭睆 + if (n == right_border) { value = 0; } } @@ -23,7 +25,7 @@ void main() { printf("Running Word"); n--; system("cls"); - if (n == 0) { + if (n == left_border) { value = 1; } } From 7f12c2d69ad4da4c566302927252d24bb3cd2783 Mon Sep 17 00:00:00 2001 From: Tian Jun <72535794+Crazycat-tj@users.noreply.github.com> Date: Tue, 9 Mar 2021 16:51:55 +0800 Subject: [PATCH 08/21] Update Diophantus.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 瑙e喅涔辩爜闂 --- level1/p03_Diophantus/Diophantus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/level1/p03_Diophantus/Diophantus.c b/level1/p03_Diophantus/Diophantus.c index bf96ae4a..5dd48f6a 100644 --- a/level1/p03_Diophantus/Diophantus.c +++ b/level1/p03_Diophantus/Diophantus.c @@ -1,5 +1,5 @@ #include -//丢番图问题 +//涓㈢暘鍥鹃棶棰 int main(){ float x; for(x=1;x<200;x++){ From 4cac58a039bca85e06dbc331521e4a6ead9414f1 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Tue, 9 Mar 2021 20:47:44 +0800 Subject: [PATCH 09/21] add encrypt_decrypt.c --- level1/p07_encrypt_decrypt/encrypt.c | 99 ++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 level1/p07_encrypt_decrypt/encrypt.c diff --git a/level1/p07_encrypt_decrypt/encrypt.c b/level1/p07_encrypt_decrypt/encrypt.c new file mode 100644 index 00000000..6004d416 --- /dev/null +++ b/level1/p07_encrypt_decrypt/encrypt.c @@ -0,0 +1,99 @@ +/*尝试凯撒加密与解密*/ +#include +#include +#include + +//加密 +void encode(char str[], int n) { + int i; + char c; + for (i = 0; i < strlen(str); ++i) { + c = str[i]; + if (str[i] >= 'A' && str[i] <= 'Z') { + if (c + n % 26 <= 'Z') { + str[i] = (char)(c + n % 26); + } + else { + str[i] = (char)(c + n % 26 - 26); + } + } + else if (str[i] >= 'a' && str[i] <= 'z') { + if (c + n % 26 <= 'z') { + str[i] = (char)c + n % 26; + } + else { + str[i] = (char)c + n % 26 - 26; + } + } + else { + str[i] = c;//不是字母,不加密 + } + } + printf("\nAfter encode: \n"); + puts(str); +} + +//解密 +void decode(char str[], int n) { + int i; + char c; + for (i = 0; i <= strlen(str); ++i) { + c = str[i]; + if (str[i] <= 'z' && str[i] >= 'a') { + if (c - n % 26 > 'a') { + str[i] = (char)(c - n % 26); + } + else { + str[i] = (char)(c - n % 26 + 26); + } + } + else if (str[i] <= 'Z' && str[i] >= 'A') { + if (c - n % 26 > 'A') { + str[i] = (char)(c - n % 26); + } + else { + str[i] = (char)(c - n % 26 + 26); + } + } + else { + str[i] = c; + } + } + printf("\nAfter decode: \n"); + puts(str); +} + + +int main() { + char str[50]; + int k, q = 1; + int n,c; + while (q) { + system("cls"); + printf("Please enter your word:\n"); + scanf_s("%s", str,50); + printf("Please set the encode function: \n"); + scanf_s("%d", &n); + printf("-----------------\n"); + printf("1: Encryption\n"); + printf("2: Decryption\n"); + printf("-----------------\n"); + printf("\nPlease choose: "); + scanf_s("%d", &k); + if (k == 1) { + encode(str, n); + } + else if (k == 2) { + decode(str, n); + } + + printf("Do you want to quit (1/0): \n"); + scanf_s("%d", &c); + if (c == 1) { + q = 0; + } + } + return 0; + +} + From 601f706dc66863253682c4ba9fbd86e96194faae Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Tue, 9 Mar 2021 21:09:07 +0800 Subject: [PATCH 10/21] modified --- level1/p01_runningLetter/runningLetter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c index c06ef5c5..5e009fed 100644 --- a/level1/p01_runningLetter/runningLetter.c +++ b/level1/p01_runningLetter/runningLetter.c @@ -1,8 +1,10 @@ #include #include + void main() { int n = 0; + const int right_border = 105, left_border = 0; char value = 1;//value为1时向右移动,否则向左移动 while (1) { if (value) { @@ -12,7 +14,7 @@ void main() { printf("Running Word"); n++; system("cls");//清屏 - if (n == 105) { + if (n == right_border) { value = 0; } } @@ -23,9 +25,10 @@ void main() { printf("Running Word"); n--; system("cls"); - if (n == 0) { + if (n == left_border) { value = 1; } } } } + From 425ab15ca2ecaf59965d1fb7f1c85c99e123bc53 Mon Sep 17 00:00:00 2001 From: Tian Jun <72535794+Crazycat-tj@users.noreply.github.com> Date: Tue, 9 Mar 2021 21:26:46 +0800 Subject: [PATCH 11/21] Update runningLetter.c --- level1/p01_runningLetter/runningLetter.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c index 1fa23d2b..0353dac9 100644 --- a/level1/p01_runningLetter/runningLetter.c +++ b/level1/p01_runningLetter/runningLetter.c @@ -5,11 +5,7 @@ void main() { int n = 0; const int right_border = 105, left_border = 0; -<<<<<<< HEAD - char value = 1;//value为1时向右移动,否则向左移动 -======= char value = 1;//value涓1鏃跺悜鍙崇Щ鍔紝鍚﹀垯鍚戝乏绉诲姩 ->>>>>>> 7f12c2d69ad4da4c566302927252d24bb3cd2783 while (1) { if (value) { for (int i = 0; i < n; i++) { @@ -17,11 +13,8 @@ void main() { } printf("Running Word"); n++; -<<<<<<< HEAD - system("cls");//清屏 -======= system("cls");//娓呭睆 ->>>>>>> 7f12c2d69ad4da4c566302927252d24bb3cd2783 + if (n == right_border) { value = 0; } From 924bad76736127ed7986516a560c2ebe8637b736 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Tue, 9 Mar 2021 21:29:30 +0800 Subject: [PATCH 12/21] test2 --- level1/p01_runningLetter/runningLetter.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c index 1fa23d2b..5e009fed 100644 --- a/level1/p01_runningLetter/runningLetter.c +++ b/level1/p01_runningLetter/runningLetter.c @@ -5,11 +5,7 @@ void main() { int n = 0; const int right_border = 105, left_border = 0; -<<<<<<< HEAD char value = 1;//value为1时向右移动,否则向左移动 -======= - char value = 1;//value涓1鏃跺悜鍙崇Щ鍔紝鍚﹀垯鍚戝乏绉诲姩 ->>>>>>> 7f12c2d69ad4da4c566302927252d24bb3cd2783 while (1) { if (value) { for (int i = 0; i < n; i++) { @@ -17,11 +13,7 @@ void main() { } printf("Running Word"); n++; -<<<<<<< HEAD system("cls");//清屏 -======= - system("cls");//娓呭睆 ->>>>>>> 7f12c2d69ad4da4c566302927252d24bb3cd2783 if (n == right_border) { value = 0; } From 4eda115a484a527b34deff446dcfe749db0bf277 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Tue, 9 Mar 2021 21:34:04 +0800 Subject: [PATCH 13/21] modified --- level1/p01_runningLetter/runningLetter.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c index fe002607..5e009fed 100644 --- a/level1/p01_runningLetter/runningLetter.c +++ b/level1/p01_runningLetter/runningLetter.c @@ -5,11 +5,7 @@ void main() { int n = 0; const int right_border = 105, left_border = 0; -<<<<<<< HEAD char value = 1;//value为1时向右移动,否则向左移动 -======= - char value = 1;//value涓1鏃跺悜鍙崇Щ鍔紝鍚﹀垯鍚戝乏绉诲姩 ->>>>>>> 425ab15ca2ecaf59965d1fb7f1c85c99e123bc53 while (1) { if (value) { for (int i = 0; i < n; i++) { @@ -17,12 +13,7 @@ void main() { } printf("Running Word"); n++; -<<<<<<< HEAD system("cls");//清屏 -======= - system("cls");//娓呭睆 - ->>>>>>> 425ab15ca2ecaf59965d1fb7f1c85c99e123bc53 if (n == right_border) { value = 0; } From 45fac38ef58260f977fbd23b6d8496586f9fe340 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Tue, 9 Mar 2021 21:37:18 +0800 Subject: [PATCH 14/21] wrong --- level1/p01_runningLetter/runningLetter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c index 5e009fed..b16b9a9d 100644 --- a/level1/p01_runningLetter/runningLetter.c +++ b/level1/p01_runningLetter/runningLetter.c @@ -5,7 +5,7 @@ void main() { int n = 0; const int right_border = 105, left_border = 0; - char value = 1;//value为1时向右移动,否则向左移动 + char value = 1; while (1) { if (value) { for (int i = 0; i < n; i++) { @@ -13,7 +13,7 @@ void main() { } printf("Running Word"); n++; - system("cls");//清屏 + system("cls"); if (n == right_border) { value = 0; } From 86540363b249dd1cf022b53c4508330193d03b44 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Sun, 14 Mar 2021 12:19:58 +0800 Subject: [PATCH 15/21] hanio game --- level1/p08_hanoi/haoni.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 level1/p08_hanoi/haoni.c diff --git a/level1/p08_hanoi/haoni.c b/level1/p08_hanoi/haoni.c new file mode 100644 index 00000000..4695a81a --- /dev/null +++ b/level1/p08_hanoi/haoni.c @@ -0,0 +1,28 @@ +#include +int m = 0; +void move(int disk, char A, char C) { + m++; + printf("第 %d 次移动: 将 %d 号圆盘从 %c 移动到 %c\n", m, disk, A, C); +} +void hanoi(int n, char A, char B, char C) { + if (n == 1) { + move(n, A, C); + } + else { + hanoi(n - 1, A, C, B); + move(n, A, C); + hanoi(n - 1, B, A, C); + } +} + +int main() { + char A = 'A'; + char B = 'B'; + char C = 'C'; + int disks; + printf("请输入圆盘的个数\n"); + scanf("%d", &disks); + hanoi(disks, A, B, C); + return 0; +} + From 4874fe5116198df996c80b613f9b6f52feac384e Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Tue, 23 Mar 2021 13:43:59 +0800 Subject: [PATCH 16/21] =?UTF-8?q?=E5=B8=B8=E9=87=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- level1/p01_runningLetter/runningLetter.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c index b16b9a9d..5820bdda 100644 --- a/level1/p01_runningLetter/runningLetter.c +++ b/level1/p01_runningLetter/runningLetter.c @@ -4,7 +4,7 @@ void main() { int n = 0; - const int right_border = 105, left_border = 0; + const int RIGHT_BORDER = 105, LEFT_BORDER = 0; char value = 1; while (1) { if (value) { @@ -14,7 +14,7 @@ void main() { printf("Running Word"); n++; system("cls"); - if (n == right_border) { + if (n == RIGHT_BORDER) { value = 0; } } @@ -25,7 +25,7 @@ void main() { printf("Running Word"); n--; system("cls"); - if (n == left_border) { + if (n == LEFT_BORDER) { value = 1; } } From b264d1c944b28d61c96776c387dabc27274161ad Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Tue, 23 Mar 2021 14:09:52 +0800 Subject: [PATCH 17/21] maze --- level1/p09_maze/maze.c | 238 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 level1/p09_maze/maze.c diff --git a/level1/p09_maze/maze.c b/level1/p09_maze/maze.c new file mode 100644 index 00000000..3daaf9cb --- /dev/null +++ b/level1/p09_maze/maze.c @@ -0,0 +1,238 @@ +#include +#include +#include +#include +#include + +int rank = 6; +//地图边长 L,包括迷宫主体 20,外侧的包围的墙体 2,最外侧包围路径 2 +#define L 24 +#define WALL 0 //墙 +#define ROUTE 1 //路径 +#define PLAYER 2 //玩家 + +void menu(); +void start(); +void degree(); +int init(int** maze); +void print(int** maze); +void creatMaze(int** maze, int x, int y); +void move(int** maze, char t, int& x, int& y); + + +int main() { + menu(); + return 0; +} + +//显示主菜单 +void menu() { + char c; + while (1) { + system("cls"); + printf("---------------------\n"); + printf("---欢迎来到迷宫游戏---\n"); + printf("----1. 开始游戏 -----\n"); + printf("----2. 游戏难度 -----\n"); + printf("----0. 退出游戏 -----\n"); + printf("--------------------\n"); + c = _getch(); + switch (c) { + case '1': + start(); + break; + case '2': + degree(); + break; + case '0': + printf("欢迎下次继续游玩........\n"); + Sleep(1500); + exit(0); + default: + break; + } + } +} + +//开始游戏 +void start() { + char t; + //x,y是玩家的坐标,out是出口的纵坐标(行号) + int i, x = 2, y = 1, out = 0; + //初始化随机数种子,利用系统时间生成随机数,之后就可以使用rand函数生成随机数 + srand((unsigned)time(NULL)); + //初始化迷宫 + int** maze = (int**)malloc(L * sizeof(int*)); + for (i = 0; i < L; i++) { + maze[i] = (int*)calloc(L, sizeof(int)); + } + //得到出口纵坐标 + out = init(maze); + system("cls"); + print(maze); + while (t = _getch()) { + system("cls"); + move(maze, t, x, y); + print(maze); + if (x == out && y == L - 2) { + system("cls"); + printf("恭喜你,到达了终点!\n"); + printf("即将返回主菜单\n"); + Sleep(1500); + break; + } + } + for (i = 0; i < L; i++) + free(maze[i]); + free(maze); +} + +void degree() { + char t; + system("cls"); + printf("---------------------\n"); + printf("---请输入游戏难度---\n"); + printf("----- 1. 简单 -----\n"); + printf("----- 2. 中等 -----\n"); + printf("----- 3. 困难 -----\n"); + printf("--------------------\n"); + t = _getch(); + switch (t) { + case '1': + printf("已修改游戏难度为简单\n"); + rank = 6; + break; + case '2': + printf("已修改游戏难度为中等\n"); + rank = 3; + break; + case '3': + printf("已修改游戏难度为困难\n"); + rank = 0; + break; + default: + break; + } + printf("按任意键返回菜单\n"); + system("pause"); + +} +//初始化迷宫 +int init(int** maze) { + int i; + //将最外层都设置为空的路径,防止挖穿 + for (i = 0; i < L; i++) { + maze[i][0] = ROUTE; + maze[0][i] = ROUTE; + maze[i][L - 1] = ROUTE; + maze[L - 1][i] = ROUTE; + } + creatMaze(maze, 2, 2);//生成迷宫入口和出口 + maze[2][1] = PLAYER; //给玩家初始位置 + //寻找出口,出口可能不在[L-3][L-2],因此需要查找 + for (i = L - 3; i >= 0; i--) { + if (maze[i][L - 3] == ROUTE) { + maze[i][L - 2] = ROUTE; + return i; //出口返回纵坐标 + } + } +} + +//打印迷宫 +void print(int** maze) { + int i, j; + for (i = 0; i < L; i++) { + for (j = 0; j < L; j++) { + if (maze[i][j] == ROUTE) + printf(" "); + else if (maze[i][j] == WALL) + printf("墙"); + else if (maze[i][j] == PLAYER) + printf("十"); + } + printf("\n"); + } +} + +//构建迷宫 +void creatMaze(int** maze, int x, int y) { + maze[x][y] = ROUTE; + //确保四个方向随机,而不再是固定的上下左右这种排列 + int direction[4][2] = { { 1,0 },{ -1,0 },{ 0,-1 },{ 0,1 } }; + for (int i = 0; i < 4; i++) { + int r = rand() % 4; + int temp = direction[0][0]; + direction[0][0] = direction[r][0]; + direction[r][0] = temp; + temp = direction[0][1]; + direction[0][1] = direction[r][1]; + direction[r][1] = temp; + } + //向四个方向开挖 + for (int i = 0; i < 4; i++) { + int dx = x; + int dy = y; + //控制挖的距离,由Rank来调整大小 + int range = 1 + (rank == 0 ? 0 : rand() % rank); + while (range > 0) { + //计算出将要访问到的坐标 + dx += direction[i][0]; + dy += direction[i][1]; + //排除掉回头路 + if (maze[dx][dy] == ROUTE) { + break; + } + //判断是否挖穿路径 + int count = 0; + for (int j = dx - 1; j < dx + 2; j++) { + for (int k = dy - 1; k < dy + 2; k++) { + //abs(j - dx) + abs(k - dy) == 1 确保只判断九宫格的四个特定位置 + if (abs(j - dx) + abs(k - dy) == 1 && maze[j][k] == ROUTE) { + count++; + } + } + } + //count大于1表明墙体会被挖穿,停止 + if (count > 1) + break; + //确保不会挖穿时,前进 + range -= 1; + maze[dx][dy] = ROUTE; + } + //没有挖穿危险,以此为节点递归 + if (range <= 0) { + creatMaze(maze, dx, dy); + } + } +} + +//移动 +void move(int** maze, char t, int& x, int& y) { + int i, j; + i = x; + j = y; + switch (t) { + case 'w': + x--; + break; + case 's': + x++; + break; + case 'a': + y--; + break; + case 'd': + y++; + break; + default: + break; + } + if (x >= 0 && x < L-1 && y >= 0 && y < L-1 && maze[x][y] != WALL) { + maze[i][j] = ROUTE; + maze[x][y] = PLAYER; + } + else { + x = i; + y = j; + } +} From dccafb472fae6b37e666c95b4e191742b65e422a Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Thu, 25 Mar 2021 23:51:06 +0800 Subject: [PATCH 18/21] linkedList --- level1/p11_linkedList/linkedList.c | 108 +++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 level1/p11_linkedList/linkedList.c diff --git a/level1/p11_linkedList/linkedList.c b/level1/p11_linkedList/linkedList.c new file mode 100644 index 00000000..07aac8ff --- /dev/null +++ b/level1/p11_linkedList/linkedList.c @@ -0,0 +1,108 @@ +/* 在 main 函数中创建一个单向链表; +1. 遍历该链表,依次现实各节点的 value; +1. 将该链表所有节点反序; +1. 在该链表中查找第一个值为 5 的节点,如果找到则返回该节点的序号,否则返回-1; +1. 查找下一个值为 5 的节点,返回值同上;*/ + +#include +#include +typedef struct linkedList{ + int elem; + struct linkedList *next; +}link; + +link* initLink(int n); +link* reverse(link* p,int n); +link* insertLink(link* p,int elem,int add); +int find(link* p,int n,int ele,int num); + +int main(){ + int n; + printf("请输入要创建的链表大小:\n"); + scanf("%d",&n); + link* p = initLink(n+1); + link* temp = p->next; + for(int i = 1;i <= n;i ++){ + printf("请输入第%d号节点的元素值\n",i); + scanf("%d",&temp->elem); + temp = temp->next; + } + + //逆序 + p = reverse(p,n); + temp = p->next; + printf("逆序输出成功:\n"); + for(int i = 1;i<=n;i++){ + printf("%d ",temp->elem); + temp = temp->next; + } + printf("\n"); + + //查找 5 + for(int num=1;num<=2;num++){ + int position = find(p,n,5,num); + if(position!=-1) + printf("第%d个值为5的节点序号(逆序后)是:%d\n",num,position); + else + printf("没有找到值为5的节点\n"); + } + return 0; +} + +//init linklist +link* initLink(int n){ + link* p = (link*)malloc(sizeof(link)); //创建一个头节点 + link* temp = p; //创建一个中间变量用于遍历链表 + for(int i = 1 ; i < n; i ++){ + link* a = (link*)malloc(sizeof(link)); + a->elem = i; + a->next = NULL; + temp->next = a; + temp = temp->next; + } + return p; +} + +//add new element +link* insertLink(link* p,int elem,int add){ + link* temp = p; //创建临时节点,用于遍历 + link* c = (link*)malloc(sizeof(link)); + for(int i = 1;i < add;i ++){ + if(temp==NULL){ + printf("插入的位置无效\n"); + return p; + } + temp = temp->next; + } + c->elem = elem; + c->next = temp->next; + temp->next = c; + return p; +} + +//reverse the linklist +link* reverse(link*p,int n){ + link* temp = p->next; + link* newp = (link*)malloc(sizeof(link)); + newp->next = NULL; + for(int i =1;i<=n;i++){ + insertLink(newp,temp->elem,1); + temp = temp->next; + } + return newp; +} + +//find the element +int find(link* p,int n,int ele,int num){ + link* temp = p->next; + int x = 0; //记录找到的次数 + for(int i=1;i<=n;i++){ + if(temp->elem==ele){ + x++; + if(x==num) + return i; + } + temp = temp->next; + } + return -1; +} From 84d8c2c2ad0cf926a8320a1047584cd45430aaba Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Fri, 2 Apr 2021 20:33:02 +0800 Subject: [PATCH 19/21] add warehouse --- level1/p12_warehouse/warehouse.cpp | 226 +++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 level1/p12_warehouse/warehouse.cpp diff --git a/level1/p12_warehouse/warehouse.cpp b/level1/p12_warehouse/warehouse.cpp new file mode 100644 index 00000000..5076b35c --- /dev/null +++ b/level1/p12_warehouse/warehouse.cpp @@ -0,0 +1,226 @@ +#include +#include +#include + +typedef struct Node { + char name[200]; + int num; + struct Node* next; +}nodeList; + +void menu(); +void showList(nodeList* p); +void fileWrite(nodeList* p); +int find(nodeList* p, char* name); +nodeList* fileRead(); +nodeList* getin(nodeList* p); +nodeList* getout(nodeList* p); +nodeList* remove(nodeList* p, char* name, int num, int del); + +int main() { + menu(); +} + +// 打印菜单 +void menu() { + int t, q = 1; + nodeList* p = (nodeList*)malloc(sizeof(nodeList)); //初始化仓库 + p->next = NULL; + while (q) { + system("cls"); + printf("--------------\n"); + printf("欢迎来到仓库!\n"); + printf("1.显示存货列表\n"); + printf("2.进库\n"); + printf("3.出库\n"); + printf("4.保存\n"); + printf("5.读取\n"); + printf("0.退出\n"); + printf("--------------\n"); + scanf("%d", &t); + switch (t) { + case 1: + showList(p); //打印仓库清单 + break; + case 2: + p = getin(p); //入库 + break; + case 3: + p = getout(p); //出库 + break; + case 4: + fileWrite(p); //保存文件 + break; + case 5: + p = fileRead(); //读取文件 + break; + case 0: //退出 + q = 0; + printf("正在退出,欢迎下次再来......\n"); + Sleep(1500); + break; + default: + printf("error\n"); + system("pause"); + } + } +} + +//入库 +nodeList* getin(nodeList* p) { + char name[100]; + int num; + nodeList* temp = p; //临时变量 + nodeList* value = (nodeList*)malloc(sizeof(nodeList)); + system("cls"); + printf("请输入要存入仓库的货物名称:\n"); + scanf("%s", name); + printf("请输入要存入仓库的货物数量:\n"); + scanf("%d", &num); + int position = find(p, name); //寻找货物是否已经在仓库中,若在则返回位置,否则返回0 + if (position == 0) { //插入当链尾 + for (int i = 0; temp->next != NULL; i++) { + temp = temp->next; + } + value->next = NULL; + strcpy(value->name, name); + value->num = num; + temp->next = value; + } + else { + for (int i = 0; i < position; i++) { + temp = temp->next; + } + temp->num += num; + } + printf("已存入仓库......\n"); + system("pause"); + return p; +} + +//出库 +nodeList* getout(nodeList* p) { + char name[100]; + int num, del; + nodeList* temp = p; + system("cls"); + printf("请输入要出库的货品名字:\n"); + scanf("%s", name); + del = find(p, name); //寻找货物在仓库中的位置 + if (del > 0) { + printf("请输入要取出的货物数量:\n"); + scanf("%d", &num); + p = remove(p, name, num, del); + system("pause"); + } + else { + printf("未找到货物......\n"); + } + return p; +} + +//打印仓库 +void showList(nodeList* p) { + system("cls"); + nodeList* temp = p->next; + printf("---------------------------------------------------\n"); + printf("||货品名称\t\t\t\t货品数量 ||\n"); + printf("---------------------------------------------------\n"); + for (int i = 0; temp != NULL; i++) { + printf("||%-10s\t\t\t\t%-10d||\n", temp->name, temp->num); + printf("---------------------------------------------------\n"); + temp = temp->next; + } + system("pause"); +} + +// 寻找货物在仓库中的位置 +int find(nodeList* p, char* name) { + nodeList* temp = p->next; + for (int i = 1; temp != NULL; i++) { + if (!strcmp(name, temp->name)) + return i; + temp = temp->next; + } + return 0; +} + +// 取出货物 +nodeList* remove(nodeList* p, char* name, int num, int del) { + nodeList* temp = p; + for (int i = 1; i < del; i++) { + temp = temp->next; + } + if (num == temp->next->num) { + nodeList* c = temp->next; + temp->next = temp->next->next; + printf("已取出货物....... \n"); + free(c); + } + else if (num < temp->next->num) { + temp->next->num -= num; + printf("已取出货物....... \n"); + } + else { + printf("error,没有那么多货物......\n"); + } + return p; +} + +// 写入文件 +void fileWrite(nodeList* p) { + FILE* fp = NULL; + nodeList* temp = p->next; + + system("cls"); + if ((fp = fopen("test.txt", "w")) == NULL) { + printf("File failed to open......\n"); + system("pause"); + return; + } + else { + printf("打开文件成功......\n"); + } + while (temp != NULL) { + fprintf(fp, "%s %d\n", temp->name, temp->num); //逐行写入文件 + temp = temp->next; + } + fclose(fp); + printf("保存成功......\n"); + system("pause"); +} + +//读取文件 +nodeList* fileRead() { + nodeList* p = (nodeList*)malloc(sizeof(nodeList)); + nodeList* temp = p; + system("cls"); + FILE* fp; + if ((fp = fopen("test.txt", "r")) == NULL) { + printf("File failed to open......\n"); + system("pause"); + return 0; + } + else { + printf("打开文件成功\n"); + } + + nodeList* q[1000]; + int i = 0; + q[i] = (nodeList*)malloc(sizeof(nodeList)); + while (fscanf(fp, "%s %d", q[i]->name, &q[i]->num) != EOF) { //逐行读取文件 + temp->next = q[i]; + temp = temp->next; + temp->next = NULL; + i++; + q[i] = (nodeList*)malloc(sizeof(nodeList)); + } + for (int x = 0; x <= i; x++) + free(q[i]); + fclose(fp); + printf("读取成功\n"); + printf("即将打印仓库......\n"); + Sleep(1500); + showList(p); + return p; +} From 47655df72ddeb04e4e223c5c6c36a94d5d07bdb7 Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Wed, 7 Apr 2021 00:42:22 +0800 Subject: [PATCH 20/21] pushBox --- level1/p10_pushBoxes/function.c | 250 ++++++++++++++++++++++++++++++++ level1/p10_pushBoxes/function.h | 22 +++ level1/p10_pushBoxes/main.c | 52 +++++++ level1/p10_pushBoxes/map.txt | 27 ++++ 4 files changed, 351 insertions(+) create mode 100644 level1/p10_pushBoxes/function.c create mode 100644 level1/p10_pushBoxes/function.h create mode 100644 level1/p10_pushBoxes/main.c create mode 100644 level1/p10_pushBoxes/map.txt diff --git a/level1/p10_pushBoxes/function.c b/level1/p10_pushBoxes/function.c new file mode 100644 index 00000000..8121c3ca --- /dev/null +++ b/level1/p10_pushBoxes/function.c @@ -0,0 +1,250 @@ +#include +#include +#include +#include "function.h" + +//开始游戏 +void start(int map[][L],int nmap) { + int num,goal = 0; + int score = 0; + int bestscore = map[L][0]; + for(int i=0;i0;num--) { + for (int i = 0; i < L; i++) { + fscanf(fp, "%d %d %d %d %d %d %d %d", &map[i][0], &map[i][1], &map[i][2], &map[i][3], &map[i][4], + &map[i][5], &map[i][6], &map[i][7]); + } + fscanf(fp,"%d",&map[L][0]); + } + fclose(fp); + return map; +} + +//游戏说明 +void explain(){ + system("cls"); + printf("欢迎来到推箱子游戏......\n"); + printf("本游戏共有三关\n"); + printf("使用w上移,适用s下移\n"); + printf("使用a左移,使用d右移\n"); + printf("游戏目的是将所有的箱子推到对应的目的地上\n"); + printf("游戏过程中会随时记录你的步数,希望你能够打破记录!\n"); + printf("注意:在游戏中随时可以按q退出游戏,回到主界面\n"); + system("pause"); +} + +void write(int bestscore,int num){ + int (*map)[L]; + map=(int(*)[L])malloc((3*L+3)*sizeof(int[L])); + FILE* fp; + //现读取原有文件,为更新最佳成绩的值做好准备 + if ((fp = fopen("map.txt", "r")) == NULL) { + printf("File failed to open......\n"); + system("pause"); + exit(0); + } + for (int i = 0; i < 3*L+3; i++) { + if(i==L||i==2*L+1||i==3*L+2) + fscanf(fp,"%d",&map[i][0]); + else + fscanf(fp, "%d %d %d %d %d %d %d %d", &map[i][0], &map[i][1], &map[i][2], &map[i][3], &map[i][4], + &map[i][5], &map[i][6], &map[i][7]); + } + fclose(fp); + + map[num*L+num-1][0] = bestscore; //更新最佳成绩 + //重新写入文件以更新最佳成绩 + if ((fp = fopen("map.txt", "w")) == NULL) { + printf("File failed to open......\n"); + system("pause"); + exit(0); + } + for(int i = 0;i< 3*L+3;i++){ + if(i==L||i==2*L+1||i==3*L+2) + fprintf(fp,"%d\n",map[i][0]); + else + fprintf(fp, "%d %d %d %d %d %d %d %d\n", map[i][0], map[i][1], map[i][2], map[i][3], map[i][4], + map[i][5], map[i][6], map[i][7]); + } + fclose(fp); +} + + diff --git a/level1/p10_pushBoxes/function.h b/level1/p10_pushBoxes/function.h new file mode 100644 index 00000000..ad753919 --- /dev/null +++ b/level1/p10_pushBoxes/function.h @@ -0,0 +1,22 @@ +#ifndef __FUNCTION_H__ +#define __FUNCTION_H__ + +#define ROUTE 0 //路径 +#define WALL 1 //墙 +#define PLAYER 2 //玩家 +#define BOX 3 //箱子 +#define DESTINATION 4 //终点 +#define FINSHED 7// 表示已完成的箱子 +#define PFINSHED 6 // 人加终点 +#define L 8 //规定的地图大小(文件中的地图也将按这个尺寸编写) + +void start(int map[][L],int nmap); +void print(int map[][L],int score,int bestscore); +int (*tuidong(int map[][L]))[L]; +int (*fileReader(int num))[L]; +int check(int map[][L]); +void explain(); +void write(int bestscore,int num); + +#endif + diff --git a/level1/p10_pushBoxes/main.c b/level1/p10_pushBoxes/main.c new file mode 100644 index 00000000..9ffe50da --- /dev/null +++ b/level1/p10_pushBoxes/main.c @@ -0,0 +1,52 @@ +/*推箱子小游戏,经测试可以正常运行, +1. 将p09迷宫游戏改造为“推箱子”游戏; +1. 在地图中增加箱子、箱子目标位置等图形; +1. 当玩家将所有箱子归位,则显示玩家赢得了游戏; +1. 按玩家走动步数记分; +1. 设计多个关卡,每一关的地图从文件中读取,玩家每关的分数记录到文件中; +注意:运行前请将各个文件放到同一工程目录下, +若不能正常运行,请将读写文件的路径改为绝对路径*/ + +#include +#include +#include +#include "function.h" + +int main() { + int(*map)[L]; + char c; + while (1) { + system("cls"); + printf("---------------------\n"); + printf("---欢迎来到推箱子小游戏---\n"); + printf("----1. 关卡1 -----\n"); + printf("----2. 关卡2 -----\n"); + printf("----3. 关卡3 -----\n"); + printf("----4. 游戏说明---\n"); + printf("----0. 退出游戏 -----\n"); + printf("--------------------\n"); + c = _getch(); + switch (c) { + case '1': + map= fileReader(1); + start(map,1); + break; + case '2': + map = fileReader(2); + start(map,2); + break; + case '3': + map = fileReader(3); + start(map,3); + break; + case '4': + explain(); + break; + case '0': + printf("欢迎下次继续游玩........\n"); + Sleep(1500); + exit(0); + } + } +} + diff --git a/level1/p10_pushBoxes/map.txt b/level1/p10_pushBoxes/map.txt new file mode 100644 index 00000000..7abdc5ba --- /dev/null +++ b/level1/p10_pushBoxes/map.txt @@ -0,0 +1,27 @@ +0 0 1 1 1 0 0 0 +0 0 1 4 1 0 0 0 +0 0 1 0 1 1 1 1 +1 1 1 3 0 3 4 1 +1 4 0 3 2 1 1 1 +1 1 1 1 3 1 0 0 +0 0 0 1 4 1 0 0 +0 0 0 1 1 1 0 0 +100 +1 1 1 1 1 1 1 0 +1 4 4 3 4 4 1 0 +1 4 4 1 4 4 1 0 +1 0 3 3 3 0 1 0 +1 0 0 3 0 0 1 0 +1 0 3 3 3 0 1 0 +1 0 0 1 2 0 1 0 +1 1 1 1 1 1 1 0 +100 +1 1 1 1 1 1 1 0 +1 4 0 4 0 4 1 0 +1 0 3 3 3 0 1 0 +1 4 3 2 3 4 1 0 +1 0 3 3 3 0 1 0 +1 4 0 4 0 4 1 0 +1 1 1 1 1 1 1 0 +0 0 0 0 0 0 0 0 +100 \ No newline at end of file From af2d9218358247687c11ce8eeb2043e8786cf2cb Mon Sep 17 00:00:00 2001 From: Crazycat-tj <2321169422@qq.com> Date: Wed, 16 Jun 2021 13:02:22 +0800 Subject: [PATCH 21/21] go-bang --- "\345\256\236\351\252\214/assist.cpp" | 84 +++ "\345\256\236\351\252\214/assist.h" | 45 ++ "\345\256\236\351\252\214/dPlayers.cpp" | 58 ++ "\345\256\236\351\252\214/dPlayers.h" | 9 + "\345\256\236\351\252\214/hum_VS_AI.cpp" | 595 ++++++++++++++++++++ "\345\256\236\351\252\214/hum_VS_AI.h" | 18 + "\345\256\236\351\252\214/initmap.cpp" | 81 +++ "\345\256\236\351\252\214/initmap.h" | 10 + "\345\256\236\351\252\214/menu.cpp" | 69 +++ "\345\256\236\351\252\214/menu.h" | 11 + "\345\256\236\351\252\214/resource.h" | 14 + "\345\256\236\351\252\214/resource1.h" | 14 + "\345\256\236\351\252\214/\346\272\220.cpp" | 7 + 13 files changed, 1015 insertions(+) create mode 100644 "\345\256\236\351\252\214/assist.cpp" create mode 100644 "\345\256\236\351\252\214/assist.h" create mode 100644 "\345\256\236\351\252\214/dPlayers.cpp" create mode 100644 "\345\256\236\351\252\214/dPlayers.h" create mode 100644 "\345\256\236\351\252\214/hum_VS_AI.cpp" create mode 100644 "\345\256\236\351\252\214/hum_VS_AI.h" create mode 100644 "\345\256\236\351\252\214/initmap.cpp" create mode 100644 "\345\256\236\351\252\214/initmap.h" create mode 100644 "\345\256\236\351\252\214/menu.cpp" create mode 100644 "\345\256\236\351\252\214/menu.h" create mode 100644 "\345\256\236\351\252\214/resource.h" create mode 100644 "\345\256\236\351\252\214/resource1.h" create mode 100644 "\345\256\236\351\252\214/\346\272\220.cpp" diff --git "a/\345\256\236\351\252\214/assist.cpp" "b/\345\256\236\351\252\214/assist.cpp" new file mode 100644 index 00000000..8ec70743 --- /dev/null +++ "b/\345\256\236\351\252\214/assist.cpp" @@ -0,0 +1,84 @@ +#include "assist.h" + +int gBoard[M_SIZE][M_SIZE]; //棋盘 + +/******************************************* +Function: is_win + +Description: 从当前下棋位置判断下棋方是否已经赢了 + +Input: x->int 棋子坐标 + y->int 棋子坐标 + chessColor->int 当前下棋方棋子的颜色 + +Return: TRUE赢了;FALSE没赢 +********************************************/ +int is_win(int x, int y, int chessColor) { + int i, j, n1 = 0, n2 = 0; + for (i = x, j = y + 1; j < M_SIZE; j++) { //往右累加,计算右边棋子个数 + if (gBoard[i][j] == chessColor) + n1++; + else + break; + } + for (i = x, j = y; j >= 0; j--) { //往左累加,计算左边棋子个数 + if (gBoard[i][j] == chessColor) + n2++; + else + break; + } + if (n1 + n2 >= 5) + return TRUE; + n1 = 0; + n2 = 0; + for (i = x, j = y; i >= 0; i--) { //向上检索 + if (gBoard[i][j] == chessColor) + n1++; + else + break; + } + for (i = x + 1, j = y; i < M_SIZE; i++) { //向下检索 + if (gBoard[i][j] == chessColor) + n2++; + else + break; + } + if (n1 + n2 >= 5) + return TRUE; + n1 = 0; + n2 = 0; + for (i = x - 1, j = y + 1; i >= 0 && j < M_SIZE; i--, j++) { //向右上检索 + if (gBoard[i][j] == chessColor) + n1++; + else + break; + } + for (i = x, j = y; i < M_SIZE && j >= 0; i++, j--) { //向左下检索 + if (gBoard[i][j] == chessColor) + n2++; + else + break; + } + if (n1 + n2 >= 5) + return TRUE; + n1 = 0; + n2 = 0; + for (i = x, j = y; i >= 0 && j >= 0; i--, j--) {//向左上检索 + if (gBoard[i][j] == chessColor) + n1++; + else + break; + } + for (i = x + 1, j = y + 1; i < M_SIZE && j < M_SIZE; i++, j++) {//向右下检索 + if (gBoard[i][j] == chessColor) + n2++; + else + break; + } + if (n1 + n2 >= 5) + return TRUE; + return FALSE; +} + + + diff --git "a/\345\256\236\351\252\214/assist.h" "b/\345\256\236\351\252\214/assist.h" new file mode 100644 index 00000000..5b5a42d2 --- /dev/null +++ "b/\345\256\236\351\252\214/assist.h" @@ -0,0 +1,45 @@ +#ifndef _ASSIST_H +#define _ASSIST_H + +#include +#include +#include +#include +#include + +#define M_SIZE 15 //棋盘大小为 15 * 15 + +//棋子状态颜色 +#define SPACE 0 //空 +#define White 1 //白子 +#define Black 2 //黑子 +#define AIChessColor 1 +#define humChessColor 2 + +extern int gBoard[M_SIZE][M_SIZE]; + +//分数规定 +#define WIN5 100000 //5连 +#define ALIVE4 10000 //活四 +#define ALIVE3 1000 //活三 +#define DIE4 1000 //死四 +#define ALIVE2 100 //活2 +#define DIE3 100 //死3 +#define DIE2 10 //死2 +#define ALIVE1 10 //活1 + +//棋子 +typedef struct chess_s { + int x = 0; + int y = 0; +}chess_t; + +//空子的序列 +typedef struct chess_queue_s { + chess_t chess[M_SIZE * M_SIZE]; + int len = 0; +}chess_queue; + +int is_win(int x, int y, int chessColor); + +#endif \ No newline at end of file diff --git "a/\345\256\236\351\252\214/dPlayers.cpp" "b/\345\256\236\351\252\214/dPlayers.cpp" new file mode 100644 index 00000000..4879ab78 --- /dev/null +++ "b/\345\256\236\351\252\214/dPlayers.cpp" @@ -0,0 +1,58 @@ +#include "dPlayers.h" + +/******************************************* +Function: d_Players + +Description: 人人对战主函数,核心功能就是对当前棋手的鼠标事件做出响应,每一次下棋后都检测是否五子连珠。 + Ps:由于正式比赛中总是黑棋先下,因此初始化棋手为黑方,之后依次转换 + +Input: NULL + +Return: 胜利方棋子颜色 +********************************************/ +int dPlayers() { + int x, y, i, j, is_find = 0; //is_find用于检测是否找到了鼠标点击时对应棋盘上的位置 + int player = Black; //黑子先下棋 + MOUSEMSG mouse; + chess_t chess; + RECT r = { 480,250,580,300 }; + LOGFONT f; + gettextstyle(&f); // 获取当前字体设置 + f.lfHeight = 20; // 设置字体高度为20 + settextstyle(&f); // 设置字体样式 + while (true) { + if (player == Black) + drawtext(_T("黑方下棋"), &r, DT_CENTER); //提示当前回合是黑色棋子下棋 + else + drawtext(_T("白方下棋"), &r, DT_CENTER); //提示当前回合是白色棋子下棋 + mouse = GetMouseMsg(); //获取一个鼠标消息 + if (mouse.uMsg == WM_LBUTTONDOWN) { //判断鼠标左键是否按下 + for (i = 0; i < 15 && is_find != 1; i++) { + for (j = 0; j < 15 && is_find != 1; j++) { + if (abs(mouse.x - (112 + i * 25)) < 12 && abs(mouse.y - (112 + j * 25)) < 12) {//寻找距离鼠标点击最近的点 + x = 112 + i * 25; //对应点的横坐标 + y = 112 + j * 25; //对应点的纵坐标 + is_find = 1; + } + } + } + if (is_find == 1) { + i--; //由于跳出for循换的时候++了,因此需要-1抵消这个误差 + j--; + if(gBoard[j][i]==SPACE) { + if (player == Black) + setfillcolor(RGB(0, 0, 0)); //设置填充颜色为黑色 + else + setfillcolor(RGB(255, 255, 255)); //设置填充颜色为白色 + solidcircle(x, y, 10); //绘制棋子 + gBoard[j][i] = player; //棋盘记录当前玩家所下的棋子 + clearrectangle(480, 250, 580, 300); + if (is_win(j, i, player)) //判断玩家是否已经胜利 + return player; + player = player % 2 + 1; //换手 + } + } + is_find = 0; + } + } +} \ No newline at end of file diff --git "a/\345\256\236\351\252\214/dPlayers.h" "b/\345\256\236\351\252\214/dPlayers.h" new file mode 100644 index 00000000..21fa6ce6 --- /dev/null +++ "b/\345\256\236\351\252\214/dPlayers.h" @@ -0,0 +1,9 @@ +#ifndef _DPLAYERS_H +#define _DPLAYERS_H + +#include "assist.h" +#include "initmap.h" + +int dPlayers(); //人人对战 + +#endif diff --git "a/\345\256\236\351\252\214/hum_VS_AI.cpp" "b/\345\256\236\351\252\214/hum_VS_AI.cpp" new file mode 100644 index 00000000..8f3b4541 --- /dev/null +++ "b/\345\256\236\351\252\214/hum_VS_AI.cpp" @@ -0,0 +1,595 @@ +#include "hum_VS_AI.h" + +/************************************************* +Function: hum_VS_AI + +Description: 人机对战辅助函数,主要用于响应玩家的鼠标事件,同时在每一次玩家下棋后,调用AI_turn函数让AI下棋。 + +Input: null + +Return: 返回游戏胜利方 +********************************************/ +int hum_VS_AI() { + int x, y, i, j, is_find = 0; //is_find用于检测是否找到了鼠标点击时对应棋盘上的位置 + int is_first = 1; + MOUSEMSG mouse; + chess_t chess; + RECT r = { 480,250,580,300 }; + LOGFONT f; + gettextstyle(&f); // 获取当前字体设置 + f.lfHeight = 20; // 设置字体高度为 20 + settextstyle(&f); // 设置字体样式 + setfillcolor(RGB(228, 121, 21)); //设置按钮颜色 + RECT R = { 480, 150, 580, 200 }; + fillrectangle(480, 150, 580, 200); + drawtext(_T("玩家先手"), &R, DT_CENTER | DT_VCENTER | DT_SINGLELINE); + while (true) { + drawtext(_T("你的回合"), &r, DT_CENTER); // 对应区域居中打印文字 + mouse = GetMouseMsg(); //获取一个鼠标消息 + if (mouse.uMsg == WM_LBUTTONDOWN) { //判断鼠标左键是否按下 + for (i = 0; i < 15 && is_find != 1; i++) { + for (j = 0; j < 15 && is_find != 1; j++) { + if (abs(mouse.x - (112 + i * 25)) < 12 && abs(mouse.y - (112 + j * 25)) < 12) {//寻找距离鼠标点击最近的点 + x = 112 + i * 25; + y = 112 + j * 25; + is_find = 1; + } + } + } + if (is_find == 0 && is_first == 1) { + if (abs(mouse.x - 530) < 50 && abs(mouse.y - 175) < 25) { + RECT R = { 480, 150, 580, 200 }; + fillrectangle(480, 150, 580, 200); + drawtext(_T("AI先手"), &R, DT_CENTER | DT_VCENTER | DT_SINGLELINE); + chess.x = 7, chess.y = 7; + gBoard[chess.x][chess.y] = AIChessColor; + i = 112 + 25 * 7; + j = 112 + 25 * 7; + setfillcolor(RGB(255, 255, 255)); + solidcircle(i, j, 10); //绘制白色棋子(代表AI) + setfillcolor(RGB(255, 0, 0)); + solidcircle(i, j, 2); //绘制下棋示意点 + is_first = 0; + } + } + if (is_find == 1) { + i--; //由于跳出for循换的时候++了,因此需要-1抵消这个误差 + j--; + if(gBoard[j][i]==SPACE) { //棋盘上对应位置没有棋子 + if (!is_first) { //消除标记点 + setfillcolor(RGB(255, 255, 255)); + solidcircle(25 * chess.y + 112, 25 * chess.x + 112, 10); + } + setfillcolor(RGB(0, 0, 0)); + solidcircle(x, y, 10); //绘制黑色棋子(代表玩家) + gBoard[j][i] = humChessColor; + HRGN del = CreateRectRgn(480, 250, 580, 300); //删除文字区域的文字 + setcliprgn(del); + DeleteObject(del); + clearcliprgn(); + setcliprgn(NULL); + if (is_win(j, i, humChessColor)) { //判断玩家是否已经获胜 + return humChessColor; + } + chess = AI_turn();//AI下棋 + if (is_win(chess.x, chess.y, AIChessColor)) { //判断AI是否已经获胜 + return AIChessColor; + } + is_first = 0; + } + is_find = 0; + } + } + } +} + +/************************************************* +Function:AI_turn + +Description: 轮到AI下棋,调用chess_AI_Negmax_Alphabeta函数获取AI下棋的决策坐标 + 用于绘制提示信息以及棋子、示意点 + +Input: null + +Return: 返回每一次AI决策下棋的位置信息 +********************************************/ +chess_t AI_turn() { + RECT r = { 480,250,580,300 }; //打印区域 + drawtext(_T("轮到AI下棋"), &r, DT_CENTER); // 对应区域居中打印文字 + chess_t chess; + chess_AI_Negmax_Alphabeta(&chess); //获取AI决策下棋的位置 + int i = 112 + 25 * chess.y, j = 112 + 25 * chess.x; + setfillcolor(RGB(255, 255, 255)); + solidcircle(i, j, 10); //绘制白色棋子(代表AI) + setfillcolor(RGB(255, 0, 0)); + solidcircle(i, j, 2); //绘制下棋示意点 + gBoard[chess.x][chess.y] = AIChessColor; // 棋盘记录下棋信息 + HRGN del = CreateRectRgn(480, 250, 580, 300); //删除文字区域文字 + setcliprgn(del); + DeleteObject(del); + clearcliprgn(); + setcliprgn(NULL); + return chess; +} + +/************************************************* +Function: chess_AI_Negmax_Alphabeta + +Description: 轮到AI下棋,在每一个可以下棋的位置(经初步筛选)中决策出分数最高的位置 + +Input: 虽然是函数的输入,但主要用于记录决策出来的最佳坐标,作用更接近于返回值。 + +Return: NULL +********************************************/ +void chess_AI_Negmax_Alphabeta(chess_t* chess) { + int i, k = 0; + int x, y, tmp, depth = 4; //这里可以更改搜索的深度 + int best = -WIN5; //找到的最高分,初始值赋一个最小值 + chess_queue option_queue; //待选的空子队列 + chess_queue sure_queue; //最合适的下子位置 + option_queue = generate_point(AIChessColor); //寻找可以下子的地方 + + for (i = 1; i <= option_queue.len; i++) { //一个一个子轮着试一遍 + x = option_queue.chess[i].x; + y = option_queue.chess[i].y; + gBoard[x][y] = AIChessColor; //尝试下一个子 + tmp = negaMax_alphabeta(depth, option_queue.chess[i], -WIN5, WIN5, humChessColor); //获得此位置的分数 + if (tmp == best) { //找到一个和当前最高分一样的分数,保存下来 + sure_queue.chess[k].x = option_queue.chess[i].x; + sure_queue.chess[k].y = option_queue.chess[i].y; + sure_queue.len = k + 1; + k++; + } + else if (tmp > best) { //找到一个比当前最高分更高的分数,刷新最高值 + best = tmp; + k = 0; + sure_queue.len = 1; + sure_queue.chess[k].x = option_queue.chess[i].x; + sure_queue.chess[k].y = option_queue.chess[i].y; + k++; + } + gBoard[x][y] = SPACE; //撤销选择 + } + if (best == -WIN5) { //有可能任意位置都要比最低分要低,即当AI必输时,sure_queue可能没有记录,此时随机选择一个点下棋 + k = (int)(rand() % option_queue.len); + chess->x = option_queue.chess[k].x; + chess->y = option_queue.chess[k].y; + } + else { + k = (int)(rand() % sure_queue.len); //如果有多个最高分数,随机选择一个 + chess->x = sure_queue.chess[k].x; + chess->y = sure_queue.chess[k].y; + } +} + +/************************************************* +Function: negaMax_alphabeta + +Description: 核心函数,负极大值搜索,用深度优先的思想搜索给定深度下当前位置的预估分数,结合alpha_beta剪枝 + +Input: int depth : 搜索深度 + chess_t chess : 上一步尝试落子的棋子 + int alpha : 用于剪枝 + int beta : 用于剪枝 + int player:本轮对应玩家 + +Return: 返回搜索得到的预估分数 +********************************************/ +int negaMax_alphabeta(int depth, chess_t chess, int alpha, int beta, int player) { + int res = evaluate_board(); //当前棋盘分数(AI-player) + int x, y, tempScore; + if ((depth <= 0) || (is_win(chess.x, chess.y, player % 2 + 1))) //如果已经达到目标深度,或上一步对方已经胜利 + return res; + chess_queue queue; + queue = generate_point(player); //记录当前可以下子的位置 + + for (int i = 1; i <= queue.len; i++) { //这里就是DFS的过程 + x = queue.chess[i].x; + y = queue.chess[i].y; + gBoard[x][y] = player; //做出选择 + tempScore = -negaMax_alphabeta(depth - 1, queue.chess[i], -beta, -alpha, player % 2 + 1); + gBoard[x][y] = SPACE; //撤销选择 + if (tempScore > alpha) + alpha = tempScore; + if (alpha >= beta) + break; + } + return alpha; +} + +/************************************************* +Function: evaluate_board + +Description: 将棋盘上的位置分解为由行、列、斜线组成的一维数组. + 利用count_score函数遍历一维数组,分别结算玩家和AI的分数。 + +Input: null + +Return: 当前棋局AI总分与玩家总分的差值 +********************************************/ +int evaluate_board() { + int AIScore = 0, humScore = 0; + int i, j, x, y, n[M_SIZE]; + memset(n, 0, sizeof(n)); + //计算所有横排的分数之和 + for (i = 0; i < M_SIZE; i++) { + for (j = 0; j < M_SIZE; j++) + n[j] = gBoard[i][j]; + AIScore += count_score(n, AIChessColor); + humScore += count_score(n, humChessColor); + memset(n, 0, sizeof(n)); + } + //计算所有纵排的分数之和 + for (j = 0; j < M_SIZE; j++) { + for (i = 0; i < M_SIZE; i++) + n[i] = gBoard[i][j]; + AIScore += count_score(n, AIChessColor); + humScore += count_score(n, humChessColor); + memset(n, 0, sizeof(n)); + } + //计算所有下半正斜线(\)的分数之和 + for (i = 0; i < M_SIZE; i++) { + for (x = i, y = 0; x < M_SIZE && y < M_SIZE; x++, y++) + n[y] = gBoard[x][y]; + AIScore += count_score(n, AIChessColor); + humScore += count_score(n, humChessColor); + memset(n, 0, sizeof(n)); + } + //计算所有上半正斜线的分数之和 + for (j = 1; j < M_SIZE; j++) { + for (x = 0, y = j; y < M_SIZE && x < M_SIZE; x++, y++) + n[x] = gBoard[x][y]; + AIScore += count_score(n, AIChessColor); + humScore += count_score(n, humChessColor); + memset(n, 0, sizeof(n)); + } + //计算所有上半反斜线(/)的分数之和 + for (i = 0; i < M_SIZE; i++) { + for (y = i, x = 0; y >= 0 && x < M_SIZE; y--, x++) + n[x] = gBoard[x][y]; + AIScore += count_score(n, AIChessColor); + humScore += count_score(n, humChessColor); + memset(n, 0, sizeof(n)); + } + //计算所有下半反斜线的分数之和 + for (j = 1; j < M_SIZE; j++) { + for (y = j, x = M_SIZE - 1; y < M_SIZE && x >= 0; y++, x--) + n[y - j] = gBoard[x][y]; + AIScore += count_score(n, AIChessColor); + humScore += count_score(n, humChessColor); + memset(n, 0, sizeof(n)); + } + return AIScore - humScore; //返回 AI-人 的分数 +} + +/******************************************* +Function: generate_point + +Description: 寻找当前棋局可以下棋且对棋手有利的位置。 + 要求是位置为空且一步之内有邻居(要求有邻居是为了使下棋的地方更接近现实) + Ps:为了便于alpha-beta剪枝,使用了启发式搜索算法,若为杀棋则直接返回,否则进行大致的排序 。 + +Input: int player : 当前回合的棋手 + +Return: 返回当前棋局可以落子的位置结构体(结构体中包含一个数组,记录各点位置信息) +********************************************/ +chess_queue generate_point(int player) { + int i, j = 0; + int length; + chess_queue rivalFive; //对方成5 + chess_queue ComFour; //本方活4 + chess_queue rivalFour; //对方活四 + chess_queue ComDoubleThree; //本方双活三 + chess_queue rivalDoubleThree; //对方双活三 + chess_queue ComThree; //本方活三 + chess_queue rivalThree; //对方活三 + chess_queue ComTwo; //本方活二 + chess_queue rivalTwo; //对方活二 + chess_queue others; //其余 + chess_queue queue; //用于函数返回 + + for (i = 0; i < M_SIZE; i++) { + for (j = 0; j < M_SIZE; j++) { + chess_t p; + p.x = i, p.y = j; + if ((gBoard[i][j] == SPACE) && hasNeighbors(i, j)) {//有邻居的空子,做为可下子的队列 + int ComScore = evaluatePoint(player, p); //本方分数 + int rivalScore = evaluatePoint(player % 2 + 1, p); //对方分数 + + if (ComScore >= WIN5) { //本方成5 + queue.len++; + queue.chess[queue.len] = p; + return queue; //必杀棋,直接返回 + } + else if (rivalScore >= WIN5) { //对方成5 + rivalFive.len++; + rivalFive.chess[rivalFive.len] = p; //对方的必杀棋,必须阻挡 + } + else if (ComScore >= ALIVE4) { //本方活四 + ComFour.len++; + ComFour.chess[ComFour.len] = p; + } + else if (rivalScore >= ALIVE4) { //对方活四 + rivalFour.len++; + rivalFour.chess[rivalFour.len] = p; + } + else if (ComScore >= 2 * ALIVE3) { //本方双活三 + ComDoubleThree.len++; + ComDoubleThree.chess[ComDoubleThree.len] = p; + } + else if (rivalScore >= 2 * ALIVE3) { //对方活三 + rivalDoubleThree.len++; + rivalDoubleThree.chess[rivalDoubleThree.len] = p; + } + else if (ComScore >= ALIVE3) { //本方活三 + ComThree.len++; + ComThree.chess[ComThree.len] = p; + } + else if (rivalScore >= ALIVE3) { //对方活三 + rivalThree.len++; + rivalThree.chess[rivalThree.len] = p; + } + else if (ComScore >= ALIVE2) { //本方活二 + ComTwo.len++; + ComTwo.chess[ComTwo.len] = p; + } + else if (rivalScore >= ALIVE2) { //对方活二 + rivalTwo.len++; + rivalTwo.chess[rivalTwo.len] = p; + } + else { //其余 + others.len++; + others.chess[others.len] = p; + } + } + } + } + if (rivalFive.len > 0) { + queue = rivalFive; + return queue; + }else if (ComFour.len > 0 || rivalFour.len > 0) { + queue = ComFour; + length = queue.len; + for (int x = 1; x <= rivalFour.len; x++) { + queue.chess[length + x] = rivalFour.chess[x]; + queue.len++; + } + return queue; + }else if (ComDoubleThree.len > 0 || rivalDoubleThree.len > 0) { + queue = ComDoubleThree; + length = queue.len; + for (int x = 1; x <= rivalDoubleThree.len; x++) { + queue.chess[length + x] = rivalDoubleThree.chess[x]; + queue.len++; + } + return queue; + } + //以上为杀棋,直接返回 + //以下非必杀,因此进行一个大致的排序,按顺序存放进queue + queue = ComThree; + length = queue.len; + for (int x = 1; x <= rivalThree.len; x++) { + queue.chess[length + x] = rivalThree.chess[x]; + queue.len++; + } + length = queue.len; + for (int x = 1; x <= ComTwo.len; x++) { + queue.chess[length + x] = ComTwo.chess[x]; + queue.len++; + } + length = queue.len; + for (int x = 1; x <= rivalTwo.len; x++) { + queue.chess[length + x] = rivalTwo.chess[x]; + queue.len++; + } + length = queue.len; + for (int x = 1; x <= others.len; x++) { + queue.chess[length + x] = others.chess[x]; + queue.len++; + } + return queue; +} + +/******************************************* +Function: hasNeighbors + +Description: 判断当前位置 (x,y) s步之内是否有子(不管是对方的子还是己方的子) + +Input: x->int 横坐标 + y->int 纵坐标 + +Return: TRUE->有子 ;FALSE->无子 +********************************************/ +int hasNeighbors(int x, int y) { + int s = 1; + int i, j; + for (i = (x - s > 0 ? x - s : 0); i <= x + s && i < M_SIZE; i++) + for (j = (y - s > 0 ? y - s : 0); j <= y + s && j < M_SIZE; j++) + if ((i != x || j != y) && gBoard[i][j] != SPACE) + return TRUE; + return FALSE; +} + + +/******************************************* +Function: evaluatePoint + +Description: 评估某一点对应的分数。注:此函数主要用于启发式搜索算法,判断该点的类型(如活三、冲四等) + +Input: int chessColor //棋子颜色 + chess_t chess //棋子坐标 + +Return: 评估得到的分数 +********************************************/ +int evaluatePoint(int chessColor, chess_t chess) { + int x = chess.x, y = chess.y; + int i, j, number = 0, empty = 2, score = 0; + gBoard[x][y] = chessColor; + for (i = x, j = y + 1; j < M_SIZE; j++) { //往右累加,计算右边棋子个数 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) //对方棋子 + empty--; + break; + } + } + for (i = x, j = y; j >= 0; j--) { //往左累加,计算左边棋子个数 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) + empty--; + break; + } + } + score += score_table(number, empty); + + number = 0, empty = 2; + for (i = x, j = y; i >= 0; i--) { //向上检索 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) + empty--; + break; + } + } + for (i = x + 1, j = y; i < M_SIZE; i++) { //向下检索 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) + empty--; + break; + } + } + score += score_table(number, empty); + + number = 0, empty = 2; + for (i = x - 1, j = y + 1; i >= 0 && j < M_SIZE; i--, j++) { //向右上检索 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) + empty--; + break; + } + } + for (i = x, j = y; i < M_SIZE && j >= 0; i++, j--) { //向左下检索 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) + empty--; + break; + } + } + score += score_table(number, empty); + + number = 0, empty = 2; + for (i = x, j = y; i >= 0 && j >= 0; i--, j--) {//向左上检索 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) + empty--; + break; + } + } + for (i = x + 1, j = y + 1; i < M_SIZE && j < M_SIZE; i++, j++) {//向右下检索 + if (gBoard[i][j] == chessColor) + number++; + else { + if (gBoard[i][j] != SPACE) + empty--; + break; + } + } + score += score_table(number, empty); + gBoard[x][y] = SPACE; + return score; +} + + +/************************************************* +Function: count_score + +Description: 计算这一行、列、斜线的连子数、空位数,每找到一串连子就根据调用score_table函数计算分数,最后求出分数总和,代表该行、列、斜线的分数。 + +Input: int n[] : 代表每一行、列、斜线的一维数组 + int chessColor : 本回合棋手的棋子颜色 + +Return: 这一组(一维数组)的分数总和 +********************************************/ +int count_score(int n[], int chessColor) { + int i = 1; //n[0]在下面作为初始点单独计算 + int empty = 0; //空的位子 + int number = 0; //连子的个数 + int scoretmp = 0; //计算分数总和 + + if (n[0] == SPACE) //位置为空 + empty++; + else if (n[0] == chessColor) //本方棋子 + number++; + + while (i < M_SIZE) { + if (n[i] == chessColor) //本方棋子 + number++; + else if (n[i] == SPACE) { //位置为空,分两种情况来讨论 + if (number == 0) //上一个位置也为空 + empty = 1; + else { //上一个位置为本方棋子 + scoretmp += score_table(number, empty + 1); + empty = 1; + number = 0; + } + } + else {//对方棋子 + scoretmp += score_table(number, empty); + empty = 0; + number = 0; + } + i++; + } + scoretmp += score_table(number, empty); + return scoretmp; //返回本组分数总和 +} + +/************************************************* +Function: score_table + +Description: 根据连子个数和两端的空子个数计算分数 + +Input: number->连子的个数 + empty->空子的个数 + +Return: 分数 +********************************************/ +int score_table(char number, char empty) { + if (number >= 5) { + return WIN5; + } + else if (number == 4) { + if (empty == 2) + return ALIVE4; + else if (empty == 1) + return DIE4; + } + else if (number == 3) { + if (empty == 2) + return ALIVE3; + else if (empty == 1) + return DIE3; + } + else if (number == 2) { + if (empty == 2) + return ALIVE2; + else if (empty == 1) + return DIE2; + } + else if (number == 1 && empty == 2) + return ALIVE1; + else + return 0; +} \ No newline at end of file diff --git "a/\345\256\236\351\252\214/hum_VS_AI.h" "b/\345\256\236\351\252\214/hum_VS_AI.h" new file mode 100644 index 00000000..ece23d06 --- /dev/null +++ "b/\345\256\236\351\252\214/hum_VS_AI.h" @@ -0,0 +1,18 @@ +#ifndef _HUM_VS_AI_H +#define _HUM_VS_AI_H + +#include "initmap.h" +#include "assist.h" + +int hum_VS_AI(); +int hasNeighbors(int x, int y); +int negaMax_alphabeta(int depth, chess_t chess, int alpha, int beta, int player); +void chess_AI_Negmax_Alphabeta(chess_t* chess); +int evaluatePoint(int chessColor, chess_t chess); +int count_score(int n[], int chessColor); +int score_table(char number, char empty); +int evaluate_board(); +chess_queue generate_point(int player); +chess_t AI_turn(); + +#endif diff --git "a/\345\256\236\351\252\214/initmap.cpp" "b/\345\256\236\351\252\214/initmap.cpp" new file mode 100644 index 00000000..da419570 --- /dev/null +++ "b/\345\256\236\351\252\214/initmap.cpp" @@ -0,0 +1,81 @@ +#include "initmap.h" + +/************************************************* +Function: initmap + +Description: 基于EasyX图形库,用于初始化绘制棋盘,包括棋盘、坐标轴、天元点 + +Input: null + +Return: null +********************************************/ +void initmap() { + char letter[] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O' }; + TCHAR s[5];//用于打印棋盘边沿的数字 + LOGFONT f; + gettextstyle(&f); // 获取当前字体设置 + f.lfHeight = 20; // 设置字体高度为20 + settextstyle(&f); // 设置字体样式 + cleardevice(); // 应用背景色 + setlinestyle(PS_SOLID, 1); //画实线 宽度2 + for (int i = 0; i < 13; i++) { + line(112, 137 + i * 25, 462, 137 + i * 25); //画棋盘上的横线 + line(137 + i * 25, 112, 137 + i * 25, 462); //画棋盘上的竖线 + } + for (int i = 0; i < 15; i++) { + RECT r = { 87,100 + i * 25,112,125 + 25 * i }; //打印数字的区域 + RECT m = { 99.5 + i * 25,462,124 + i * 25,487 }; //打印字母的区域 + _stprintf(s, _T("%d"), i + 1); //将数字转换成字符串 + drawtext(s, &r, DT_CENTER); // 对应区域居中打印数字 + drawtext(letter[i], &m, DT_CENTER); //对应区域居中打印字母 + } + setlinestyle(PS_SOLID, 2); //画实线 宽度2 + setfillcolor(RGB(0, 0, 0)); //设置填充颜色为黑色 + line(112, 112, 112, 462); //棋盘左侧边界 + line(462, 112, 462, 462); //棋盘右侧边界 + line(112, 112, 462, 112); //棋盘上方边界 + line(112, 462, 462, 462); //棋盘下方边界 + solidcircle(187, 187, 2); //绘制天元点 + solidcircle(187, 387, 2); + solidcircle(287, 287, 2); + solidcircle(387, 187, 2); + solidcircle(387, 387, 2); +} + +/************************************************* +Function: drawButton + +Description: 基于EasyX图形库,用于绘制游戏标题以及3个按钮 + +Input: NULL + +Return: NULL +********************************************/ +void drawButton() { + int nR1[] = { 225, 175, 375, 225 }; + int nR2[] = { 225, 300, 375, 350 }; + int nR3[] = { 225, 425, 375, 475 }; + RECT R1 = { nR1[0], nR1[1], nR1[2], nR1[3] }; //矩形指针R1 + RECT R2 = { nR2[0], nR2[1], nR2[2], nR2[3] }; //矩形指针R2 + RECT R3 = { nR3[0], nR3[1], nR3[2], nR3[3] }; //矩形指针R3 + setfillcolor(RGB(228, 121, 21)); //设置按钮颜色 + setlinecolor(RGB(0, 0, 0)); //设置线条颜色 + setlinestyle(PS_SOLID, 2); //设置线条属性为实线 宽度2 + fillrectangle(nR1[0], nR1[1], nR1[2], nR1[3]); //绘制按钮 + fillrectangle(nR2[0], nR2[1], nR2[2], nR2[3]); + fillrectangle(nR3[0], nR3[1], nR3[2], nR3[3]); + LOGFONT f; + gettextstyle(&f); // 获取当前字体设置 + f.lfHeight = 30; // 设置字体高度为 30 + _tcscpy_s(f.lfFaceName, _T("楷体")); // 设置字体为“楷体” + f.lfQuality = ANTIALIASED_QUALITY; // 设置输出效果为抗锯齿 + settextstyle(&f); // 设置字体样式 + setbkmode(TRANSPARENT); // 去掉文字背景 + settextcolor(BLACK); // 设置文字颜色为黑色 + drawtext(_T("人机对战"), &R1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R1内打印文字,水平居中,垂直居中,单行显示 + drawtext(_T("人人对战"), &R2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R2内打印文字,水平居中,垂直居中,单行显示 + drawtext(_T("退出游戏"), &R3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//在矩形区域R3内打印文字,水平居中,垂直居中,单行显示 + f.lfHeight = 45; //设置字体高度为45 + settextstyle(&f); //设置字体样式 + outtextxy(150, 75, _T("天天五子棋V1.0")); //打印标题 +} \ No newline at end of file diff --git "a/\345\256\236\351\252\214/initmap.h" "b/\345\256\236\351\252\214/initmap.h" new file mode 100644 index 00000000..3a214710 --- /dev/null +++ "b/\345\256\236\351\252\214/initmap.h" @@ -0,0 +1,10 @@ +#ifndef _INITMAP_H_ +#define _INITMAP_H_ + +#include +#include "assist.h" + +void drawButton(); +void initmap(); + +#endif \ No newline at end of file diff --git "a/\345\256\236\351\252\214/menu.cpp" "b/\345\256\236\351\252\214/menu.cpp" new file mode 100644 index 00000000..6ee14fa1 --- /dev/null +++ "b/\345\256\236\351\252\214/menu.cpp" @@ -0,0 +1,69 @@ +#include "menu.h" +/************************************************* +Function: Menu + +Description: 主菜单,调用drawButton函数绘制菜单后用于检测鼠标事件并给予响应 + +Input: NULL + +Return: NULL +********************************************/ +void Menu() { + setbkcolor(RGB(216, 150, 84)); //设置背景色 + cleardevice(); //应用背景色 + drawButton(); //绘制按钮组件以及标题等 + MOUSEMSG mouse; //鼠标指针,用于检测鼠标动作,按钮响应 + int button = 0, winner; + while (true) { + mouse = GetMouseMsg(); //获取一条鼠标消息 + if (mouse.uMsg == WM_LBUTTONDOWN) { //鼠标左键点击 + for (int i = 0; i < 3; i++) { //判断按的是哪一个按钮 + if (abs(mouse.x - 300) < 50 && abs(mouse.y - (200 + 125 * i) < 25)) { + button = i + 1; + break; + } + } + switch (button) { + case 1: //人机对战 + initmap(); //初始化地图 + winner = hum_VS_AI(); //hum_VS_AI 返回游戏胜利方 + if (winner == AIChessColor) { //AI获得胜利 + RECT r = { 480,300,580,350 }; + drawtext(_T("败北!"), &r, DT_CENTER); + } + else if (winner == humChessColor) { //玩家获得胜利 + RECT r = { 480,300,580,350 }; + drawtext(_T("你赢了!"), &r, DT_CENTER); + } + for (int i = 0; i < M_SIZE; i++) { + for (int j = 0; j < M_SIZE; j++) + gBoard[i][j] = SPACE; //游戏结束,重置棋盘 + } + _getch(); + return; + break; + case 2: //人人对战 + initmap();//初始化地图 + winner = dPlayers(); //dPlayers返回游戏胜利方 + if (winner == Black) { //黑方获胜 + RECT r = { 480,300,580,350 }; + drawtext(_T("黑方胜利!"), &r, DT_CENTER); + } + else if (winner == White) { + RECT r = { 480,300,580,350 }; //白方获胜 + drawtext(_T("白方胜利!"), &r, DT_CENTER); + } + for (int i = 0; i < M_SIZE; i++) { + for (int j = 0; j < M_SIZE; j++) + gBoard[i][j] = SPACE; //游戏结束,重置棋盘 + } + _getch(); + return; + break; + case 3: //游戏结束 + closegraph(); + exit(0); + } + } + } +} \ No newline at end of file diff --git "a/\345\256\236\351\252\214/menu.h" "b/\345\256\236\351\252\214/menu.h" new file mode 100644 index 00000000..b41f09e3 --- /dev/null +++ "b/\345\256\236\351\252\214/menu.h" @@ -0,0 +1,11 @@ +#ifndef _MENU_H +#define _MENU_H + +#include "initmap.h" +#include "assist.h" +#include "hum_VS_AI.h" +#include "dPlayers.h" + +void Menu(); + +#endif \ No newline at end of file diff --git "a/\345\256\236\351\252\214/resource.h" "b/\345\256\236\351\252\214/resource.h" new file mode 100644 index 00000000..bb84da6f --- /dev/null +++ "b/\345\256\236\351\252\214/resource.h" @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by go-bang.rc + +// 新对象的下一组默认值 +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git "a/\345\256\236\351\252\214/resource1.h" "b/\345\256\236\351\252\214/resource1.h" new file mode 100644 index 00000000..bb84da6f --- /dev/null +++ "b/\345\256\236\351\252\214/resource1.h" @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by go-bang.rc + +// 新对象的下一组默认值 +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git "a/\345\256\236\351\252\214/\346\272\220.cpp" "b/\345\256\236\351\252\214/\346\272\220.cpp" new file mode 100644 index 00000000..15b0f99d --- /dev/null +++ "b/\345\256\236\351\252\214/\346\272\220.cpp" @@ -0,0 +1,7 @@ +#include "menu.h" + +void main() { + initgraph(600, 600); // 初始化窗口 + while (true) + Menu(); +} \ No newline at end of file