diff --git "a/C\350\257\255\350\250\200\345\255\246\344\271\240\347\254\224\350\256\260.md" "b/C\350\257\255\350\250\200\345\255\246\344\271\240\347\254\224\350\256\260.md" old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/level0/README.md b/level0/README.md old mode 100755 new mode 100644 diff --git a/level0/bubbleSort/README.md b/level0/bubbleSort/README.md old mode 100755 new mode 100644 diff --git a/level1/p01_runningLetter/README.md b/level1/p01_runningLetter/README.md old mode 100755 new mode 100644 diff --git a/level1/p01_runningLetter/runningLetter.c b/level1/p01_runningLetter/runningLetter.c new file mode 100644 index 00000000..abebe044 --- /dev/null +++ b/level1/p01_runningLetter/runningLetter.c @@ -0,0 +1,45 @@ +#include +#include +#include +#define SCREENLENGTH 10 +#define SLEEPTIME 300 //if you can't see the letter move,please modify this number. +void PrintSpace(int n) //enter the amount of space. +{ + for (int i = 0; i < n; i++) + { + printf(" "); + } +} +int main() +{ + while (1) + { + int j = 0; + int TempForDection = 0; + while (j >= 0 && j <= SCREENLENGTH) //Condition is very clear. + { + + PrintSpace(j); + printf("S"); + if (TempForDection == 0) + { + j++; + } + if (TempForDection == 1) + { + j--; + } + if (j == SCREENLENGTH) + { + TempForDection = 1; + } + if (j == 0) + { + TempForDection = 0; + } + Sleep(SLEEPTIME); + system("cls"); + } + } + return 0; +} \ No newline at end of file diff --git a/level1/p02_isPrime/README.md b/level1/p02_isPrime/README.md old mode 100755 new mode 100644 diff --git a/level1/p02_isPrime/is_Prime.c b/level1/p02_isPrime/is_Prime.c new file mode 100644 index 00000000..308cbb80 --- /dev/null +++ b/level1/p02_isPrime/is_Prime.c @@ -0,0 +1,38 @@ +#include +#define MAX_RANGE /*(2 << 29 - 1)*/ 100000 +int main() +{ + int n; + int funCode = 1; //zero is allPrimes,one is isPrime + while (scanf("%d", &n) == 1 && n > 1) + { + int A[MAX_RANGE] = {0}; //Use zero to represent this is a prime.Use one to represent this is a prime. + int num = 0; + int TempOfPrime[MAX_RANGE]; + for (int i = 2; i <= n; i++) + { + if (!A[i]) + { + num += 1; + TempOfPrime[num] = i; //Attention:First element is a[1] + } + for (int j = 1; j <= num&&i*TempOfPrime[j]<=n; j++) + { + A[i * TempOfPrime[j]] = 1; + if ((i % TempOfPrime[j])==0) + break; + } + } + if (!funCode) + { + for (int i = 2; i <= n; i++) + if (!A[i]) + printf("%d ", i); + } + else + { + + (!A[n]) ? printf("%d is prime ", n) : printf("%d is not prime ", n); + } + } +} \ No newline at end of file diff --git a/level1/p03_Diophantus/README.md b/level1/p03_Diophantus/README.md old mode 100755 new mode 100644 diff --git a/level1/p03_Diophantus/diu.c b/level1/p03_Diophantus/diu.c new file mode 100644 index 00000000..2cacaefc --- /dev/null +++ b/level1/p03_Diophantus/diu.c @@ -0,0 +1,9 @@ +#include +int main() +{ + int i=0; + for(;i<100;i++) + if((1*12*7/6*i+1*12*7/12*i+1*12*7/7*i+5*12*7+1*12*7/2*i+4*12*7)==i*12*7) + break; + printf("His age is :%d",i); +} \ No newline at end of file diff --git a/level1/p04_ narcissus/README.md b/level1/p04_ narcissus/README.md old mode 100755 new mode 100644 diff --git a/level1/p04_ narcissus/narcissus.c b/level1/p04_ narcissus/narcissus.c new file mode 100644 index 00000000..69e57db9 --- /dev/null +++ b/level1/p04_ narcissus/narcissus.c @@ -0,0 +1,28 @@ +#include +void getThreeDigitNumber(const int targetnumber,int *digit_number) +{ + int i=targetnumber; + int j=0; + while(i) + { + digit_number[j++]=i%10; + i/=10; + } +} +int main() +{ + int digit_number[3]; + for(int i=100;i<1000;i++) + { + int sum=0; + get_threeDigit_Number(i,digit_number); + for(int j=0;j<3;j++) + { + sum+=digit_number[j]*digit_number[j]*digit_number[j]; + } + if(sum==i){ + printf("%d ",i); + } + } + return 0; +} \ No newline at end of file diff --git a/level1/p05_allPrimes/README.md b/level1/p05_allPrimes/README.md old mode 100755 new mode 100644 diff --git a/level1/p05_allPrimes/is_Prime.c b/level1/p05_allPrimes/is_Prime.c new file mode 100644 index 00000000..ba84c74b --- /dev/null +++ b/level1/p05_allPrimes/is_Prime.c @@ -0,0 +1,43 @@ +#include +#define MAX_RANGE /*(2 << 29 - 1)*/ 100000 +#include +int main() +{ + clock_t t1 = clock(); + int n; + int funCode = 0; //zero is allPrimes,one is isPrime + while (scanf("%d", &n) == 1 && n > 1) + { + int A[MAX_RANGE] = {0}; //Use zero to represent this is a prime.Use one to represent this is a prime. + int num = 0; + int TempOfPrime[MAX_RANGE]; + for (int i = 2; i <= n; i++) + { + if (!A[i]) + { + num += 1; + TempOfPrime[num] = i; //Attention:First element is a[1] + } + for (int j = 1; j <= num&&i*TempOfPrime[j]<=n; j++) + { + A[i * TempOfPrime[j]] = 1; + if ((i % TempOfPrime[j])==0) + break; + } + } + + if (!funCode) + { + for (int i = 2; i <= n; i++) + if (!A[i]) + printf("%d ", i); + } + else + { + + (!A[n]) ? printf("%d is prime ", n) : printf("%d is not prime ", n); + } + clock_t t2 = clock(); + printf("Execution time is: %fs\n", double(t2-t1)/CLOCKS_PER_SEC); + } +} \ No newline at end of file diff --git a/level1/p06_Goldbach/Goldbach.cpp b/level1/p06_Goldbach/Goldbach.cpp new file mode 100644 index 00000000..14949a35 --- /dev/null +++ b/level1/p06_Goldbach/Goldbach.cpp @@ -0,0 +1,53 @@ +#include +#include +#define MAX_RANGE /*(2 << 29 - 1)*/ 100000 +using namespace std; +int main() +{ + const int n=101;//The range of number you want to prove + set storage_Prime; + + int A[MAX_RANGE] = {0}; //Use zero to represent this is a prime.Use one to represent this is a prime. + int num = 0; + //generate Prime + int TempOfPrime[MAX_RANGE]; + for (int i = 2; i <= n; i++) + { + if (!A[i]) + { + num += 1; + TempOfPrime[num] = i; //Attention:First element is a[1] + } + for (int j = 1; j <= num && i * TempOfPrime[j] <= n; j++) + { + A[i * TempOfPrime[j]] = 1; + if ((i % TempOfPrime[j]) == 0) + break; + } + for (int i = 2; i <= n; i++) + { + if (!A[i]) + { + storage_Prime.insert(i); + } + } + } + for(int i=4;i::const_iterator citer=storage_Prime.begin();(*citer)<=i&&citer!=storage_Prime.end();citer++) + { + int remainder=i-*citer; + if(storage_Prime.find(remainder) != storage_Prime.end())//If find in Prime Set + { + flag=0;// + } + } + if(flag) + { + printf("Goldbach is not right."); + return 0; + } + } + printf("Goldbach is right."); +} diff --git a/level1/p06_Goldbach/README.md b/level1/p06_Goldbach/README.md old mode 100755 new mode 100644 diff --git a/level1/p07_encrypt_decrypt/Huffman.cpp b/level1/p07_encrypt_decrypt/Huffman.cpp new file mode 100644 index 00000000..d688c8be --- /dev/null +++ b/level1/p07_encrypt_decrypt/Huffman.cpp @@ -0,0 +1,66 @@ +#include "pch.h" +#include "Huffman.h" +void HuffmanCoding(HNode *HT, HCode *HC, unsigned long long *w, const int n) +{ + //初始化 + int m = 2 * n - 1; + HNode *p = HT; + int i = 0; + //听取俸爷建议,重构此处代码 + for (; i < n+m; i++, p++) + { + if (i >= n) + { + p->weight = 0; + } + else + { + p->weight = *w; + w++; + } + p->lchild = -1; + p->rchild = -1; + p->parent = -1; + } + //构造HUFFMAN TREE + for (i = n; i < m; i++) + { + long long min1 = MAXVALUE, min2 = MAXVALUE; + int min1id = 0, min2id = 0; //min1是最小的,min2次小 + for (int j = 0; j < i; j++) + { + if (HT[j].parent == -1 && HT[j].weight < min1) + { + min2 = min1; + min2id = min1id; + min1 = HT[j].weight; + min1id = j; + } + else if (HT[j].parent == -1 && HT[j].weight < min2) + { + min2 = HT[j].weight; + min2id = j; + } + } + HT[min1id].parent = i; + HT[min2id].parent = i; + HT[i].lchild = min1id; + HT[i].rchild = min2id; + HT[i].weight = min1 + min2; + } + //做字符编码 + for (int j = 0; j < n; j++) + { + int start = n - 1; + for (int tempid = j, tempparent = HT[j].parent; tempparent != -1; tempid = tempparent, tempparent = HT[tempparent].parent) + { + if (HT[tempparent].lchild == tempid) + { + HC[j].bit[start--] = 0; + } + else + HC[j].bit[start--] = 1; + } + HC[j].start = start + 1; //记录根节点位置 + } +} \ No newline at end of file diff --git a/level1/p07_encrypt_decrypt/Huffman.h b/level1/p07_encrypt_decrypt/Huffman.h new file mode 100644 index 00000000..6dfe2fa6 --- /dev/null +++ b/level1/p07_encrypt_decrypt/Huffman.h @@ -0,0 +1,14 @@ +#pragma once +#define MAXBIT 256 +const long long MAXVALUE = 9223372036854775806; +typedef struct HNode { + long long weight; + int parent; + int lchild; + int rchild; +} HNode; +typedef struct HCode { + int bit[MAXBIT]; + int start; +} HCode; +void HuffmanCoding(HNode *HT, HCode *HC, unsigned long long *w, const int n); \ No newline at end of file diff --git a/level1/p07_encrypt_decrypt/README.md b/level1/p07_encrypt_decrypt/README.md old mode 100755 new mode 100644 index efd67472..63a0b714 --- a/level1/p07_encrypt_decrypt/README.md +++ b/level1/p07_encrypt_decrypt/README.md @@ -1,3 +1,8 @@ ### 功能要求: -1. 分别编写“加密”、“解密”函数,输入为任意长度的字符串 \ No newline at end of file +<<<<<<< HEAD +1. 分别编写“加密”、“解密”函数,输入为任意长度的字符串 + + +MY program:Huffman encoding.This program can deal with any format below 4GB. + diff --git a/level1/p07_encrypt_decrypt/encrypt_decrypt.cpp b/level1/p07_encrypt_decrypt/encrypt_decrypt.cpp new file mode 100644 index 00000000..28477880 --- /dev/null +++ b/level1/p07_encrypt_decrypt/encrypt_decrypt.cpp @@ -0,0 +1,466 @@ +// HuffmanCompress.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 +#include "pch.h" +#include +#include +#include +#include +#include +#include "Huffman.h" +#include +using namespace std; +size_t WR_SIZE = 1024*1024 ; //每次读写的大小,此处为0.01M +const char displayLoading = 1; //编码进度显示 +const int chFreqSize = 256; +unsigned long long chFreq[chFreqSize]; + +long long getFileSize(const char *FileName) +{ + + FILE *stream_rd; + if (0 == fopen_s(&stream_rd, FileName, "rb")) + { + _fseeki64(stream_rd, 0L, SEEK_SET); + long long begin = _ftelli64(stream_rd); + _fseeki64(stream_rd, 0L, SEEK_END); + long long end = _ftelli64(stream_rd); + fclose(stream_rd); + return (end - begin); + } + else + { + fclose(stream_rd); + return -1; + } +} +void read_count_bitFile(const char *FILE_RD) +{ + FILE *stream_rd; + size_t num_read; + int rw_cnt = 0; + long long offset = 0; + + unsigned char *buf = new unsigned char[WR_SIZE]; + long long fileSize = getFileSize(FILE_RD); + if (0 == fopen_s(&stream_rd, FILE_RD, "rb")) + { + + while (!feof(stream_rd)) + { + //读 + num_read = fread(buf, sizeof(char), WR_SIZE, stream_rd); + if (displayLoading == 1 && 0 != num_read) + { + system("cls"); + long long curpoision = _ftelli64(stream_rd); //得到当前加载位置 + double percent = (double)curpoision / (double)fileSize * 100; + cout << "Loading " << percent << "% " << endl; + } + //统计二进制信息 + unsigned long i = num_read; + //long long count = 0; + while (i--) + { + chFreq[buf[i]]++; + } + if (0 == num_read) + break; + offset = num_read; //文件偏移 + //_fseeki64(stream_rd, offset, SEEK_CUR); //注意,这样做不能随意更改文件流位置 + } + } + //资源释放 + delete[] buf; + fclose(stream_rd); +} +//将一个字符转化为二进制串存入数组 +void b2char(unsigned char a,unsigned char code[], int k) +{ + + for (int i = k; i < k + 8; i++) + code[i] = 0; + + + int c = (int)a; + int n = k+7; + while (c) + { + code[n--] = c % 2; + c = c / 2; + } +} + +//以8为单位,将字符数组a转换为acsii +void char2b(unsigned char a[], unsigned char b[]) +{ + + int j, m; + int k = 0; + for (; a[8 * k] != '\0'; k++) + { + unsigned char c = 0; + for (int i = 8 * k; i < 8 * k + 8; i++) + { + if (a[i] != 0) + { + m = 7 - i + 8 * k; + j = 1 << m; + c = c + (int)(a[i] - '0') * j; + } + } + b[k] = c; + } +} + +void write_bitFile(const char *FILE_RD, const char *FILE_WR, HNode *HT, HCode *HC, const int n) +{ + FILE *stream_rd, *stream_wr, *stream_wr_miyao; + size_t num_read, num_written; + long long offsetRD = 0; + long long offsetWR = 0; + unsigned char *bufRD = new unsigned char[WR_SIZE]; + unsigned char *bufWR = new unsigned char[WR_SIZE]; + unsigned char *buf = new unsigned char[8 * WR_SIZE + 1]; + long long fileSize = getFileSize(FILE_RD); + long long k = 0; + //先处理加密区 + unsigned long long *buff = new unsigned long long[chFreqSize]; + fopen_s(&stream_wr_miyao, "miyao.b", "wb"); + for (int ll = 0; ll < chFreqSize; ll++) + { + buff[ll] = chFreq[ll]; + } + fwrite(buff, sizeof(unsigned long long), chFreqSize, stream_wr_miyao); + delete[] buff; + fclose(stream_wr_miyao); + //打开要写的文件 + errno_t errNum = 0; + try + { + errNum = fopen_s(&stream_wr, FILE_WR, "wb"); + } + catch (...) + { + cout << errNum << endl; + } + //正式文件处理 + if (0 == fopen_s(&stream_rd, FILE_RD, "rb")) + { + + while (!feof(stream_rd)) + { + //读 + num_read = fread(bufRD, sizeof(char), WR_SIZE, stream_rd); + long long debugRD = _ftelli64(stream_rd); + if (displayLoading == 1 && 0 != num_read) + { + system("cls"); + long long curpoision = _ftelli64(stream_rd); //得到当前加载位置 + double percent = (double)curpoision / (double)fileSize * 100; + cout << "Encoding perccent: " << percent << "% " << endl; + } + if (0 == num_read) + break; + offsetRD = num_read; //文件偏移 + //_fseeki64(stream_rd, offsetRD, SEEK_CUR); //注意,这样做不能随意更改文件流位置 + //文件读出后放入新buf区 + long long maxn = num_read; + for (int i = 0; i < maxn; i++) //内存字段扫描,每次1B + { + for (int j = HC[bufRD[i]].start; j < n; j++) //编码扫描 + { + //得到char串 + unsigned char tempchar1bit = (unsigned char)(HC[bufRD[i]].bit[j] + '0'); + buf[k++] = tempchar1bit; + + if (k == 8 * WR_SIZE) //装满了,但是可能j还有信息 + { + buf[k] = '\0'; + char2b(buf, bufWR); //把char串转换成ascii + + num_written = fwrite(bufWR, sizeof(char), WR_SIZE, stream_wr); + offsetWR = num_written; + //_fseeki64(stream_wr, offsetWR, SEEK_CUR); + long long debug1 = _ftelli64(stream_wr); + k = 0; + + // buf[0] = '\0'; + } + } + } + + } + if (num_read != WR_SIZE && k != 0) //说明读完了但是buf区还有东西 + { + int tempi = ((k - 1) % 8 + 1); + if (tempi != 8) + { + for (int kk = 0; kk < 8 - tempi; kk++) + buf[k++] = 0; + } + buf[k] = '\0'; + char2b(buf, bufWR); //把信息转换后存到bufWR + + size_t write_size = k / 8; + k = 0; + num_written = fwrite(bufWR, sizeof(char), write_size, stream_wr); + + offsetWR = num_written; +// _fseeki64(stream_wr, offsetWR, SEEK_CUR); + long long debug1 = _ftelli64(stream_wr); + // buf[0] = '\0'; + } + } + + //资源释放 + delete[] bufRD; + delete[] bufWR; + delete[] buf; + fclose(stream_rd); + fclose(stream_wr); +} +void HuffmanDecoding(const char *FILE_RD, const char *FILE_WR) +{ + FILE *stream_rd_miyao; + + /* + if (0 != fopen_s(&stream_wr, FILE_WR, "wb")) + { //获取待写入文件的句柄 + errNum = errno; + printf("open fail errno = %d reason = %s \n", errNum, (errNum)); + return; + } + */ + + //先处理加密区,得到哈夫曼树和哈夫曼编码 + unsigned long long *buff = new unsigned long long[chFreqSize]; + fopen_s(&stream_rd_miyao, "miyao.b", "rb"); + unsigned long long *REchFreqSize = new unsigned long long[chFreqSize]; + fread(REchFreqSize, sizeof(unsigned long long), chFreqSize, stream_rd_miyao); + HNode *HT = new HNode[2 * chFreqSize - 1]; + HCode *HC = new HCode[chFreqSize]; + HuffmanCoding(HT, HC, REchFreqSize, chFreqSize); + fclose(stream_rd_miyao); + delete[] REchFreqSize; + //找到树的根 + int root[2]; + for (int i = 0, j = 0; i < 2 * chFreqSize - 1; i++) + { + if (HT[i].parent == -1) + root[j++] = i; + } + //读入加密文件 + FILE *stream_rd, *stream_wr; + size_t num_read, num_written; + + errno_t errNum = 0; + try + { + errNum = fopen_s(&stream_wr, FILE_WR, "wb"); + } + catch (...) + { + cout << errNum << endl; + } + + /* + if (0 != fopen_s(&stream_wr, FILE_WR, "wb")) + { //获取待写入文件的句柄 + errNum = errno; + printf("open fail errno = %d reason = %s \n", errNum, (errNum)); + return; + } + */ + unsigned char *bufRD = new unsigned char[WR_SIZE]; + unsigned char *bufWR = new unsigned char[8 * WR_SIZE]; + unsigned char *buf = new unsigned char[8 * WR_SIZE ]; + long long fileSize = getFileSize(FILE_RD); + long long k = 0; + long long offsetRD = 0; + long long offsetWR = 0; + //正式文件处理 + + //读文件 + if (0 == fopen_s(&stream_rd, FILE_RD, "rb")) + { + int Nodeindex = root[0]; + HNode rootNode = HT[Nodeindex]; + int targetindex = 0; + + int count_for_WR = 0; + //unsigned long long aaa = 0,bbb=0; + + while (!feof(stream_rd)) + { + + //读 + num_read = fread(bufRD, sizeof(char), WR_SIZE, stream_rd); + + if (displayLoading == 1 && 0 != num_read) + { + system("cls"); + long long curpoision = _ftelli64(stream_rd); //得到当前加载位置 + double percent = (double)curpoision / (double)fileSize * 100; + cout << "Decoding perccent: " << percent << "% " << endl; + } + + if (0 == num_read) + break; + //变为二进制码 + long k = 0; + for (int i = 0; i < num_read; i++, k += 8) + { + b2char(bufRD[i], buf, k); + } + //解码 + + //aaa += num_read; + + for (long j = 0; j < k; j++) + { + int upflag = 0; + //如果为1,访问右节点,否则左节点 + if (buf[j]) + //如果要访问右节点 + if (rootNode.rchild == -1) //如果已经是叶节点 + { + if (rootNode.lchild != -1) + { + printf("r l error"); + exit(0); + } + targetindex = Nodeindex; + j--; + upflag = 1; + } + else + { + Nodeindex = rootNode.rchild; + rootNode = HT[Nodeindex]; + } + else + { + if (rootNode.lchild == -1) + { + if (rootNode.rchild != -1) + { + printf("l r error"); + exit(0); + } + targetindex = Nodeindex; + j--; + upflag = 1; + } + else + { + Nodeindex = rootNode.lchild; + rootNode = HT[Nodeindex]; + } + } + if (upflag) //如果找到了一个根结点 + { + bufWR[count_for_WR++] = (unsigned char)targetindex; + targetindex = -1; + Nodeindex = root[0]; + rootNode = HT[Nodeindex]; + } + } + //读文件更新 + offsetRD = num_read; //文件偏移 + //_fseeki64(stream_rd, offsetRD, SEEK_CUR); //注意,这样做不能随意更改文件流位置 + //写文件和文件更新 + num_written = fwrite(bufWR, sizeof(char), count_for_WR , stream_wr); + long long debug1 = _ftelli64(stream_wr); + /* + if (displayLoading == 1 ) + { + long long curpoision1 = _ftelli64(stream_wr); //得到当前加载位置 + double percent1 = (double)bbb / (double)aaa * 100; + cout << "Decoding perccent1: " << percent1 << "% " << endl; + } + + bbb += count_for_WR; + */ + count_for_WR = 0;//每次写完后清空 + offsetWR = num_written; +// _fseeki64(stream_wr, offsetWR, SEEK_CUR); + } + } + + //资源释放 + delete[] bufRD; + delete[] bufWR; + delete[] buf; + fclose(stream_rd); + fclose(stream_wr); + + //清空 + delete[] HC; + delete[] HT; +} +int main() +{ + /* + unsigned char a[17] = "0110001111000001"; + unsigned char b[80]; + char2b(a, b); + */ + /* + unsigned char a = 127; + unsigned char code[8]; + b2char(a, code, 0); + */ + const char *FILE_RD = "1.exe"; //原文件 + const char *FILE_WR = "2.exe"; //待写入的文件 + const char *FILE_RE = "3.exe"; //解码出的文件 + for (int i = 0; i < chFreqSize; i++) + chFreq[i] = 0; + //读取和统计二进制文件频率 + read_count_bitFile(FILE_RD); + + //构造HUFFMAN TREE以及编码 + HNode *HT = new HNode[2 * chFreqSize - 1]; + HCode *HC = new HCode[chFreqSize]; + HuffmanCoding(HT, HC, chFreq, chFreqSize); + //写入文件 + write_bitFile(FILE_RD, FILE_WR, HT, HC, chFreqSize); + //HUFFMAN解码 + HuffmanDecoding(FILE_WR, FILE_RE); + //清空 + delete[] HC; + delete[] HT; + + return 0; +} + +/* +#include +#include +using namespace std; + +long print_get_FileSize(const char * filename) +{ + + long l, m; + ifstream in(filename, ios::in | ios::binary); + l = in.tellg(); + in.seekg(0, ios::end); + m = in.tellg(); + in.close(); + cout << "size of " << filename; + cout << " is " << (m - l) << " bytes.\n"; + return (m - l); +} +int read_count_file(const char * filename) +{ + +} +int main() +{ + char * buffer; + + + + + return 0; + +}*/ diff --git a/level1/p08_hanoi/README.md b/level1/p08_hanoi/README.md old mode 100755 new mode 100644 diff --git a/level1/p08_hanoi/hanoi.c b/level1/p08_hanoi/hanoi.c new file mode 100644 index 00000000..c160c5e2 --- /dev/null +++ b/level1/p08_hanoi/hanoi.c @@ -0,0 +1,21 @@ +#include +//Let f(n) be the solution of n plates.So just let f(n-1) move to temp storage pillar,the left one plate to +//the target pillar.At last move (n-1) plates in temp storage pillar to target pillar. +//Obviously,Recursion is a good method to solve this problem. +void hanoi(int n,char current_storage_pillar,char temp_storage_pillar,char target_storage_pillar) +{ + if(n==1) + { + printf("%c->%c ",current_storage_pillar,target_storage_pillar); + return; + } + hanoi(n-1,current_storage_pillar,target_storage_pillar,temp_storage_pillar); + printf("%c->%c ",current_storage_pillar,target_storage_pillar); + hanoi(n-1,temp_storage_pillar,current_storage_pillar,target_storage_pillar); +} +int main() +{ + hanoi(4,'A','B','C'); + printf("\n"); + return 0; +} \ No newline at end of file diff --git a/level1/p08_hanoi/hanoi.jpg b/level1/p08_hanoi/hanoi.jpg old mode 100755 new mode 100644 diff --git a/level1/p09_maze/README.md b/level1/p09_maze/README.md old mode 100755 new mode 100644 diff --git a/level1/p09_maze/maze.c b/level1/p09_maze/maze.c new file mode 100644 index 00000000..bce1d79b --- /dev/null +++ b/level1/p09_maze/maze.c @@ -0,0 +1,591 @@ +/*todolist +1.read map; +2.print map&you; +3.move it:1)input;2)canyoumove?; +4.judge if you win; +5.score;*/ +#include +#include +#include +#define W 219 +#define P 232 +#define K 224 +#define E 215 + +unsigned char screen[22][22]; +void map(int level); +void print_map(void); +void judge(int level); +void gotoxy(int x, int y); + +int main(void) +{ + char input; + + system("chcp 437"); + system("mode con cols=23 lines=23"); + system("cls"); + + printf("Maze\n"); + printf("Info:Use \"w\" \"a\" \"s\" \"d\" to move,and you should"); + printf("get the %c to open the door(%c)\n",K,E); + printf("please choose a map:\n"); + printf("1 2 q.quit\n"); + while((input=getch())!='q') + { + switch(input) + { + case '1': + map(0); + judge(0); + break; + case '2': + map(1); + judge(1); + break; + case 'q': + return 0; + default: + ; + } + + map(-1); + system("cls"); + printf("Super Maze\n"); + printf("Info:Use \"w\" \"a\" \"s\" \"d\" to move,and you should"); + printf("get the %c to open the door(%c)\n",K,E); + printf("please choose a map:\n"); + printf("1 2 q.quit\n"); + + } + + + return 0; +} +void map(int level) +{ + int i,j; + + for(i=0;i<22;i++) + { + screen[i][0]=W; + screen[i][21]=W; + } + for(j=1;j<21;j++) + { + screen[0][j]=W; + screen[21][j]=W; + } + + if(level==0) + { + + for(i=8;i<11;i++) + { + screen[i][1]=W; + } + screen[4][1]=W; + screen[14][1]=W; + screen[16][1]=W; + + for(i=2;i<=14;i=i+2) + { + if(i!=8) + { + screen[i][2]=W; + } + } + for(i=16;i<20;i++) + { + screen[i][2]=W; + } + + for(i=1;i<15;i++) + { + if(i!=3&&i!=5&&i!=9&&i!=11 + &&i!=13) + { + screen[i][3]=W; + } + } + + screen[1][4]=W; + screen[4][4]=W; + screen[8][4]=W; + screen[12][4]=W; + screen[14][4]=W; + for(i=16;i<21;i++) + { + if(i!=18) + { + screen[i][4]=W; + } + } + + for(i=1;i<13;i++) + { + if(i!=2&&i!=7) + { + screen[i][5]=W; + } + } + screen[14][5]=W; + screen[16][5]=W; + screen[19][5]=W; + + screen[1][6]=W; + screen[3][6]=W; + screen[8][6]=W; + screen[16][6]=W; + screen[18][6]=W; + screen[19][6]=W; + + for(i=1;i<8;i=i+2) + { + screen[i][7]=W; + } + screen[8][7]=W; + for(i=10;i<19;i++) + { + if(i!=17) + { + screen[i][7]=W; + } + } + + for(i=3;i<8;i=i+2) + { + screen[i][8]=W; + } + screen[10][8]=W; + screen[16][8]=W; + screen[18][8]=W; + screen[19][8]=W; + + for(i=2;i<15;i++) + { + if(i!=4&&i!=6&&i!=8&&i!=11) + { + screen[i][9]=W; + } + } + + screen[5][10]=W; + screen[7][10]=W; + for(i=10;i<20;i++) + { + if(i!=13&&i!=15) + { + screen[i][10]=W; + } + } + + for(i=1;i<9;i++) + { + if(i!=4&&i!=6) + { + screen[i][11]=W; + } + } + screen[11][11]=W; + screen[14][11]=W; + screen[16][11]=W; + + screen[5][12]=W; + screen[8][12]=W; + screen[9][12]=W; + for(i=13;i<21;i++) + { + screen[i][12]=W; + } + + screen[1][13]=W; + for(i=3;i<12;i++) + { + screen[i][13]=W; + } + + screen[1][14]=W; + screen[3][14]=W; + screen[7][14]=W; + for(i=11;i<21;i++) + { + if(i!=16) + { + screen[i][14]=W; + } + } + + for(i=3;i<20;i=i+2) + { + if(i!=13) + { + screen[i][15]=W; + } + } + + for(i=3;i<20;i=i+2) + { + if(i!=15) + { + screen[i][16]=W; + } + } + screen[2][16]=W; + + for(i=5;i<20;i=i+2) + { + screen[i][17]=W; + } + for(i=14;i<18;i++) + { + screen[i][17]=W; + } + + screen[16][18]=W; + for(i=1;i<6;i++) + { + screen[i][18]=W; + } + for(i=7;i<12;i=i+2) + { + screen[i][18]=W; + } + screen[19][18]=W; + + screen[3][19]=W; + screen[11][19]=W; + for(i=7;i<10;i++) + { + screen[i][19]=W; + } + for(i=13;i<20;i++) + { + if(i!=17) + { + screen[i][19]=W; + } + } + + screen[1][20]=W; + screen[11][20]=W; + screen[5][20]=W; + + screen[0][2]=P; + screen[21][15]=E; + screen[8][18]=K; + } + else if(level==1) + { + for(i=5;i<8;i++) + { + screen[i][1]=W; + } + screen[11][1]=W; + screen[15][1]=W; + + for(i=1;i<14;i=i+2) + { + if(i!=5) + { + screen[i][2]=W; + } + } + for(i=15;i<19;i++) + { + screen[i][2]=W; + } + + for(i=3;i<6;i++) + { + screen[i][3]=W; + } + for(i=9;i<14;i=i+2) + { + screen[i][3]=W; + } + screen[18][3]=W; + screen[20][3]=W; + + screen[2][4]=W; + screen[3][4]=W; + for(i=5;i<10;i++) + { + screen[i][4]=W; + } + for(i=13;i<17;i++) + { + screen[i][4]=W; + } + screen[18][4]=W; + + screen[5][5]=W; + screen[12][5]=W; + screen[13][5]=W; + screen[16][5]=W; + screen[18][5]=W; + screen[19][5]=W; + + for(i=1;i<13;i++) + { + if(i!=4&&i!=6) + { + screen[i][6]=W; + } + } + screen[14][6]=W; + screen[16][6]=W; + + screen[5][7]=W; + screen[14][7]=W; + for(i=16;i<20;i++) + { + screen[i][7]=W; + } + + screen[1][8]=W; + screen[16][8]=W; + screen[19][8]=W; + for(i=3;i<15;i++) + { + if(i!=11) + { + screen[i][8]=W; + } + } + + screen[6][9]=W; + screen[10][9]=W; + screen[16][9]=W; + screen[17][9]=W; + + screen[1][10]=W; + screen[3][10]=W; + for(i=4;i<9;i=i+2) + { + screen[i][10]=W; + } + for(i=10;i<15;i++) + { + screen[i][10]=W; + } + screen[16][10]=W; + screen[19][10]=W; + + for(i=4;i<19;i=i+2) + { + if(i!=6&&i!=12) + { + screen[i][11]=W; + } + } + screen[19][11]=W; + + for(i=1;i<9;i++) + { + if(i!=3) + { + screen[i][12]=W; + } + } + for(i=10;i<17;i=i+2) + { + screen[i][12]=W; + } + screen[19][12]=W; + + screen[4][13]=W; + screen[10][13]=W; + screen[12][13]=W; + screen[16][13]=W; + screen[17][13]=W; + screen[19][13]=W; + + for(i=2;i<18;i++) + { + if(i!=5) + { + screen[i][14]=W; + } + } + + screen[2][15]=W; + screen[4][15]=W; + screen[14][15]=W; + screen[17][15]=W; + screen[19][15]=W; + screen[20][15]=W; + + for(i=1;i<13;i++) + { + if(i!=3) + { + screen[i][16]=W; + } + } + screen[16][16]=W; + screen[17][16]=W; + + screen[2][17]=W; + screen[6][17]=W; + screen[19][17]=W; + for(i=12;i<17;i++) + { + screen[i][17]=W; + } + + for(i=2;i<11;i=i+2) + { + screen[i][18]=W; + } + screen[9][18]=W; + screen[18][18]=W; + + for(i=2;i<9;i=i+2) + { + screen[i][19]=W; + } + screen[3][19]=W; + screen[20][19]=W; + for(i=10;i<19;i++) + { + screen[i][19]=W; + } + + screen[8][20]=W; + + screen[0][15]=P; + screen[0][17]=E; + screen[16][15]=K; + } + else if(level==-1) + { + for(i=0;i<22;i++) + { + for(j=0;j<22;j++) + { + screen[i][j]=' '; + } + } + } +} +void print_map(void) +{ + int i,j; + + system("cls"); + for(i=0;i<22;i++) + { + for(j=0;j<22;j++) + { + printf("%c",screen[i][j]); + } + printf("\n"); + } +} +void judge(int level) +{ + char move; + int i,j,k,l,m,n; + + if(level==0) + { + i=0; + j=2; + k=21; + l=15; + m=8; + n=18; + } + else if(level==1) + { + i=0; + j=15; + k=0; + l=17; + m=16; + n=15; + } + print_map(); + while(screen[k][l]!=P) + { + gotoxy(j,i); + move=getch(); + switch(move) + { + case 'w': + if(i!=0&&screen[i-1][j]!=W&&screen[i-1][j]!=E)//did not come to the final. + { + screen[i][j]=' '; + gotoxy(j,i); + printf("%c",screen[i][j]); + i--; + screen[i][j]=P; + gotoxy(j,i); + printf("%c",screen[i][j]); + } + break; + case 's': + if(i!=21&&screen[i+1][j]!=W&&screen[i+1][j]!=E) + { + screen[i][j]=' '; + gotoxy(j,i); + printf("%c",screen[i][j]); + i++; + screen[i][j]=P; + gotoxy(j,i); + printf("%c",screen[i][j]); + } + break; + case 'a': + if(j!=0&&screen[i][j-1]!=W&&screen[i][j-1]!=E) + { + screen[i][j]=' '; + gotoxy(j,i); + printf("%c",screen[i][j]); + j--; + screen[i][j]=P; + gotoxy(j,i); + printf("%c",screen[i][j]); + } + break; + case 'd': + if(j!=21&&screen[i][j+1]!=W&&screen[i][j+1]!=E) + { + + screen[i][j]=' '; + gotoxy(j,i); + printf("%c",screen[i][j]); + j++; + screen[i][j]=P; + gotoxy(j,i); + printf("%c",screen[i][j]); + } + break; + case 27: + return ; + default: + ; + } + if(screen[m][n]!=K&&screen[k][l]!=P) + { + screen[k][l]=' '; + gotoxy(l,k); + printf("%c",screen[k][l]); + } + + } + system("cls"); + printf("YOU WIN!\n"); + system("pause"); +} +//MFC set Console Cursor Position +void gotoxy(int x, int y) +{ + HANDLE hOutput; + COORD coo; + coo.X = x; + coo.Y = y; + hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleCursorPosition(hOutput, coo); +} diff --git a/level1/p10_pushBoxes/README.md b/level1/p10_pushBoxes/README.md old mode 100755 new mode 100644 diff --git a/level1/p10_pushBoxes/pushBoxes.c b/level1/p10_pushBoxes/pushBoxes.c new file mode 100644 index 00000000..10e1dee4 --- /dev/null +++ b/level1/p10_pushBoxes/pushBoxes.c @@ -0,0 +1,513 @@ +#include +#include +#include +#define P 148 //player-1 +#define G 176 //goal-2 +#define B 177 //box-3 +#define BG 178 //box on goal-4 +#define W 219 //wall-5 +#define PG 232 //player on goal-6 +/*todolist +1.read map; +2.print map&you; +3.move it:1)input;2)canyoumove?; +4.judge if you win; +5.score;*/ +void gotoxy(int x,int y); +void print_map(void); +void print_block(int n); +void move(int level); +bool judge(int level); +int wasd(int * x,int * y,char way); +void load_map(int n); + +int block[20][20];//0:空位 1:人物 2:目标位置 3:箱子 4:放在目标位置的箱子 5:墙 6:站在目标位置的人物 +int score=0; + +int main(void) +{ + char jud; + + system("chcp 437"); + system("mode con cols=32 lines=23"); + system("cls"); + + printf("Push Box\n"); + printf("Please choose a map\n"); + printf("1 2 3 4 5 6 7 q.quit\n"); + while((jud=getch())!='q') + { + system("cls"); + score=0; + switch(jud) + { + case '1': + load_map(0); + print_map(); + move(0); + break; + case '2': + load_map(1); + print_map(); + move(1); + break; + case '3': + load_map(2); + print_map(); + move(2); + break; + case '4': + load_map(3); + print_map(); + move(3); + break; + case '5': + load_map(4); + print_map(); + move(4); + break; + case '6': + load_map(5); + print_map(); + move(5); + break; + case '7': + load_map(6); + print_map(); + move(6); + break; + case 'q': + return 0; + default: + ; + } + system("cls"); + printf("Push Box\n"); + printf("Please choose a map\n"); + printf("1 2 3 4 5 6 7 q.quit\n"); + } + + return 0; +} +void move(int level) +{ + int i,j; + char jud; + + if(level==0) + { + i=4; + j=3; + } + else if(level==1) + { + i=1; + j=1; + } + else if(level==2) + { + i=3; + j=2; + } + else if(level==3) + { + i=2; + j=1; + } + else if(level==4) + { + i=1; + j=2; + } + else if(level==5) + { + i=1; + j=8; + } + else if(level==6) + { + i=3; + j=8; + } + while(judge(level)) + { + jud=getch(); + if(!wasd(&i,&j,jud)) + { + return; + } + gotoxy(21,0); + printf("score:%4d",score); + } + system("cls"); + printf("You win!\n"); + printf("Your step is %4d.\n",score); + system("pause"); + +} +int wasd(int * x,int * y,char way) +{ + int di,dj; + + switch(way) + { + case 'w': + di=-1; + dj=0; + break; + case 's': + di=1; + dj=0; + break; + case 'a': + di=0; + dj=-1; + break; + case 'd': + di=0; + dj=1; + break; + case 27: + return 0; + default: + return; + } + if(block[*x+di][*y+dj]==0) + { + if(block[*x][*y]==6) + { + block[*x][*y]=2; + block[*x+di][*y+dj]=1; + } + else if(block[*x][*y]==1) + { + block[*x][*y]=0; + block[*x+di][*y+dj]=1; + } + + gotoxy(*y,*x); + print_block(block[*x][*y]); + *x=*x+di; + *y=*y+dj; + gotoxy(*y,*x); + print_block(block[*x][*y]); + score++; + } + else if(block[*x+di][*y+dj]==2) + { + if(block[*x][*y]==6) + { + block[*x][*y]=2; + block[*x+di][*y+dj]=6; + } + else if(block[*x][*y]==1) + { + block[*x][*y]=0; + block[*x+di][*y+dj]=6; + } + + gotoxy(*y,*x); + print_block(block[*x][*y]); + *x=*x+di; + *y=*y+dj; + gotoxy(*y,*x); + print_block(block[*x][*y]); + score++; + } + else if(block[*x+di][*y+dj]==3) + { + if(block[*x][*y]==6) + { + if(block[*x+2*di][*y+2*dj]==0) + { + block[*x+2*di][*y+2*dj]=3; + block[*x+di][*y+dj]=1; + block[*x][*y]=2; + score++; + } + else if(block[*x+2*di][*y+2*dj]==2) + { + block[*x+2*di][*y+2*dj]=4; + block[*x+di][*y+dj]=1; + block[*x][*y]=2; + score++; + } + else + { + return; + } + } + else + { + if(block[*x+2*di][*y+2*dj]==0) + { + block[*x+2*di][*y+2*dj]=3; + block[*x+di][*y+dj]=1; + block[*x][*y]=0; + score++; + } + else if(block[*x+2*di][*y+2*dj]==2) + { + block[*x+2*di][*y+2*dj]=4; + block[*x+di][*y+dj]=1; + block[*x][*y]=0; + score++; + } + else + { + return; + } + } + gotoxy(*y,*x); + print_block(block[*x][*y]); + *x=*x+di; + *y=*y+dj; + gotoxy(*y,*x); + print_block(block[*x][*y]); + gotoxy(*y+dj,*x+di); + print_block(block[*x+di][*y+dj]); + } + else if(block[*x+di][*y+dj]==4) + { + if(block[*x][*y]==6) + { + if(block[*x+2*di][*y+2*dj]==0) + { + block[*x+2*di][*y+2*dj]=3; + block[*x+di][*y+dj]=6; + block[*x][*y]=2; + score++; + } + else if(block[*x+2*di][*y+2*dj]==2) + { + block[*x+2*di][*y+2*dj]=4; + block[*x+di][*y+dj]=6; + block[*x][*y]=2; + score++; + } + else + { + return; + } + } + else + { + if(block[*x+2*di][*y+2*dj]==0) + { + block[*x+2*di][*y+2*dj]=3; + block[*x+di][*y+dj]=6; + block[*x][*y]=0; + score++; + } + else if(block[*x+2*di][*y+2*dj]==2) + { + block[*x+2*di][*y+2*dj]=4; + block[*x+di][*y+dj]=6; + block[*x][*y]=0; + score++; + } + else + { + return; + } + } + gotoxy(*y,*x); + print_block(block[*x][*y]); + *x=*x+di; + *y=*y+dj; + gotoxy(*y,*x); + print_block(block[*x][*y]); + gotoxy(*y+dj,*x+di); + print_block(block[*x+di][*y+dj]); + } + + return 1; +} +//It's obviously tough to use C,if use C++ just use string +(Operator overloading),for C,we could use strcat +void load_map(int n) +{ + FILE *fp; + int i,j; + + if(n==0) + { + fp=fopen("map1.txt","r"); + } + else if(n==1) + { + fp=fopen("map2.txt","r"); + } + else if(n==2) + { + fp=fopen("map3.txt","r"); + } + else if(n==3) + { + fp=fopen("map4.txt","r"); + } + else if(n==4) + { + fp=fopen("map5.txt","r"); + } + else if(n==5) + { + fp=fopen("map6.txt","r"); + } + else if(n==6) + { + fp=fopen("map7.txt","r"); + } + for(i=0;i<20;i++) + { + for(j=0;j<20;j++) + { + fscanf(fp,"%d",&block[i][j]); + } + } + fclose(fp); + +} +void print_block(int n) +{ + if(n==0) + { + putchar(' '); + } + else if(n==1) + { + putchar(P); + } + else if(n==2) + { + putchar(G); + } + else if(n==3) + { + putchar(B); + } + else if(n==4) + { + putchar(BG); + } + else if(n==5) + { + putchar(W); + } + else if(n==6) + { + putchar(PG); + } + +} +bool judge(int level) +{ + if(level==0) + { + if(block[3][1]==4&&block[1][4]==4&& + block[4][6]==4&&block[6][3]==4) + { + return 0; + } + else + { + return 1; + } + } + else if(level==1) + { + if(block[3][7]==4&&block[4][7]==4&& + block[5][7]==4) + { + return 0; + } + else + { + return 1; + } + } + else if(level==2) + { + if(block[4][2]==4&&block[4][3]==4&& + block[5][2]==4&&block[5][3]==4) + { + return 0; + } + else + { + return 1; + } + } + else if(level==3) + { + if(block[5][1]==4&&block[6][3]==4&& + block[6][1]==4&&block[6][2]==4&& + block[6][4]==4) + { + return 0; + } + else + { + return 1; + } + } + else if(level==4) + { + if(block[4][1]==4&&block[5][1]==4&& + block[6][1]==4) + { + return 0; + } + else + { + return 1; + } + } + else if(level==5) + { + if(block[6][1]==4&&block[6][2]==4&& + block[6][3]==4&&block[6][4]==4&& + block[6][5]==4) + { + return 0; + } + else + { + return 1; + } + } + else if(level==6) + { + if(block[2][2]==4&&block[3][2]==4&& + block[4][2]==4&&block[3][1]==4&& + block[4][1]==4) + { + return 0; + } + else + { + return 1; + } + } +} +void print_map(void) +{ + int i,j; + + for(i=0;i<20;i++) + { + for(j=0;j<20;j++) + { + print_block(block[i][j]); + } + printf("\n"); + } +} +void gotoxy(int x, int y) +{ + HANDLE hOutput; + COORD coo; + coo.X = x; + coo.Y = y; + hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleCursorPosition(hOutput, coo); +} \ No newline at end of file diff --git a/level1/p11_linkedList/README.md b/level1/p11_linkedList/README.md old mode 100755 new mode 100644 diff --git a/level1/p11_linkedList/linkedList.c b/level1/p11_linkedList/linkedList.c new file mode 100644 index 00000000..d420ac38 --- /dev/null +++ b/level1/p11_linkedList/linkedList.c @@ -0,0 +1,112 @@ +#include +#include +#include + +struct list +{ + int num; + int value; + struct list *next; +}; +void display(struct list *head); +void is_five(struct list *head); +struct list *exchange(struct list *head, int n); +struct list *move(struct list *head, int n); +int main(void) +{ + struct list *_link, *_head, *q; + int m, i = 0, j; + + _link = q = (struct list *)malloc(sizeof(struct list)); + + printf("Now you can start to enter the value.(q to quit)\n"); + _head = NULL; + while (1 == scanf("%d", &m)&& m!=-1) + { + if (0 == i) + { + _head = _link; + } + else + { + _link->next = q; + _link = q; + } + _link->num = i + 1; + _link->value = m; + + q = (struct list *)malloc(sizeof(struct list)); + + i++; + } + _link->next = NULL; + free(q); + display(_head); + _head = exchange(_head, i); + is_five(_head); + + system("pause"); + + return 0; +} +void display(struct list *head) +{ + struct list *cp; + + cp = head; + while (cp != NULL) + { + printf("No.%d is %d\n", cp->num, cp->value); + cp = cp->next; + } +} +struct list *move(struct list *head, int n) +{ + struct list *cp; + int i; + + cp = head; + for (i = 0; i < n - 1; i++) + { + cp = cp->next; + } + + return cp; +} +struct list *exchange(struct list *head, int n) +{ + struct list *ch1, *ch2; + int i; + + ch1 = head; + ch2 = move(ch1, n); + head = ch2; + for (i = n; i > 1; i--) + { + ch2->next = move(ch1, i - 1); + ch2 = ch2->next; + } + ch2->next = NULL; + + return head; +} +void is_five(struct list *head) +{ + struct list *ch; + bool flag = 0; + ch = head; + while (ch != NULL) + { + if (5 == ch->value) + { + printf("%d\n", ch->num); + flag = 1; + } + ch = ch->next; + } + + if (!flag) + { + printf("-1\n"); + } +} \ No newline at end of file diff --git a/level1/p12_warehouse/README.md b/level1/p12_warehouse/README.md old mode 100755 new mode 100644 diff --git a/level1/p12_warehouse/warehouse.c b/level1/p12_warehouse/warehouse.c new file mode 100644 index 00000000..b7eaee53 --- /dev/null +++ b/level1/p12_warehouse/warehouse.c @@ -0,0 +1,172 @@ +#include +#include +#include + +typedef struct goods +{ + char name[16],size[4]; + long long int amount; + +}GOODS; + +void menu(GOODS * Goods,int * n); +void write(GOODS * Goods,int n); +void display(GOODS * Goods,int n); +void input(GOODS** Goods,int * n); +void output(GOODS** Goods,int * n); +long long int is_num(void); + +int main(void){ + FILE *fp; + int max,i; + + fp=fopen("warehouse.txt","r"); + fscanf(fp,"%d",&max); + + GOODS list[100]; + for(i=0;i=0)return n; + else return 0; + +} \ No newline at end of file diff --git a/level2/GA/README.md b/level2/GA/README.md old mode 100755 new mode 100644 diff --git a/level2/NeuralNetworks/README.md b/level2/NeuralNetworks/README.md old mode 100755 new mode 100644 index 29e3fba2..35c8ed10 --- a/level2/NeuralNetworks/README.md +++ b/level2/NeuralNetworks/README.md @@ -7,4 +7,6 @@ ### 参考: -[神经网络入门](http://blog.csdn.net/zzwu/article/details/574931) \ No newline at end of file +[神经网络入门](http://blog.csdn.net/zzwu/article/details/574931) + +说实话,用C++写挺麻烦的,数据集也要自己生成。一般来说神经网络倒不是特别难写,不过要借助opencv的库。。。还是先把五子棋做完再来看看吧。 \ No newline at end of file diff --git a/level2/PI/README.md b/level2/PI/README.md old mode 100755 new mode 100644 diff --git a/wuziqi/wuziqi/wuziqi.cpp b/wuziqi/wuziqi/wuziqi.cpp new file mode 100644 index 00000000..4044b551 --- /dev/null +++ b/wuziqi/wuziqi/wuziqi.cpp @@ -0,0 +1,1507 @@ +#include "pch.h" +#include "stdio.h" +#include "graphics.h" +#include "conio.h" +#include "windows.h" + +void init_system(); //初始化系统 +void close_system(); //关闭系统 +void init_globales(); //初始化参数 + +void play_chess(); //开始五子棋游戏 +void gamestart(); //开始下棋 +int count_xyk_by_message(MOUSEMSG *m, int *x, int *y, int *a, int *b); //计算鼠标所在区域状态 +int judge(int a, int b, int c); //判断胜负条件 +void regret(int x2, int y2, int chessbox[][2]); //悔棋 +void battleAI(); //AI对战程序 +void AIdecideNext(int *x, int *y, int *a, int *b, int num); //AI决策函数返回数组中下棋的下标。 +int MaxMinSearch(int deep, int alpha, int beta, int num); //alpha-beta搜索 +int generator(int num); //生成棋子位置 +int evaluate(int num); //评估全局面棋子得分 +int evaluate_point(int x, int y, int num); //单个点棋子得分 + +void draw_chessmen(int x, int y, int num, int a, int b); //绘制黑白棋子 +void draw_chessboard(); //画棋盘、菜单、状态框,画标题 +void text(); //绘制标题 +void draw_menu(); //绘制菜单 +void over_black(); //绘制黑棋胜字样 +void over_white(); //绘制白棋胜字样 +void position(); //绘制状态栏及内容 +void text_black(); //绘制黑棋下字样 +void text_white(); //绘制白棋下字样 +void draw_regret(int m, int n, int x2, int y2); //所有悔棋情况 +void draw_re(int x2, int y2); //绘制悔棋棋子 + + +int m_x0, m_y0, m_wh = 40, m_x01, m_y01; //对战区坐标 +int m_x_box, m_y_box, m_x_box1, m_y_box1; //棋盘起始坐标 +int m_x_chess, m_y_chess, m_x_chess1, m_y_chess1; //可下棋坐标 +int m_row = 14, m_row1 = 15; +int num = 0; //步数,偶数轮到黑棋下,奇数轮到白棋下 +int chessbox[255][2]; +int l_chess_range, r_chess_range, u_chess_range,d_chess_range; +int init_visit=1; + + +int Score_point[15][15];//评分数组 +int minmax_result_x, minmax_result_y; +int chess[15][15] = { 0 };//记录棋盘上棋子信息 +#define GAME_RUNNING 1 +#define GAME_OVER 0 +#define MOUSE_POS_ELSE 99 +#define MOUSE_POS_AREA 1 +#define NUM_BLACK 10 +#define NUM_WHITE 20 +#define MOUSE_POS_START 100 +#define MOUSE_POS_REGRET 200 +#define GAME_ROBOT 3 +#define Inf 2 << 20 + +int main() +{ + init_system(); + + draw_chessboard(); + + play_chess(); + + close_system(); + + return 0; +} +/*================================================ +== 函数名:AIdecideNext +== 功 能:AI对战系统 +== 参 数: + int *x, int *y:交叉点横纵坐标 + int *a, int *b:交叉点对应二维数组下标 + level:难度 +== 返回值:无 +=================================================*/ +void AIdecideNext(int *x, int *y, int *a, int *b, int num) +{ + //初始化一些变量start + int deep = 6,beta= Inf,alpha= -Inf; + //初始化一些变量end + int AI_color = num % 2; //偶数0轮到黑棋下,奇数1轮到白棋下 + //alpha beta剪枝开始 + MaxMinSearch(deep,alpha,beta,AI_color); + //alpha beta剪枝结束,结果放在 minmax_result_x,minmax_result_y中 + *a = minmax_result_x; + *b = minmax_result_y; + //得到数组坐标后进行转换 + *x = (*b) * m_wh + m_x0; //坐标横坐标 + *y = (*a) * m_wh + m_y0; //得到后传出 + +} +/*================================================ +== 函数名:evaluate +== 功 能:评估局面分数 +== 参 数: + int num下棋数目 +== 返回值:局面分数 +=================================================*/ +int evaluate(int num)//0就是黑棋将下,1白棋将下 +{ + int x, y, i, j, k; //循环变量 + int number1 = 0, number2 = 0; //number用来统计玩家或电脑棋子连成个数 + int empty = 0; //empty用来统计空点个数 + int player_score = 0, AI_score = 0;//先记下来,后面优化可能用这个 + for (x = 0; x < 15; x++) //把评分数组先清零 + for (y = 0; y < 15; y++) + Score_point[x][y] = 0; + for (x = 0; x < 15; x++) + { + for (y = 0; y < 15; y++) + { + if (chess[x][y] == 0) //如果这个点为空 + { + for (i = -1; i <= 1; i++) + { + for (j = -1; j <= 1; j++) //判断8个方向 + { + if (i != 0 || j != 0) //若是都为0的话,那不就是原坐标嘛 + { + //对玩家落点评分 + for (k = 1; i <= 4; k++) //循环4次 + { //这点没越界 且这点存在黑子(玩家) + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_BLACK) + { + number1++; + } + else if (chess[x + k * i][y + k * j] == 0) //这点是个空点,+1后退出 + { + empty++; + break; + } + else //否则是墙或者对方的棋子了 + { + break; + } + } + for (k = -1; k >= -4; k--) //向它的相反方向判断 + { //这点没越界 且这点存在黑子(玩家) + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_BLACK) + { + number1++; + } + else if (chess[x + k * i][y + k * j] == 0) //这点是个空点,+1后退出 + { + empty++; + break; + } + else + { + break; + } + } + if (number2 == 1) //2个棋子 + { + Score_point[x][y] += 100; + player_score += 100; + + } + else if (number1 == 2) //3个棋子 + { + if (empty == 1) + { + Score_point[x][y] += 100; //有一个空点+5分 死3 + player_score += 100; + } + else if (empty == 2) + { + Score_point[x][y] += 1000; //有两个空点+10分 活3 + player_score += 1000; + } + } + else if (number1 == 3) //4个棋子 + { + if (empty == 1) + { + Score_point[x][y] += 1000; //有一个空点+20分 死4 + player_score += 1000; + } + else if (empty == 2) + { + Score_point[x][y] += 10000; //有2个空点+100分 活4 + player_score += 10000; + } + } + else if (number1 >= 4) + { + Score_point[x][y] += 100000; //对方有5个棋子,分数要高点,先堵 + player_score += 100000; + } + empty = 0; //统计空点个数的变量清零 + //对电脑落点评分 + for (k = 1; i <= 4; k++) //循环4次 + { //这点没越界 且这点存在白子(电脑) + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_WHITE) + { + number2++; + } + else if (chess[x + k * i][y + k * j] == 0) + { + empty++; break; //空点 + } + else + { + break; + } + } + for (k = -1; k >= -4; k--) //向它的相反方向判断 + { + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_WHITE) + { + number2++; + } + else if (chess[x + k * i][y + k * j] == 0) + { + empty++; break; + } + else + { + break; //注释与上面玩家版相同 + } + } + if (number2 == 0) + { + Score_point[x][y] += 10; //1个棋子 + AI_score += 10; + } + else if (number2 == 1) + { + Score_point[x][y] += 100; //2个棋子 + AI_score += 100; + } + else if (number2 == 2) //3个棋子 + { + if (empty == 1) + { + Score_point[x][y] += 100; //死3 + AI_score += 100; + } + else if (empty == 2) + { + Score_point[x][y] += 1000; //活3 + AI_score += 1000; + } + } + else if (number2 == 3) //4个棋子 + { + if (empty == 1) + { + Score_point[x][y] += 1000; //死4 + AI_score += 1000; + } + else if (empty == 2) + { + Score_point[x][y] += 10000; //活4 + AI_score += 10000; + } + } + else if (number2 >= 4) + { + Score_point[x][y] += 100000; //自己落在这点能形成5个,也就能胜利了,分数最高 + AI_score += 100000; + } + + number1 = 0; //清零,以便下次重新统计 + number2 = 0; + empty = 0; + } + } + } + } + } + } + return (num % 2) ? AI_score : player_score;//死编码,后面如果有需要记得改 + +} +/*================================================ +== 函数名:evaluate_point +== 功 能:评估局面分数 +== 参 数: + int x,int y坐标 + int num下棋数 +== 返回值:单个点分数 +=================================================*/ +int evaluate_point(int x,int y,int num)//0就是黑棋将下,1白棋将下 +{ + int i, j, k; //循环变量 + int number1 = 0, number2 = 0; //number用来统计玩家或电脑棋子连成个数 + int empty = 0; //empty用来统计空点个数 + int player_score = 0, AI_score = 0;//先记下来,后面优化可能用这个 + + if (chess[x][y] == 0) //如果这个点为空 + { + for (i = -1; i <= 1; i++) + { + for (j = -1; j <= 1; j++) //判断8个方向 + { + if (i != 0 || j != 0) //若是都为0的话,那不就是原坐标嘛 + { + //对玩家落点评分 + for (k = 1; i <= 4; k++) //循环4次 + { //这点没越界 且这点存在黑子(玩家) + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_BLACK) + { + number1++; + } + else if (chess[x + k * i][y + k * j] == 0) //这点是个空点,+1后退出 + { + empty++; + break; + } + else //否则是墙或者对方的棋子了 + { + break; + } + } + for (k = -1; k >= -4; k--) //向它的相反方向判断 + { //这点没越界 且这点存在黑子(玩家) + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_BLACK) + { + number1++; + } + else if (chess[x + k * i][y + k * j] == 0) //这点是个空点,+1后退出 + { + empty++; + break; + } + else + { + break; + } + } + if (number2 == 1) //2个棋子 + { + + player_score += 100; + + } + else if (number1 == 2) //3个棋子 + { + if (empty == 1) + { + //有一个空点+5分 死3 + player_score += 100; + } + else if (empty == 2) + { + //有两个空点+10分 活3 + player_score += 1000; + } + } + else if (number1 == 3) //4个棋子 + { + if (empty == 1) + { + //有一个空点+20分 死4 + player_score += 1000; + } + else if (empty == 2) + { + //有2个空点+100分 活4 + player_score += 10000; + } + } + else if (number1 >= 4) + { + //对方有5个棋子,分数要高点,先堵 + player_score += 100000; + } + empty = 0; //统计空点个数的变量清零 + //对电脑落点评分 + for (k = 1; i <= 4; k++) //循环4次 + { //这点没越界 且这点存在白子(电脑) + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_WHITE) + { + number2++; + } + else if (chess[x + k * i][y + k * j] == 0) + { + empty++; break; //空点 + } + else + { + break; + } + } + for (k = -1; k >= -4; k--) //向它的相反方向判断 + { + if (x + k * i >= 0 && x + k * i <= 14 && + y + k * j >= 0 && y + k * j <= 14 && + chess[x + k * i][y + k * j] == NUM_WHITE) + { + number2++; + } + else if (chess[x + k * i][y + k * j] == 0) + { + empty++; break; + } + else + { + break; //注释与上面玩家版相同 + } + } + if (number2 == 0) + { + //1个棋子 + AI_score += 10; + } + else if (number2 == 1) + { + //2个棋子 + AI_score += 100; + } + else if (number2 == 2) //3个棋子 + { + if (empty == 1) + { + //死3 + AI_score += 100; + } + else if (empty == 2) + { + //活3 + AI_score += 1000; + } + } + else if (number2 == 3) //4个棋子 + { + if (empty == 1) + { + //死4 + AI_score += 1000; + } + else if (empty == 2) + { + //活4 + AI_score += 10000; + } + } + else if (number2 >= 4) + { + //自己落在这点能形成5个,也就能胜利了,分数最高 + AI_score += 100000; + } + + number1 = 0; //清零,以便下次重新统计 + number2 = 0; + empty = 0; + } + } + } + } + return (num % 2) ? AI_score : player_score;//死编码,后面如果有需要记得改 +} +/*================================================ +== 函数名:generator +== 功 能:计算新的点 +== 参 数: + int num下棋数 + int buff_for_sort[255][3]保存点,用于启发式函数数组,最后排序 +== 返回值:返回可行点数目 +=================================================*/ +int generator(int num, int buff_for_sort[255][3]) +{ + int funtion_code = 1;//1是启发式生成 + //求出可行范围,选取原则是棋子范围+2的矩形 + int left_range = (l_chess_range - 2 >= 0) ? l_chess_range - 2 : 0; + int right_range = ( r_chess_range<=12) ? r_chess_range + 2 : 14; + int down_range = (d_chess_range - 2 >= 0) ? d_chess_range - 2 : 0; + int up_range = (u_chess_range <= 12) ? u_chess_range + 2 : 14; + //可行范围内遍历点 + int count_possible_point = 0;//记录有多少个可行点 + int search_amount = 10;//每个可行范围只搜评分高的10个点,启发式函数用 + for (int i = left_range; i <= right_range; i++) + { + for (int j = down_range; j <= up_range; j++) + { + if (chess[i][j] != NUM_BLACK && chess[i][j] != NUM_WHITE)//此格子上没有棋子时候才统计 + { + if (funtion_code) + { + /*启发式函数用这*/ + buff_for_sort[count_possible_point][0] = evaluate_point(i, j, num);//0记录分数,1记录a,2记录b + } + + /*普通搜索用这里*/ + buff_for_sort[count_possible_point][1] = i;//[0]留出用于启发式函数存东西 + buff_for_sort[count_possible_point][2] = j; + + count_possible_point++; + } + } + } + if (funtion_code) + { + //把分数大的放前面,笨办法,随手写的冒泡,复杂度O(n^2)也算之前没有考虑清楚,应该直接上结构体数组方便用sort,复杂度O(nlogn) + for (int i = 0; i < count_possible_point-1; i++) + { + for (int j = i + 1; j < count_possible_point; j++) + { + if (buff_for_sort[i][0] < buff_for_sort[j][0]) + { + int t = buff_for_sort[i][0]; + buff_for_sort[i][0] = buff_for_sort[j][0]; + buff_for_sort[j][0] = t; + t = buff_for_sort[i][1]; + buff_for_sort[i][1] = buff_for_sort[j][1]; + buff_for_sort[j][1] = t; + t = buff_for_sort[i][2]; + buff_for_sort[i][2] = buff_for_sort[j][2]; + buff_for_sort[j][2] = t; + } + } + } + } + return count_possible_point; +} +/*================================================ +== 函数名:MaxMinSearch(int deep,int beta,int alpha,int num) +== 功 能:alpha-beta搜索,带启发式搜索功能 +== 参 数: + int deep 深度 + alpha, beta 分别代表了最大层的最大值和最小层的最小值 + +== 返回值:评估得分 +=================================================*/ +int MaxMinSearch(int deep,int alpha,int beta,int num) //alpha是最大 +{ + int heuristic_number = 10;//因为启发式函数已经排好序了,所以通常不用再搜那么多点,设置最多搜多少个点有好处。 + int buff_for_sort[255][3]; + for (int i = 0; i < 255; i++) + for (int j = 0; j < 3; j++) + buff_for_sort[i][j] = 0; + int count_possible_point=generator(num%2,buff_for_sort);//得到可以下子的点,num%2得到的和之前相同,也就是说如果是0就是黑棋将下,1白棋将下,generator改变了buff_for_sort + if (deep == 0 )//深度为0的时候直接评价返回 + return evaluate(num%2); // 根据局面评价函数直接返回,注意深度的层数,evaluate将返回一个人或者AI的分数 + else + { + int i = 0; + //深度为奇数或者偶数都可以 + int heuristic_range = (heuristic_number < count_possible_point) ? heuristic_number :count_possible_point;//因为启发式函数已经排好序了,所以通常不用再搜那么多点,找更小那个就行 + for (;i< heuristic_range;i++)//在可行点内 + { + //MakeNextMove + chess[buff_for_sort[i][1]][buff_for_sort[i][2]] = (num % 2) ? NUM_WHITE: NUM_BLACK;//假设下了这步棋,可行点处都是空棋,不用判断是不是空棋了 + int num_pass = (num == 1) ? 0 : 1;//传入相反棋的颜色 + int val = -MaxMinSearch(deep-1, -beta, -alpha, num_pass); + chess[buff_for_sort[i][1]][buff_for_sort[i][2]] = 0;//撤销假设棋子 + if (val >= beta)//在min层比beta大的不搜 + { + minmax_result_x = buff_for_sort[i][1];//记下最后走哪个点 + minmax_result_y = buff_for_sort[i][2];//记下最后走哪个点 + return beta; + } + /* + if (val <= alpha) + { + minmax_result_x = buff_for_sort[i][1];//记下最后走哪个点 + minmax_result_y = buff_for_sort[i][2];//记下最后走哪个点 + return alpha; + } + */ + if (val > alpha)//相当于只做了beta剪枝,因为转换了问题 + { + alpha = val; + } + } + //如果此时还没有找到 + i = i - 1; + minmax_result_x = buff_for_sort[i][1];//记下最后走哪个点 + minmax_result_y = buff_for_sort[i][2];//记下最后走哪个点 + return alpha; + } +} +/*================================================ +== 函数名:battleAI() +== 功 能:AI对战系统 +== 参 数:无 +== 返回值:无 +=================================================*/ +void battleAI() +{ + for (int ii = 0; ii < 15; ii++) + for (int jj = 0; jj < 15; jj++) + { + chess[ii][jj] = 0; + } + + draw_chessboard(); + num = 0; + int x1, y1; + x1 = m_x0 + m_wh * (m_row + 2); + y1 = m_y0 + m_wh * 5; + TCHAR str[] = _T("请下棋"); + settextstyle(m_wh, m_wh / 2 - 1, _T("楷体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + outtextxy(x1 + 1, y1, str); + + int x, y; //鼠标坐标 + int pos; //鼠标状态 + int x2, y2; + int a, b; + int mstate = GAME_RUNNING; + MOUSEMSG m; + IMAGE img; + int exit_flag = 0; + + + while (1) + { + m = GetMouseMsg(); + pos = count_xyk_by_message(&m, &x, &y, &a, &b); //鼠标点击后就由m得到x,y,a,b + + switch (m.uMsg) + { + case WM_LBUTTONDOWN: + { + if (pos == MOUSE_POS_AREA) + { + if (chess[a][b] == NUM_BLACK || chess[a][b] == NUM_WHITE) + continue; //If there has existed + else + { + //people chess start + draw_chessmen(x, y, num, a, b); //画出刚下的棋 + chessbox[num][0] = a; //记录此步的位置 + chessbox[num][1] = b; + //text tip start + if (num % 2 == 0) + { + text_white(); + } + if (num % 2 != 0) + { + text_black(); + } + //text tip end + // 找出有棋子的矩形范围,方便后续操作start + if (init_visit) + { + l_chess_range = a; + r_chess_range = a; + u_chess_range = b; + d_chess_range = b; + } + else + { + l_chess_range = (l_chess_range > a) ? a : l_chess_range; + r_chess_range = (r_chess_range < a) ? a : r_chess_range; + u_chess_range = (u_chess_range < b) ? b : u_chess_range; + d_chess_range = (d_chess_range > b) ? b : d_chess_range; + + } + // 找出范围,方便后续操作end + num++; //步数++ + + x2 = x; //暂存刚才的那一步,用于悔棋 + y2 = y; + if (judge(a, b, NUM_BLACK)) + { + over_black(); + return; + } + if (judge(a, b, NUM_WHITE)) + { + over_white(); + return; + } + //people chess end + + //AI chess start + AIdecideNext(&x, &y, &a, &b, num); //AI计算下一步去哪里 + // 找出范围,方便后续操作start + l_chess_range = (l_chess_range > a) ? a : l_chess_range; + r_chess_range = (r_chess_range < a) ? a : r_chess_range; + u_chess_range = (u_chess_range < b) ? b : u_chess_range; + d_chess_range = (d_chess_range > b) ? b : d_chess_range; + // 找出范围,方便后续操作end + + draw_chessmen(x, y, num, a, b); //画出刚下的棋 + chessbox[num][0] = a; + chessbox[num][1] = b; + //text tip start + if (num % 2 == 0) + { + text_white(); + } + if (num % 2 != 0) + { + text_black(); + } + //text tip end + num++; + x2 = x; + y2 = y; + if (judge(a, b, NUM_BLACK)) + { + over_black(); + return; + } + if (judge(a, b, NUM_WHITE)) + { + over_white(); + return; + } + //AI chess end + } + } + /* AI暂不支持悔棋 + else if (pos == MOUSE_POS_REGRET) + { + regret(x2, y2, chessbox); + } + */ + else if (pos == GAME_OVER) + { + exit_flag = 1; + } + } + } + if (exit_flag) + break; //如果点了退出回退上个页面 + } +} +/*================================================ +== 函数名:init_system() +== 功 能:初始化系统 +== 参 数:无 +== 返回值:无 +=================================================*/ +void init_system() +{ + initgraph(1024, 768); + init_globales(); + l_chess_range = 0; + r_chess_range = 0; + u_chess_range = 0; + d_chess_range = 0; +} +/*================================================ +== 函数名:close_system() +== 功 能:关闭系统 +== 参 数:无 +== 返回值:无 +=================================================*/ +void close_system() +{ + _getch(); + closegraph(); +} +/*================================================ +== 函数名:init_globales() +== 功 能:初始化参数 +== 参 数:无 +== 返回值:无 +=================================================*/ +void init_globales() +{ + m_x0 = 1024 / 2 - (m_row / 2) * m_wh; /*小棋盘*/ + m_x01 = m_x0 + m_row * m_wh; + m_y0 = 768 / 2 - (m_row / 2) * m_wh; + m_y01 = m_y0 + m_row * m_wh; + + m_x_box = m_x0 - m_wh; /*大棋盘*/ + m_x_box1 = m_x01 + m_wh; + m_y_box = m_y0 - m_wh * 2; + m_y_box1 = m_y01 + m_wh; + + m_x_chess = m_x0 - m_wh / 2; /*可下棋区域*/ + m_y_chess = m_y0 - m_wh / 2; + m_x_chess1 = m_x01 + m_wh / 2; + m_y_chess1 = m_y01 + m_wh / 2; +} +/*================================================ +== 函数名:draw_chessboard() +== 功 能:画棋盘、菜单、状态框,画标题 +== 参 数:无 +== 返回值:无 +=================================================*/ +void draw_chessboard() +{ + //画棋盘 + int i; + setbkcolor(BLACK); + cleardevice(); /*用背景色清空屏幕*/ + setlinestyle(PS_SOLID, 1); + setlinecolor(WHITE); + rectangle(m_x_box, m_y_box, m_x_box1, m_y_box1); + setfillcolor(RGB(172, 81, 24)); + setfillstyle(BS_SOLID); + floodfill((m_x0 + m_x01) / 2, (m_y0 + m_y01) / 2, WHITE); + + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + + setlinestyle(PS_SOLID, 1); + setlinecolor(BLACK); + rectangle(m_x0, m_y0, m_x01, m_y01); + + for (i = m_x0 + m_wh; i < m_x01; i += m_wh) //绘制交叉线 + { + line(i, m_y0, i, m_y01); + } + for (i = m_y0 + m_wh; i < m_y01; i += m_wh) + { + line(m_x0, i, m_x01, i); + } + + setlinecolor(BLACK); + setfillcolor(BLACK); /*绘制画笔颜色以及填充颜色*/ + + fillcircle(m_x0 + m_wh * 3, m_y0 + m_wh * 3, 3); //绘制星位 + fillcircle(m_x0 + m_wh * 11, m_y0 + m_wh * 3, 3); + fillcircle(m_x0 + m_wh * 3, m_y0 + m_wh * 11, 3); + fillcircle(m_x0 + m_wh * 11, m_y0 + m_wh * 11, 3); + fillcircle(m_x0 + m_wh * 7, m_y0 + m_wh * 7, 3); + + draw_menu(); /*绘制菜单*/ + position(); /*绘制状态框*/ + text(); /*绘制标题*/ +} +/*================================================ +== 函数名:play_chess() +== 功 能:开始五子棋游戏 +== 参 数:无 +== 返回值:无 +=================================================*/ +void play_chess() +{ + int x, y; //鼠标坐标 + int pos; //鼠标状态 + int a, b; + MOUSEMSG m; + while (1) + { + m = GetMouseMsg(); + pos = count_xyk_by_message(&m, &x, &y, &a, &b); + + switch (m.uMsg) + { + case WM_LBUTTONDOWN: /*判别鼠标左键点击区域*/ + { + if (pos == MOUSE_POS_ELSE) + continue; //其他区域 + if (pos == MOUSE_POS_START) + { + gamestart(); //开始方框 + break; + } + if (pos == GAME_ROBOT) + { + battleAI(); //开始方框 + break; + } + if (pos == GAME_OVER) + exit(1); //结束方框 + } + } + } +} +/*================================================ +== 函数名:gamestart() +== 功 能:开始下棋 +== 参 数:无 +== 返回值:无 +=================================================*/ +void gamestart() +{ + draw_chessboard(); + + for(int ii=0;ii<15;ii++) + for (int jj = 0; jj < 15; jj++) + { + chess[ii][jj] = 0; + } + + num = 0; + + int x1, y1; + x1 = m_x0 + m_wh * (m_row + 2); + y1 = m_y0 + m_wh * 5; + TCHAR str[] = _T("请下棋"); + settextstyle(m_wh, m_wh / 2 - 1, _T("楷体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + outtextxy(x1 + 1, y1, str); + + int x, y; //鼠标坐标 + int pos; //鼠标状态 + int x2, y2; + int a, b; + int mstate = GAME_RUNNING; + MOUSEMSG m; + IMAGE img; + int exit_flag = 0; + while (1) + { + m = GetMouseMsg(); + pos = count_xyk_by_message(&m, &x, &y, &a, &b); + + switch (m.uMsg) + { + case WM_LBUTTONDOWN: + { + if (pos == MOUSE_POS_AREA) + { + if (chess[a][b] == NUM_BLACK || chess[a][b] == NUM_WHITE) + continue; + else + { + draw_chessmen(x, y, num, a, b); + chessbox[num][0] = a; + chessbox[num][1] = b; + if (num % 2 == 0) + { + text_white(); + } + if (num % 2 != 0) + { + text_black(); + } + num++; + x2 = x; + y2 = y; + if (judge(a, b, NUM_BLACK)) + { + over_black(); + return; + } + if (judge(a, b, NUM_WHITE)) + { + over_white(); + return; + } + } + } + else if (pos == MOUSE_POS_REGRET) + { + regret(x2, y2, chessbox); + } + else if (pos == GAME_OVER) + { + exit_flag = 1; + } + } + } + if (exit_flag) + break; //如果点了退出回退上个页面 + } +} +/*============================================================================ +== 函数名:count_xyk_by_message(MOUSEMSG *m, int *x, int *y, int *a, int *b) +== 功 能:计算鼠标所在区域状态,并返回点击区域信息 +== 参 数:MOUSEMSG *m:鼠标信息 + int *x, int *y:交叉点横纵坐标 + int *a, int *b:交叉点对应二维数组下标 +== 返回值:MOUSE_POS_AREA :可下棋区域 + MOUSE_POS_START :菜单开始方框 + MOUSE_POS_REGRET:菜单悔棋方框 + GAME_OVER :菜单结束方框 + MOUSE_POS_ELSE :非功能区域 + GAME_ROBOT :人机对战区域 +==============================================================================*/ +int count_xyk_by_message(MOUSEMSG *m, int *x, int *y, int *a, int *b) +{ + int x1, y1; + + x1 = m->x; // 鼠标的x信息 + y1 = m->y; + + if ((x1 >= m_x_chess && x1 <= m_x_chess1) && (y1 >= m_y_chess && y1 <= m_y_chess1)) //鼠标点在可下棋范围内 + { + *x = m_x0 + (m->x - m_x_chess) / m_wh * m_wh; //交叉点横坐标等于这个转换公式 + *y = m_y0 + (m->y - m_y_chess) / m_wh * m_wh; + + *b = (*x - m_x_chess) / m_wh; //数组横坐标 + *a = (*y - m_y_chess) / m_wh; + + return (MOUSE_POS_AREA); + } + + if ((x1 >= m_x0 - m_wh * 4 && x1 <= m_x0 - m_wh * 2) && (y1 >= m_y0 + m_wh * 3 && y1 <= m_y0 + m_wh * 4)) + return (MOUSE_POS_START); + + if ((x1 >= m_x0 - m_wh * 4 && x1 <= m_x0 - m_wh * 2) && (y1 >= m_y0 + m_wh * 5 && y1 <= m_y0 + m_wh * 6)) + return (MOUSE_POS_REGRET); + + if ((x1 >= m_x0 - m_wh * 4 && x1 <= m_x0 - m_wh * 2) && (y1 >= m_y0 + m_wh * 7 && y1 <= m_y0 + m_wh * 8)) + return (GAME_OVER); + + if ((x1 >= m_x0 - m_wh * 4 && x1 <= m_x0 - m_wh * 2) && (y1 >= m_y0 + m_wh * 9 && y1 <= m_y0 + m_wh * 10)) + return (GAME_ROBOT); + + return (MOUSE_POS_ELSE); +} +/*========================================================================= +== 函数名:void regret(int x2, int y2, int chessbox[][2]) +== 功 能:悔棋 +== 参 数:int x2, int y2:棋子所在的交叉点坐标 + int chess[15][15]:交叉点棋子信息(判定是黑、白、无棋) + int chessbox[][2]:上一棋子数组下标 +== 返回值:无 +==========================================================================*/ +void regret(int x2, int y2, int chessbox[][2]) +{ + int amount = 1; + while (amount > 0) + { + int m, n; + m = chessbox[num - 1][0]; + n = chessbox[num - 1][1]; + draw_regret(m, n, x2, y2); + chess[m][n] = 0; + num = num - 1; + + if (num % 2 == 0) + { + text_black(); + } + if (num % 2 != 0) + { + text_white(); + } + amount--; + } +} +/*================================================ +== 函数名:draw_regret(int m, int n, int x2, int y2) +== 功 能:绘制所有悔棋情况 +== 参 数:int m, int n:棋子所在交叉点下标 + int x2, int y2:棋子所在交叉点坐标 +== 返回值:无 +=================================================*/ +void draw_regret(int m, int n, int x2, int y2) +{ + draw_re(x2, y2); + if (m == 3 && n == 3) + { + setlinecolor(BLACK); + setfillcolor(BLACK); /*绘制画笔颜色以及填充颜色*/ + fillcircle(m_x0 + m_wh * 3, m_y0 + m_wh * 3, 3); //绘制星位 + } + if (m == 3 && n == 11) + { + setlinecolor(BLACK); + setfillcolor(BLACK); /*绘制画笔颜色以及填充颜色*/ + fillcircle(m_x0 + m_wh * 11, m_y0 + m_wh * 3, 3); + } + if (m == 11 && n == 3) + { + setlinecolor(BLACK); + setfillcolor(BLACK); /*绘制画笔颜色以及填充颜色*/ + fillcircle(m_x0 + m_wh * 3, m_y0 + m_wh * 11, 3); + } + if (m == 11 && n == 11) + { + setlinecolor(BLACK); + setfillcolor(BLACK); /*绘制画笔颜色以及填充颜色*/ + fillcircle(m_x0 + m_wh * 11, m_y0 + m_wh * 11, 3); + } + if (m == 7 && n == 7) + { + setlinecolor(BLACK); + setfillcolor(BLACK); /*绘制画笔颜色以及填充颜色*/ + fillcircle(x2, y2, 3); + } + if (m == 0 && n == 0) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2 - 15, y2); + line(x2, y2, x2, y2 - 15); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } + if (m == 0 && n == 14) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2 + 15, y2); + line(x2, y2, x2, y2 - 15); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } + if (m == 14 && n == 0) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2 - 15, y2); + line(x2, y2, x2, y2 + 15); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } + if (m == 14 && n == 14) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2 + 15, y2); + line(x2, y2, x2, y2 + 15); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } + if ((n > 0 && n < 14) && m == 0) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2, y2 - 15); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } + if ((n > 0 && n < 14) && m == 14) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2, y2 + 15); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } + if ((m > 0 && m < 14) && n == 0) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2 - 15, y2); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } + if ((m > 0 && m < 14) && n == 14) + { + setlinecolor(RGB(172, 81, 24)); + setlinestyle(PS_SOLID, 1); + line(x2, y2, x2 + 15, y2); + setlinestyle(PS_SOLID, 2); + setlinecolor(BLACK); + rectangle(m_x0 - 4, m_y0 - 4, m_x01 + 4, m_y01 + 4); + } +} +/*================================================ +== 函数名:draw_re(int x2, int y2) +== 功 能:绘制悔棋棋子 +== 参 数:int x2, int y2:棋子所在交叉点坐标 +== 返回值:无 +=================================================*/ +void draw_re(int x2, int y2) +{ + setlinecolor(RGB(172, 81, 24)); + setfillcolor(RGB(172, 81, 24)); + fillcircle(x2, y2, 15); + setlinecolor(BLACK); + setlinestyle(PS_SOLID, 1); + line(x2 - 15, y2, x2 + 15, y2); + line(x2, y2 - 15, x2, y2 + 15); +} +/*============================================================================= +== 函数名:draw_chessmen(int x, int y, int num, int a, int b) +== 功 能:绘制黑白棋子 +== 参 数:int x, int y :下棋交叉点横纵坐标 + int num :棋子数 + int a, int b :交叉点数组下标 + int chess[][15]:交叉点数组信息 +== 返回值:无 +===============================================================================*/ +void draw_chessmen(int x, int y, int num, int a, int b) +{ + if (num % 2 == 0) + { + setlinecolor(BLACK); + setfillcolor(BLACK); + fillcircle(x, y, 15); + chess[a][b] = NUM_BLACK; + } + + if (num % 2 != 0) + { + setlinecolor(WHITE); + setfillcolor(WHITE); + fillcircle(x, y, 15); + chess[a][b] = NUM_WHITE; + } +} +/*================================================ +== 函数名:text() +== 功 能:绘制标题 +== 参 数:无 +== 返回值:无 +=================================================*/ +void text() +{ + int x1, y1; + TCHAR str[] = _T("五 子 棋"); + settextstyle(m_wh, m_wh, _T("黑体")); + setbkcolor(RGB(172, 81, 24)); + settextcolor(BLACK); + x1 = m_x0 + m_wh * 3; + y1 = m_y0 - m_wh / 3 * 2 - 30; + outtextxy(x1, y1, str); +} +/*================================================ +== 函数名:judge(int a, int b, int c) +== 功 能:判断胜负条件 +== 参 数:int a,int b :数组下标(代表行和列) + int c :代表颜色 + int chess[][15]:代表棋子颜色 +== 返回值:无 +=================================================*/ +int judge(int a, int b, int c) +{ + int i, j, n1, n2; //i 表示行,j表示列 + while (1) + { + n1 = 0; + n2 = 0; + /*水平向左统计同种颜色棋子个数*/ + for (i = a, j = b; j >= 0; j--) + { + if (chess[i][j] == c) + n1++; + else + break; + } + /*水平向右统计同种颜色棋子个数*/ + for (i = a, j = b; j <= m_row1; j++) + { + if (chess[i][j] == c) + n2++; + else + break; + } + if (n1 + n2 - 1 >= 5) + { + return (1); + break; + } + /*垂直向上统计同种颜色棋子个数*/ + n1 = 0; + n2 = 0; + for (i = a, j = b; i >= 0; i--) + { + if (chess[i][j] == c) + n1++; + else + break; + } + /*垂直向下统计同种颜色棋子个数*/ + for (i = a, j = b; i <= m_row1; i++) + { + if (chess[i][j] == c) + n2++; + else + break; + } + if (n1 + n2 - 1 >= 5) + { + return (1); + break; + } + /*向左上方统计同种颜色棋子个数*/ + n1 = 0; + n2 = 0; + for (i = a, j = b; i >= 0, j >= 0; i--, j--) + { + if (chess[i][j] == c) + n1++; + else + break; + } + /*向右下方统计同种颜色棋子个数*/ + for (i = a, j = b; i <= m_row1, j <= m_row1; i++, j++) + { + if (chess[i][j] == c) + n2++; + else + break; + } + if (n1 + n2 - 1 >= 5) + { + return (1); + break; + } + /*向右上方统计同种颜色棋子个数*/ + n1 = 0; + n2 = 0; + for (i = a, j = b; i >= 0, j <= m_row1; i--, j++) + { + if (chess[i][j] == c) + n1++; + else + break; + } + /*向左下方统计同种颜色棋子个数*/ + for (i = a, j = b; i <= m_row1, j >= 0; i++, j--) + { + if (chess[i][j] == c) + n2++; + else + break; + } + + if (n1 + n2 - 1 >= 5) + { + return (1); + break; + } + return (0); + break; + } +} +/*================================================ +== 函数名:draw_menu() +== 功 能:绘制菜单 +== 参 数:无 +== 返回值:无 +=================================================*/ +void draw_menu() +{ + int x, y; + + setlinestyle(PS_SOLID, 1); + setlinecolor(WHITE); + + x = m_x0 - m_wh * 4; + y = m_y0 + m_wh * 3; + rectangle(x, y, x + m_wh * 2, y + m_wh); //开始方框 + setfillcolor(RGB(172, 81, 24)); + setfillstyle(BS_SOLID); + floodfill(x + 1, y + 1, WHITE); + TCHAR str1[] = _T("双人"); + settextstyle(m_wh - 2, m_wh / 2 - 2, _T("楷体")); + setbkcolor(RGB(172, 81, 24)); + settextcolor(BLACK); + outtextxy(x + 4, y + 1, str1); + + x = x; + y = y + m_wh * 2; + rectangle(x, y, x + m_wh * 2, y + m_wh); //悔棋方框 + setfillcolor(RGB(172, 81, 24)); + setfillstyle(BS_SOLID); + floodfill(x + 1, y + 1, WHITE); + TCHAR str2[] = _T("悔棋"); + settextstyle(m_wh - 2, m_wh / 2 - 2, _T("楷体")); + setbkcolor(RGB(172, 81, 24)); + settextcolor(BLACK); + outtextxy(x + 4, y + 1, str2); + + x = x; + y = y + m_wh * 2; + rectangle(x, y, x + m_wh * 2, y + m_wh); //结束方框 + setfillcolor(RGB(172, 81, 24)); + setfillstyle(BS_SOLID); + floodfill(x + 1, y + 1, WHITE); + TCHAR str3[] = _T("结束"); + settextstyle(m_wh - 2, m_wh / 2 - 2, _T("楷体")); + setbkcolor(RGB(172, 81, 24)); + settextcolor(BLACK); + outtextxy(x + 4, y + 1, str3); + + x = x; + y = y + m_wh * 2; + rectangle(x, y, x + m_wh * 2, y + m_wh); //人机对战方框 + setfillcolor(RGB(172, 81, 24)); + setfillstyle(BS_SOLID); + floodfill(x + 1, y + 1, WHITE); + TCHAR str4[] = _T("人机"); + settextstyle(m_wh - 2, m_wh / 2 - 2, _T("楷体")); + setbkcolor(RGB(172, 81, 24)); + settextcolor(BLACK); + outtextxy(x + 4, y + 1, str4); +} +/*================================================ +== 函数名:over_black() +== 功 能:绘制黑棋胜字样 +== 参 数:无 +== 返回值:无 +=================================================*/ +void over_black() +{ + int x, y; + x = m_x0 + m_wh * (m_row + 2); + y = m_y0 + m_wh * 5; + TCHAR str[] = _T("黑方胜"); + settextstyle(m_wh, m_wh / 2 - 1, _T("楷体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + outtextxy(x + 1, y, str); + TCHAR str1[] = _T("按开始再来一局"); + settextstyle(m_wh / 2, m_wh / 5 - 1, _T("黑体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + x = m_x0 + m_wh * (m_row + 2) + 7; + y = m_y0 + m_wh * 6; + outtextxy(x + 1, y, str1); +} +/*================================================ +== 函数名:over_white() +== 功 能:绘制白棋胜字样 +== 参 数:无 +== 返回值:无 +=================================================*/ +void over_white() +{ + int x, y; + x = m_x0 + m_wh * (m_row + 2); + y = m_y0 + m_wh * 5; + TCHAR str[] = _T("白方胜"); + settextstyle(m_wh, m_wh / 2 - 1, _T("楷体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + outtextxy(x + 1, y, str); + TCHAR str1[] = _T("按开始再来一局"); + settextstyle(m_wh / 2, m_wh / 5 - 1, _T("黑体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + x = m_x0 + m_wh * (m_row + 2) + 7; + y = m_y0 + m_wh * 6; + outtextxy(x + 1, y, str1); +} +/*================================================ +== 函数名:position() +== 功 能:绘制状态栏及内容 +== 参 数:无 +== 返回值:无 +=================================================*/ +void position() +{ + int x, y; + x = m_x0 + m_wh * (m_row + 2); + y = m_y0 + m_wh * 4; + setlinecolor(WHITE); + rectangle(x, y, x + m_wh * 3, y + m_wh * 3); + setfillcolor(RGB(172, 81, 24)); + setfillstyle(BS_SOLID); + floodfill(x + 1, y + 1, WHITE); + + TCHAR str1[] = _T("提示"); + settextstyle(m_wh / 2, m_wh / 3, _T("楷体")); + setbkmode(TRANSPARENT); + settextcolor(WHITE); + outtextxy(x + m_wh / 3 * 2, y + 2, str1); + + x = x; + y = y + m_wh; + TCHAR str[] = _T("请点击开始"); + settextstyle(m_wh, m_wh / 3 - 2, _T("楷体")); + setbkmode(TRANSPARENT); + settextcolor(WHITE); + outtextxy(x, y, str); +} +/*================================================ +== 函数名:text_black() +== 功 能:绘制黑棋下字样 +== 参 数:无 +== 返回值:无 +=================================================*/ +void text_black() +{ + int x, y; + x = m_x0 + m_wh * (m_row + 2); + y = m_y0 + m_wh * 5; + TCHAR str[] = _T("黑子下"); + settextstyle(m_wh, m_wh / 2 - 1, _T("楷体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + outtextxy(x + 1, y, str); +} +/*================================================ +== 函数名:text_white() +== 功 能:绘制白棋下字样 +== 参 数:无 +== 返回值:无 +=================================================*/ +void text_white() +{ + int x, y; + x = m_x0 + m_wh * (m_row + 2); + y = m_y0 + m_wh * 5; + TCHAR str[] = _T("白子下"); + settextstyle(m_wh, m_wh / 2 - 1, _T("楷体")); + setbkmode(OPAQUE); + settextcolor(WHITE); + outtextxy(x + 1, y, str); +} diff --git "a/wuziqi/wuziqi/\346\203\263\346\263\225.txt" "b/wuziqi/wuziqi/\346\203\263\346\263\225.txt" new file mode 100644 index 00000000..a6df2cd3 --- /dev/null +++ "b/wuziqi/wuziqi/\346\203\263\346\263\225.txt" @@ -0,0 +1,7 @@ +每次记下棋子所成矩形会更方便。 +评分函数:搜索得到整个局面的分数:直接搜索,计算分数 +评估函数是两部分,一个是总体评分,按照行,列,斜列进行模式匹配。可以使用AC算法。 +一个是单个点的评分,分两部分:生成和评分 +生成找棋子所成矩阵边长+2的矩阵 +评分用原来整体评分+下了棋后米字形的自己方棋的增加分-下了棋后米字形的对方棋的减少分(如果评分不是整数的就要事先算出各种情况的增分和减分)或者用原先的整体评价函数来评分 +以此分数做alpha-beta剪枝即可。