c/c++趣味小游戏集

趣味字符界面小游戏集。源码取自或参考网络,可以在Dev-C++中编译的c/c++趣味小游戏。

特别提示:1、走迷宫游戏和推箱子中的黑方块符号,若不会输入可用“囗”(wéi)字代替;2、windows10中使用Dev-C++编译运行没问题,但在windows11中发现失真——对不齐。

一、走迷宫游戏

能随机生成迷宫,用方向键移动A,从“入”口走到“出”口。

源码如下:

#include #include #include #include #define Height 25 //迷宫的高度,必须为奇数#define Width 25 //迷宫的宽度,必须为奇数#define Wall 1#define Road 0#define Start 2#define End 3#define Esc 5#define Up 1#define Down 2#define Left 3#define Right 4int map[Height+2][Width+2];void gotoxy(int x,int y) //移动坐标 {COORD coord;coord.X=x;coord.Y=y;SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), coord );}void hidden()//隐藏光标{HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO cci;GetConsoleCursorInfo(hOut,&cci);cci.bVisible=0;//赋1为显示,赋0为隐藏SetConsoleCursorInfo(hOut,&cci);}void create(int x,int y) //随机生成迷{int c[4][2]= {0,1,1,0,0,-1,-1,0};//四个方向int i,j,t;//将方向打乱for (i=0;i<4;i++) {j=rand()%4;t=c[i][0];c[i][0]=c[j][0];c[j][0]=t;t=c[i][1];c[i][1]=c[j][1];c[j][1]=t;}map[x][y]=Road;for (i=0;i<4;i++)if(map[x+2*c[i][0]][y+2*c[i][1]]==Wall) {map[x+c[i][0]][y+c[i][1]]=Road;create(x+2*c[i][0],y+2*c[i][1]);}}int get_key() //接收按键 {char c;while(c=getch()) {if(c==27) return Esc;//Escif(c!=-32)continue;c=getch();if(c==72) return Up;//上if(c==80) return Down;//下if(c==75) return Left;//左if(c==77) return Right;//右}return 0;}void paint(int x,int y) //画迷宫 {gotoxy(2*y-2,x-1);switch(map[x][y]) {case Start:printf("入");break;//画入口case End:printf("出");break;//画出口case Wall:printf("▇");break;//画墙case Road:printf(" ");break;//画路}}void game() {int x=2,y=1;//玩家当前位置,刚开始在入口处int c;//用来接收按键while(1) {gotoxy(2*y-2,x-1);printf("A");//画出玩家当前位置if(map[x][y]==End) //判断是否到达出口 {gotoxy(30,24);printf("\n");//printf("到达终点,按任意键结束");getch();break;}c=get_key();if(c==Esc) {gotoxy(0,24);break;}switch(c) {case Up: //向上走if(map[x-1][y]!=Wall) {paint(x,y);x--;}break;case Down: //向下走if(map[x+1][y]!=Wall) {paint(x,y);x++;}break;case Left: //向左走if(map[x][y-1]!=Wall) {paint(x,y);y--;}break;case Right: //向右走if(map[x][y+1]!=Wall) {paint(x,y);y++;}break;}}}int main() {int i,j;srand((unsigned)time(NULL));//初始化随即种子hidden();//隐藏光标for (i=0;i<=Height+1;i++)for (j=0;j<=Width+1;j++)if(i==0||i==Height+1||j==0||j==Width+1) //初始化迷宫map[i][j]=Road; else map[i][j]=Wall;create(2*(rand()%(Height/2)+1),2*(rand()%(Width/2)+1));//从随机一个点开始生成迷宫,该点行列都为偶数for (i=0;i<=Height+1;i++) //边界处理 {map[i][0]=Wall;map[i][Width+1]=Wall;}for (j=0;j<=Width+1;j++) //边界处理 {map[0][j]=Wall;map[Height+1][j]=Wall;}map[2][1]=Start;//给定入口map[Height-1][Width]=End;//给定出口for (i=1;i<=Height;i++)for (j=1;j<=Width;j++) //画出迷宫paint(i,j);game();//开始游戏getch();return 0;}

二、推箱子

源码:

#include #include #include intmap[2][7][8] ={//0:空的 1:■ :墙//3:☆ 4:★//目的地和箱子//5:※//人//7:⊙//目的(3)和箱子(4)在一起//8:※//人(5)和目的(3)在一起//为让多种情况使用一种算法{1, 1, 1, 1, 1, 1, 1, 1,1, 0, 0, 0, 0, 0, 0, 1,1, 3, 1, 0, 1, 1, 3, 1,1, 4, 0, 0, 4, 0, 3, 1,1, 0, 1, 0, 1, 1, 4, 1,1, 0, 0, 5, 0, 0, 0, 1,1, 1, 1, 1, 1, 1, 1, 1},{1, 1, 1, 1, 1, 1, 1, 1,1, 0, 0, 0, 0, 0, 0, 1,1, 3, 1, 0, 1, 1, 3, 1,1, 3, 4, 5, 4, 0, 3, 1,1, 4, 1, 0, 1, 1, 4, 1,1, 0, 0, 0, 0, 0, 0, 1,1, 1, 1, 1, 1, 1, 1, 1}};int cas = 0;//为0表示第一关//记录每一关的箱子数 或者是项目和目的在一起的总数int boxSum[2] = {3,4};//地图绘图void drawMap(){for (int i = 0; i < 7; i++){for (int j = 0; j < 8; j++){if (j == 0)printf("\t\t");switch (map[cas][i][j]){////0:空的 1:■ :墙case 0:printf("");break;case 1:printf("■");break;//3:☆ 4:★//目的地和箱子case 3:printf("☆");break;case 4:printf("★");break;//5:※//人case 5:case 8:printf("※");break;case 7:printf("⊙");break;//7:⊙//目的(3)和箱子(4)在一起//8:※//人(5)和目的(3)在一起}}printf("\n");}}//按键处理void keyDown(){//分析按键过程//定位人在哪里//人有两种情况:第一个是:人,第二个:人站在目的上int i, j;for (i = 0; i < 7; i++){for (j = 0; j < 8; j++){if (map[cas][i][j] == 5 || map[cas][i][j] == 8){break;}}if (map[cas][i][j] == 5 || map[cas][i][j] == 8){break;}}char ch = _getch();//看不见的字符输入,+头文件 conio.hswitch (ch){//72 80 75 77case 'w':case 'W':case 72://下一个地方等于空地或者是目的 能走if (map[cas][i - 1][j] == 0 || map[cas][i - 1][j] == 3){//3+5=8 :表示目的和人在一起//新地方(map[i-1][j])人(5)来了map[cas][i - 1][j] += 5;//老地方(map[i][j])人(5)走了map[cas][i][j] -= 5;}//如果下一个是箱子,要进一步判断能走//注意点:箱子两种状态:箱子,箱子和目的在一起else if (map[cas][i - 1][j] == 4 || map[cas][i - 1][j] == 7){//做箱子的下一个地方判断能不能走if (map[cas][i - 2][j] == 0 || map[cas][i - 2][j] == 3){//新的地方箱子来了map[cas][i - 2][j] += 4;//箱子的位置:箱子(-4)走了 人来(+5)map[cas][i - 1][j] += 1;//原来的地方人走了map[cas][i][j] -= 5;}}break;case 's':case 'S':case 80://下一个地方等于空地或者是目的 能走if (map[cas][i + 1][j] == 0 || map[cas][i + 1][j] == 3){//3+5=8 :表示目的和人在一起//新地方(map[i-1][j])人(5)来了map[cas][i + 1][j] += 5;//老地方(map[i][j])人(5)走了map[cas][i][j] -= 5;}else if (map[cas][i + 1][j] == 4 || map[cas][i + 1][j] == 7){//做箱子的下一个地方判断能不能走if (map[cas][i + 2][j] == 0 || map[cas][i + 2][j] == 3){//新的地方箱子来了map[cas][i + 2][j] += 4;//箱子的位置:箱子(-4)走了 人来(+5)map[cas][i + 1][j] += 1;//原来的地方人走了map[cas][i][j] -= 5;}}break;case 'a':case 'A':case 75://下一个地方等于空地或者是目的 能走if (map[cas][i][j - 1] == 0 || map[cas][i][j - 1] == 3){//3+5=8 :表示目的和人在一起//新地方(map[i-1][j])人(5)来了map[cas][i][j - 1] = map[cas][i][j - 1] + 5;//老地方(map[i][j])人(5)走了map[cas][i][j] = map[cas][i][j] - 5;//j+=5j=j+5}else if (map[cas][i][j - 1] == 4 || map[cas][i][j - 1] == 7){//做箱子的下一个地方判断能不能走if (map[cas][i][j - 2] == 0 || map[cas][i][j - 2] == 3){//新的地方箱子来了map[cas][i][j - 2] += 4;//箱子的位置:箱子(-4)走了 人来(+5)map[cas][i][j - 1] += 1;//原来的地方人走了map[cas][i][j] -= 5;}}break;case 'D':case 'd':case 77://下一个地方等于空地或者是目的 能走if (map[cas][i][j + 1] == 0 || map[cas][i][j + 1] == 3){//3+5=8 :表示目的和人在一起//新地方(map[i-1][j])人(5)来了map[cas][i][j + 1] += 5;//老地方(map[i][j])人(5)走了map[cas][i][j] -= 5;}//下一个地方是箱子,判断箱子的下一个地方是不是目的和空地else if (map[cas][i][j + 1] == 4 || map[cas][i][j + 1] == 7){//做箱子的下一个地方判断能不能走if (map[cas][i][j + 2] == 0 || map[cas][i][j + 2] == 3){//新的地方箱子来了map[cas][i][j + 2] += 4;//箱子的位置:箱子(-4)走了 人来(+5)map[cas][i][j + 1] += 1;//原来的地方人走了map[cas][i][j] -= 5;}}break;}}//胜负判断//用什么判断胜负: 箱子到达目的的个数int gameOver(){int count = 0;//所有的地方找一遍for (int i = 0; i < 7; i++){for (int j = 0; j < 8; j++){if (map[cas][i][j] == 7)count++;}}return count;}//箱子数是零的时候也是胜利int gameOver2(){int count = 3;//所有的地方找一遍for (int i = 0; i < 7; i++){for (int j = 0; j < 8; j++){if (map[cas][i][j] == 3)count--;}}return count;}int main(){while (1){printf("\n\t用方向键或w a s d键移动※推动★进入☆\n",cas+1);printf("\n\t\t 共两关 第 %d 关\n",cas+1);drawMap();if (gameOver() == boxSum[cas]){cas++;if (cas == 2)break;elseprintf("\n\t\t 该关 OK!按任一键进继续\n");}keyDown();system("cls");}printf("游戏结束!");printf("\n");system("pause");return 0;}

三、汉诺塔

源码如下:

#include #include #include using namespace std;const int COLUMN[4] = { 0, 2, 5, 8 };const int DISC_CNT_MAX = 10;const int ROW_OP_CNT = 2, COL_OP_CNT = 16;const int ROW_MESSAGE = 3, COL_MESSAGE = 16;const int ROW_HELP = 15, COL_HELP = 1;const int ROW_MAX = 30, COL_MAX = 120;const int BLUE = 1;const int GREEN = 2;const int CYAN = 3;const int AQUA = 3;const int RED = 4;const int PURPLE = 5;const int YELLOW = 6;const int WHITE = 7;int n;stack rod[4];int sz[4] = { 0 };int pos1, pos2;int key;bool prev_key_is_esc;int op_cnt;bool is_moving;int moved_disc;template inline T read() {T x = 0;T multiplier = 1;char ch = getchar();while (ch  '9') {if (ch == '-') {multiplier = -1;}ch = getchar();}while (ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch & 15);ch = getchar();}return x * multiplier;}void set_caret_pos(int row = 1, int col = 1) {COORD pos;pos.X = col - 1;pos.Y = row - 1;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);}int get_caret_row() {CONSOLE_SCREEN_BUFFER_INFO info;GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);return info.dwCursorPosition.Y + 1;}int get_caret_col() {CONSOLE_SCREEN_BUFFER_INFO info;GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);return info.dwCursorPosition.X + 1;}pair get_caret_pos() {CONSOLE_SCREEN_BUFFER_INFO info;GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);return make_pair(info.dwCursorPosition.Y + 1, info.dwCursorPosition.X + 1);}void set_foreground_color(int x, bool intensity = false) {SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x | (intensity << 3));}void set_cursor_visibility(bool visibility = true) {CONSOLE_CURSOR_INFO cc_info;cc_info.bVisible = visibility;cc_info.dwSize = 1;SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cc_info);}void disp_init_state(int n) {for (int i = 1; i <= n; i++) {set_caret_pos(i, COLUMN[1]);printf("%d", i);}for (int i = 1; i <= 3; i++) {set_caret_pos(n + 1, COLUMN[i] - 1);printf("---");set_caret_pos(n + 2, COLUMN[i]);putchar('A' + i - 1);} set_caret_pos(ROW_OP_CNT, COL_OP_CNT);printf("0");}void disp_help() {set_caret_pos(ROW_HELP, COL_HELP);printf("如何玩:\n" "数字表示光盘的尺寸.\n" "将A杆上圆盘移动到C杆上,每次一个.\n" "每个杆上的圆盘必须按大小升序堆叠.\n" "使用左右箭头键选择杆.\n" "按Enter键拾取选定杆上的顶部圆盘.\n" "然后使用左右键移动.\n" "按ESC取消当前移动.\n" "再次按Enter键可将圆盘放置.\n" "按R重新启动.\n" "按ESC键两次退出.\n");}void disp_pos(int pos1, int pos2 = 0) {for (int i = 1; i <= 3; i++) {set_caret_pos(n + 3, COLUMN[i]);printf(" ");}set_caret_pos(n + 3, COLUMN[pos1]);printf("^");if (pos2) {set_caret_pos(n + 3, COLUMN[pos2]);set_foreground_color(GREEN, true);printf("^");set_foreground_color(WHITE);}}void clear() {for (int i = 1; i <= DISC_CNT_MAX + 3; i++) {for (int j = 1; j <= COL_MAX; j++) {set_caret_pos(i, j);putchar(' ');}}}void moving_disc(int pos1, int pos2) {int x = rod[pos1].top(); set_caret_pos(n + 1 - sz[pos1], COLUMN[pos1]);set_foreground_color(RED, true);printf("%d", x);set_foreground_color(WHITE); set_caret_pos(n - sz[pos2] + (pos1 == pos2), COLUMN[pos2]);set_foreground_color(GREEN, true);printf("%d", x);set_foreground_color(WHITE);}void update_discs(int pos1, int pos2) {int x = rod[pos1].top(); set_caret_pos(n + 1 - sz[pos1], COLUMN[pos1]);printf("");rod[pos1].pop();sz[pos1]--; rod[pos2].push(x);sz[pos2]++;set_caret_pos(n + 1 - sz[pos2], COLUMN[pos2]);printf("%d", x);}void remove_temp_disc(int pos) {set_caret_pos(n - sz[pos], COLUMN[pos]);printf("");}void update_op_cnt() {op_cnt++;set_caret_pos(ROW_OP_CNT, COL_OP_CNT);printf("%d", op_cnt);}int main() {printf("输入光盘数量(不超过 %d): ", DISC_CNT_MAX);n = min(read(), DISC_CNT_MAX); set_cursor_visibility(false);disp_help(); for (; n <= DISC_CNT_MAX; n++) {clear(); for (int i = 1; i = 1; i--) {rod[1].push(i);}sz[1] = n; is_moving = false;pos1 = 1;op_cnt = 0;prev_key_is_esc = false; disp_init_state(n);disp_pos(1);while (true) {if (sz[3] == n) {set_caret_pos(ROW_MESSAGE, COL_MESSAGE);if (op_cnt != (1 << n) - 1) {printf("你用%d个动作完成了谜题.",op_cnt);} else {printf("祝贺你用最少的动作完成了谜题 " );}Sleep(2000);break;} key = getch();if (key == 224) {key = getch();if (!is_moving) {if (key == 75) { // Left arrow keypos1 = (pos1 + 1) % 3 + 1;} else if (key == 77) { // Right arrow keypos1 = pos1 % 3 + 1;}disp_pos(pos1);} else {remove_temp_disc(pos2);if (key == 75) { // Left arrow keypos2 = (pos2 + 1) % 3 + 1;} else if (key == 77) { // Right arrow keypos2 = pos2 % 3 + 1;}moving_disc(pos1, pos2);disp_pos(pos1, pos2);}} else if (key == 13) { // Enter keyif (!is_moving) {if (rod[pos1].empty()) {continue;}is_moving = true;moved_disc = rod[pos1].top();pos2 = pos1;moving_disc(pos1, pos2);disp_pos(pos1, pos2);} else {if (!rod[pos2].empty() && rod[pos2].top() < moved_disc) {set_caret_pos(ROW_MESSAGE, COL_MESSAGE);printf("提示:光盘未按升序堆叠在棒上。");continue;}is_moving = false;update_discs(pos1, pos2);update_op_cnt();pos1 = pos2;disp_pos(pos1);}} else if (key == 27) { // Escape keyif (prev_key_is_esc) { // Double ESCbreak;}if (is_moving) {is_moving = false;remove_temp_disc(pos2);update_discs(pos1, pos1);disp_pos(pos1);} else {prev_key_is_esc = true;}} else if (key == 'R' || key == 'r') {n--;break;}} if (prev_key_is_esc && key == 27) { // Double ESCbreak;}} set_caret_pos(ROW_MAX - 1, 1); return 0;}

四、贪吃蛇

源码如下:

#include #include #include #include #include #include #include using namespace std; /*** 光标定位 ***/HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);COORD coord; void locate(int x,int y){coord.X=y;coord.Y=x;SetConsoleCursorPosition(hout,coord);}; /*** 隐藏光标 ***/void hide(){CONSOLE_CURSOR_INFO cursor_info={1,0};SetConsoleCursorInfo(hout, &cursor_info);} /*** 生成随机数 ***/double random(double start, double end){return start+(end-start)*rand()/(RAND_MAX + 1.0);} /*** 定义地图的长宽,蛇的坐标,长度,方向,食物的位置 ***/int m,n; struct node{int x,y;}snake[1000]; int snake_length,dir;node food;int direct[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; /*** 输出墙 ***/void print_wall(){cout << " ";for (int i=1;i<=n;i++)cout << "-";cout << endl;for (int j=0;j<=m-1;j++){cout << "|";for (int i=1;i<=n;i++) cout << " ";cout << "|" << endl;}cout << " ";for (int i=1;i<=n;i++)cout << "-";} /*** 首次输出蛇,其中snake[0]代表头 ***/void print_snake(){locate(snake[0].x,snake[0].y);cout << "@";for (int i=1;i<=snake_length-1;i++){locate(snake[i].x,snake[i].y);cout << "*";}} /*** 判断是否撞墙或者自撞 ***/bool is_correct(){if (snake[0].x==0 || snake[0].y==0 || snake[0].x==m+1 || snake[0].y==n+1) return false;for (int i=1;i<=snake_length-1;i++){if (snake[0].x==snake[i].x && snake[0].y==snake[i].y) return false;}return true;} /*** 随机生成并输出食物位置 ***/bool print_food(){srand((unsigned)time(0));bool e;while (1){e=true;int i=(int) random(0,m)+1,j=(int) random(0,n)+1;food.x=i;food.y=j;for (int k=0;k<=snake_length-1;k++){if (snake[k].x==food.x && snake[k].y==food.y){e=false;break;}}if (e) break;}locate(food.x,food.y);cout <=1;i--)snake[i]=snake[i-1];snake[0].x+=direct[dir][0];snake[0].y+=direct[dir][1];locate(snake[1].x,snake[1].y);cout << "*";/*** 吃到了食物 ***/if (snake[0].x==food.x && snake[0].y==food.y){snake_length++;e=true;snake[snake_length-1]=temp;}/*** 输出此时蛇状态 ***/if (!e){locate(temp.x,temp.y);cout << " ";}elseprint_food();locate(snake[0].x,snake[0].y);cout << "@";/*** 如果自撞 ***/if (!is_correct()){system("cls");cout << "You lose!" << endl << "Length: " << snake_length << endl;return false;}return true;} /*** 主函数 ***/int main(){system("mode con cols=80 lines=30"); //设置cmd窗口大小system("color 2"); //设置字符颜色:0 黑;1 深蓝;2 深绿;3 深青;4 深红;5 深紫;6 深褐 cout << "--------------------贪吃蛇---------------------" << endl;cout << "先选择难度.请在1-10中输入1个数,1最简单,10则最难" << endl;cout << "然后进入游戏画面,以方向键控制方向.祝你游戏愉快!" << endl;cout << "-----------------------------------------------" << endl;cout << "请输入难度级别:" ;m=25;n=40; if (m<10 || n25 || n>40){cout << "ERROR" <> hard;if (hard100){cout << "ERROR" << endl;system("pause");return 0;}/*** 数据全部初始化,包括蛇长,位置,方向 ***/snake_length=5;clock_t a,b;char ch;double hard_len;for (int i=0;i<=4;i++){snake[i].x=1;snake[i].y=5-i;}dir=3;/*** 输出初始地图,蛇与食物 ***/system("cls");hide();print_wall();print_food();print_snake();locate(m+2,0);cout <=(int)(400-30*hard)*(1-sqrt(hard_len))) break;}/*** 接受键盘输入的上下左右,并以此改变方向 ***/if (kbhit()){ch=getch();if (ch==-32){ch=getch();switch(ch){case 72:if (dir==2 || dir==3)dir=0;break;case 80:if (dir==2 || dir==3)dir=1;break;case 75:if (dir==0 || dir==1)dir=2;break;case 77:if (dir==0 || dir==1)dir=3;break;}}}/*** 前进 ***/if (!go_ahead()) break;/*** 在最后输出此时长度 ***/locate(m+2,12);cout << snake_length;}system("pause");return 0;}

附录、C++控制cmd窗口最大化

//cmd窗口最大化控制#include#includeusing namespace std; HWND hwnd=GetForegroundWindow();//使hwnd代表最前端的窗口int main(){//ShowWindow(hwnd,SW_MINIMIZE);//最小化 hwnd所代表的窗口ShowWindow(hwnd,SW_MAXIMIZE);//最大化 hwnd 所代表的窗口 return 0;}