Multithreading (Two)
May 12, 2018
Implemented to play music while playing Snake:
Cautions:
1. VS2017下async默认为launch:deffed,所以想要在future那句中启动线程需要在后面加上result1.get(),或者在future时,加上launch:async.
2. Once a thread is started, it will run until it finishes. 若想提前终止,需要在合适的时机return,若用result1._Abandon,线程会结束,但函数仍会继续运行,且有内存泄漏风险 (如果之前没释放的话).
3. 目前对线程的控制使用的是全局变量的方法,还没有涉及到同步化 (synchronization),如有需要请参见The C++ Standard Library 有关Mutex和Lock的部分。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <future> #include <thread> #include <algorithm> #include <cmath> #include <cstdlib> #include <exception> #include <string> #include <cstring> #include <ctime> #include <conio.h> #include <windows.h> #define b(a,b) Beep(a,b) #define m 10001 using namespace std; const int a1 = 220; //低音 由十二平均律计算得出 const int a2 = 247; const int a3 = 277; const int a4 = 294; const int a5 = 330; const int a6 = 370; const int a7 = 415; const int b1 = 440; //中音 const int b2 = 494; const int b3 = 554; const int b4 = 587; const int b5 = 659; const int b6 = 740; const int b7 = 831; const int c1 = 880; //高音 const int c2 = 988; const int c3 = 1109; const int c4 = 1175; const int c5 = 1319; const int c6 = 1480; const int c7 = 1661; const int fx[] = { 0,-1,1, 0,0 }; const int fy[] = { 0, 0,0,-1,1 }; char c = 'w'; int px, py, flag; int map[24][24], father[24][24]; int getint() { int _b = 0; char _c; for (_c = getchar(); _c < '0' || _c > '9'; _c = getchar()) ; for (; _c >= '0' && _c <= '9'; _c = getchar()) { _b *= 10; _b += _c - '0'; } return _b; } struct point { int x; int y; }; void clear() //24 ↑ 25 ↓ 26 → 27 ← { memset(map, 0, sizeof(map)); for (int i = 0; i <= 22; i++) { map[0][i] = 99; map[i][23] = 99; map[23][i + 1] = 99; map[i + 1][0] = 99; } } inline void print_first() { system("cls"); for (int i = 0; i <= 23; i++) { for (int j = 0; j <= 23; j++) { switch (map[i][j]) { case 0: { printf(" "); break; } case 1: //head { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_RED); printf("●"); break; } case 2: //body { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); printf("■"); break; } case 3: //food { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE); printf("●"); break; } case 99: { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_BLUE); printf("■"); break; } } } printf("\n"); } } inline int ret(int _a, int _b) { return _a * 25 + _b; } inline point rets(int num) { point _a; _a.x = num / 25; _a.y = num % 25; return _a; } void gotoxy(int x, int y) { COORD C; C.X = x * 2; C.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), C); } void print(int x, int y, int kp) { gotoxy(x, y); switch (kp) { case 0: { printf(" "); break; } case 1: //head { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_RED); printf("●"); break; } case 2: //body { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); printf("■"); break; } case 3: //food { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE); printf("●"); break; } case 99: { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_BLUE); printf("■"); break; } } } inline void setfood() { int l = 0; int r = 0; while (l == 0 || r == 0 || map[l][r] == 1 || map[l][r] == 2 || map[l][r] == 99) { l = rand() % 23; r = rand() % 23; } map[l][r] = 3; print(l, r, 3); } void music2() { int pai = 360; int a[m] = { b3,b3,b5,b6,c1,c1,b6,b5,b5,b6,b5,0, //茉莉花 b3,b3,b5,b6,c1,c1,b6,b5,b5,b6,b5,0, b5,b5,b5,b3,b5,b6,b6,b5,0, b3,b2,b3,b5,b3,b2,b1,b1,b2,b1,0, b3,b2,b1,b3,b2,b3,b5,b6,c1,b5,0, b2,b3,b5,b2,b3,b1,a6,a5,0, a6,b1,b2,b3,b1,b2,b1,a6,a5,0 }; int c22[m] = { 2,1,1,1,1,1,1,2,1,1,4,0, //节奏 2,1,1,1,1,1,1,2,1,1,4,0, 2,2,2,1,1,2,2,4,0, 2,1,1,2,1,1,2,1,1,4,0, 1,1,1,1,3,1,2,1,1,4,0, 2,1,1,1,1,1,1,4,0, 2,2,3,1,1,1,1,1,6,0 }; while (1) { for (int i = 0; i < 74; i++) { if (flag == 1 && a[i] == 0) //播放到这一句完 return; b(a[i], pai*c22[i]); } } system("cls"); } void snake(int aty) { system("cls"); srand((unsigned)time(0)); system("color 0b"); clear(); point head, tail; int sew = 1; //1 ↑ 2 ↓ 3 ← 4 → head.x = 12; head.y = 12; tail.x = 13; tail.y = 12; father[13][12] = ret(12, 12); map[12][12] = 1; print_first(); setfood(); gotoxy(12, 12); while (1) { Sleep(1000 / aty); while (_kbhit())c = _getch(); fir: switch (c) { case 'a': { if (sew != 2) sew = 1; break; } case 'd': { if (sew != 1) sew = 2; break; } case 'w': { if (sew != 4) sew = 3; break; } case 's': { if (sew != 3) sew = 4; break; } case 72: { c = 'w'; goto fir; break; } case 75: { c = 'a'; goto fir; break; } case 80: { c = 's'; goto fir; break; } case 77: { c = 'd'; goto fir; break; } } px = head.x + fx[sew]; py = head.y + fy[sew]; switch (map[px][py]) { case 0: { map[tail.x][tail.y] = 0; print(tail.x, tail.y, 0); point _po = rets(father[tail.x][tail.y]); tail.x = _po.x; tail.y = _po.y; map[head.x][head.y] = 2; print(head.x, head.y, 2); map[px][py] = 1; print(px, py, 1); father[head.x][head.y] = ret(px, py); head.x = px; head.y = py; break; } case 1: { cout << "Fuck!" << endl; break; } case 2: { map[tail.x][tail.y] = 0; map[head.x][head.y] = 2; map[px][py] = 1; print(tail.x, tail.y, 0); print(head.x, head.y, 2); print(px, py, 1); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); gotoxy(24, 24); printf("\nGame over!\n"); Sleep(1000); return; break; } case 3: { map[head.x][head.y] = 2; map[px][py] = 1; print(head.x, head.y, 2); print(px, py, 1); father[head.x][head.y] = ret(px, py); head.x = px; head.y = py; setfood(); break; } case 99: { map[tail.x][tail.y] = 0; map[head.x][head.y] = 2; map[px][py] = 1; print(tail.x, tail.y, 0); print(head.x, head.y, 2); print(px, py, 1); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); gotoxy(24, 24); printf("\nGame over!\n"); Sleep(1000); return; break; } } } } int main() { future<void> result1(async(launch::async, music2)); //启动线程 snake(8); //速度设置为8 flag = 1; return 0; }