加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
cgame3(life)v4.cpp 11.53 KB
一键复制 编辑 原始数据 按行查看 历史
Anbang24 提交于 2021-01-26 09:51 . 第3章 康威生命游戏
//https://gitee.com/devcpp/cgames anbangli@foxmail.com GNU GPL v3
//cgame3(life)v4 康威生命游戏第4版:扩展初始化模式
#include <iostream>
#include <cstdlib>
#include <Windows.h>
#include <conio.h>
using namespace std;
const int WD = 38, HT = 20; //游戏地图的宽度(Width)和高度(Height)
bool map[HT][WD] = {0}; //定义存储数据信息的二维数组
bool periodic = true; //是否使用周期性边界条件
bool initMap() { //初始化地图
system("cls"); //调用 Windows 终端窗口下的 cls 命令,清空屏幕
cout << "** 生命游戏 (Conway's Life Game) ** \n\n";
cout << "\r生命初始设置 \n"
<< " 1: 随机分布\n"
<< " 2: 静止生命:方块、蜂窝、长面包、小船、轮船、浴缸和池塘\n"
<< " 3: 振荡器:闪烁灯、蟾蜍、灯塔信标和蜂王穿梭机\n"
<< " 4: 振荡器:圆圈与火花\n"
<< " 5: 宇宙飞船:滑翔机(斜向右下方)\n"
<< " 6: 宇宙飞船:中型飞船(从右向左)\n"
<< " 7: 宇宙飞船:拖鞋(从右向左)\n"
<< " 8: 宇宙飞船:铜头(从下向上)\n"
<< " 9: 高斯帕滑翔机枪(向右下方发射滑翔机)\n"
<< " 0: 退出程序\n"
<< "请选择:";
int ix, iy, select = 0;
cin >> select;
if (select == 0)
return false;
periodic = true; //默认为周期边界条件(仅有某些特定模式需要非周期性边界条件)
char st[HT][WD + 1] = {""}; //定义二维数组并全部初始化为空字符
if (select == 1) {
cout << "初始随机分布:30% 存活 " << endl;
for (iy = 0; iy < HT; iy++) //行循环
for (ix = 0; ix < WD; ix++) //列循环
st[iy][ix] = ((rand() % 10) < 3) ? '@' : '+';
} else if (select == 2) { //静止生命体模式图形
//Define a char array and initialized as special pattern.
//It is easy to initialize char arrays than integer arrays.
//"+" denotes 0, "@" denotes 1;
//方块(Block)、蜂窝(Beehive)、长面包(loaf)、小舟(Boat)
strcpy(st[0], "++++++++++++++++++++++++++++++++++");
strcpy(st[1], "++@@++++@@+++++@@++++@@+++");
strcpy(st[2], "++@@+++@++@+++@++@+++@+@++");
strcpy(st[3], "++++++++@@+++++@+@++++@+++");
strcpy(st[4], "++++++++++++++++@+++++++++");
strcpy(st[5], "++++++++++++++++++++++++++");
//轮船(ship)、浴缸(Tub)和池塘(pond)
strcpy(st[6], "++++++++++++++++++++++++++");
strcpy(st[7], "++@@+++++@+++++@@+++++++++");
strcpy(st[8], "++@+@+++@+@+++@++@++++++++");
strcpy(st[9], "+++@@++++@++++@++@++++++++");
strcpy(st[10], "+++++++++++++++@@+++++++++");
strcpy(st[11], "++++++++++++++++++++++++++");
} else if (select == 3) { //振荡器
//闪烁灯(blinker)、蟾蜍(toad)、灯塔信标(beacon)和蜂王穿梭机
strcpy(st[0], "++++++++++++++++++++++++++++++++++");
strcpy(st[1], "++++++++++++++++++++++++++++++++++");
strcpy(st[2], "++++++++++++@@++++++@@++++++++++++");
strcpy(st[3], "+++@@@+++++@++++++++@@++++++++++++");
strcpy(st[4], "++++++++++++++@+++++++@@++++++++++");
strcpy(st[5], "++++++++++++@@++++++++@@++++++++++");
strcpy(st[6], "++++++++++++++++++++++++++++++++++");
strcpy(st[7], "++++++++++++++++++++++++++++++++++");
strcpy(st[8], "++++++++++++++++++++++++++++++++++");
strcpy(st[9], "++++++++++++++@+++++++++++++++++++");
strcpy(st[10], "++++++++++++@+@+++++++++++++++++++");
strcpy(st[11], "+++++++++++@+@++++++++++++++++++++");
strcpy(st[12], "+++++@@+++@++@+++++++++++@@+++++++");
strcpy(st[13], "+++++@@++++@+@+++++++++++@@+++++++");
strcpy(st[14], "++++++++++++@+@+++++++++++++++++++");
strcpy(st[15], "++++++++++++++@+++++++++++++++++++");
strcpy(st[16], "++++++++++++++++++++++++++++++++++");
} else if (select == 4) { //振荡器2
strcpy(st[0], "++++++++++++++++++++++++++++++++++");
strcpy(st[1], "++++++++++++++++++++++++++++++++++");
strcpy(st[2], "++++++++++++++@@@+++@@@+++++++++++");
strcpy(st[3], "++++++++++++++++++++++++++++++++++");
strcpy(st[4], "++++++++++++@++++@+@++++@+++++++++");
strcpy(st[5], "++++++++++++@++++@+@++++@+++++++++");
strcpy(st[6], "++++++++++++@++++@+@++++@+++++++++");
strcpy(st[7], "++++++++++++++@@@+++@@@+++++++++++");
strcpy(st[8], "++++++++++++++++++++++++++++++++++");
strcpy(st[9], "++++++++++++++@@@+++@@@+++++++++++");
strcpy(st[10], "++++++++++++@++++@+@++++@+++++++++");
strcpy(st[11], "++++++++++++@++++@+@++++@+++++++++");
strcpy(st[12], "++++++++++++@++++@+@++++@+++++++++");
strcpy(st[13], "++++++++++++++++++++++++++++++++++");
strcpy(st[14], "++++++++++++++@@@+++@@@+++++++++++");
strcpy(st[15], "++++++++++++++++++++++++++++++++++");
strcpy(st[16], "++++++++++++++++++++++++++++++++++");
} else if (select == 5) { //滑翔机
strcpy(st[0], "++++++++++++++++++++++++++++++++++");
strcpy(st[1], "++++++++++++++++++++++++++++++++++");
strcpy(st[2], "+++++@++++++++++++++++++++++++++++");
strcpy(st[3], "++++++@+++++++++++++++++++++++++++");
strcpy(st[4], "++++@@@+++++++++++++++++++++++++++");
} else if (select == 6) { //中型飞船
strcpy(st[0], "++++++++++++++++++++++++++++++++++");
strcpy(st[1], "+++++++++++++++@++++++++++++");
strcpy(st[2], "+++++++++++++@+++@++++++++");
strcpy(st[3], "++++++++++++@++++++++++++");
strcpy(st[4], "++++++++++++@++++@+++++++");
strcpy(st[5], "++++++++++++@@@@@++++++++");
strcpy(st[6], "++++++++++++++++++++++++++++++++++");
strcpy(st[7], "++++++++++++++++++++++++++++++++++");
} else if (select == 7) { //拖鞋
strcpy(st[8], "++++++++++++++++++++++++++++++++++");
strcpy(st[9], "+++++++++@@++@+@@+++++++++++++++++");
strcpy(st[10], "++++++++@++@++@@++++++++++++++++++");
strcpy(st[11], "+++++++++@+@++++++++++++++++++++++");
strcpy(st[12], "++++++++++@+++++++++++++++++++++++");
strcpy(st[13], "++++++++++++++++@+++++++++++++++++");
strcpy(st[14], "++++++++++++++@@@+++++++++++++++++");
strcpy(st[15], "+++++++++++++@++++++++++++++++++++");
strcpy(st[16], "++++++++++++++@+++++++++++++++++++");
strcpy(st[17], "+++++++++++++++@@+++++++++++++++++");
strcpy(st[18], "++++++++++++++++++++++++++++++++++");
} else if (select == 8) { //铜头(从下向上)
strcpy(st[0], "++++++++++++++++++++++++++++++++++");
strcpy(st[1], "++++++++++++++++++++++++++++++++++");
strcpy(st[2], "++++++++++++++++++++++++++++++++++");
strcpy(st[3], "++++++++++++++++++++++++++++++++++");
strcpy(st[4], "+++++++++++++@@++@@+++++++++++++++");
strcpy(st[5], "+++++++++++++++@@+++++++++++++++++");
strcpy(st[6], "+++++++++++++++@@+++++++++++++++++");
strcpy(st[7], "++++++++++++@+@++@+@++++++++++++++");
strcpy(st[8], "++++++++++++@++++++@++++++++++++++");
strcpy(st[9], "++++++++++++++++++++++++++++++++++");
strcpy(st[10], "++++++++++++@++++++@++++++++++++++");
strcpy(st[11], "+++++++++++++@@++@@+++++++++++++++");
strcpy(st[12], "++++++++++++++@@@@++++++++++++++++");
strcpy(st[13], "++++++++++++++++++++++++++++++++++");
strcpy(st[14], "+++++++++++++++@@+++++++++++++++++");
strcpy(st[15], "+++++++++++++++@@+++++++++++++++++");
strcpy(st[16], "++++++++++++++++++++++++++++++++++");
} else if (select == 9) { //高斯帕滑翔机枪(Gosper glider gun)
//reference: http://www.cplusplus.com/forum/lounge/75168/
strcpy(st[0], "+++++++++++++++++++++++++++++++++++++");
strcpy(st[1], "+++++++++++++++++++++++++++++++++++++");
strcpy(st[2], "+++++++++++++++++++++++++@+++++++++++");
strcpy(st[3], "+++++++++++++++++++++++@+@+++++++++++");
strcpy(st[4], "+++++++++++++@@++++++@@++++++++++++@@");
strcpy(st[5], "++++++++++++@+++@++++@@++++++++++++@@");
strcpy(st[6], "+@@++++++++@+++++@+++@@++++++++++++++");
strcpy(st[7], "+@@++++++++@+++@+@@++++@+@+++++++++++");
strcpy(st[8], "+++++++++++@+++++@+++++++@+++++++++++");
strcpy(st[9], "++++++++++++@+++@++++++++++++++++++++");
strcpy(st[10], "+++++++++++++@@++++++++++++++++++++++");
strcpy(st[11], "+++++++++++++++++++++++++++++++++++++");
periodic = false; //非周期性边界条件
} else {
cout << "选择错误,退出程序。" << endl;
return false;
}
for (int iy = 0; iy < HT; iy++)
for (int ix = 0; ix < WD; ix++)
map[iy][ix] = (st[iy][ix] == '@' ? true : false);
return true;
}
void gotoxy(short x, short y) { //控制台窗口光标定位
COORD crd = {x, y}; //定义 COORD 类型(窗口坐标)的变量 crd 并以形参x和y初始化
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), crd);
//GetStdHandle获取控制台输出句柄并用SetConsoleCursorPosition设置光标位置
return;
}
void drawMap() { //绘制地图
gotoxy(0, 0);
int ix, iy;
for (iy = 0; iy < HT; iy++) { //行循环
for (ix = 0; ix < WD; ix++) //列循环
cout << (map[iy][ix] ? "█" : "□");
cout << endl;
}
return;
}
void updateMap() { //根据游戏规则更新地图
static bool bak[HT + 1][WD + 1] = {0}; //更新前用于备份当前地图数据
int ix, iy, up, dn, lft, rht, cnt;
//备份当前地图数据用于更新
for (iy = 0; iy < HT; iy++)
for (ix = 0; ix < WD; ix++)
bak[iy][ix] = map[iy][ix];
//计算每个格点周围的生命体个数并据此更新其生死状态
for (iy = 0; iy < HT; iy++) {
for (ix = 0; ix < WD; ix++) {
lft = (ix + WD - 1) % WD;
rht = (ix + WD + 1) % WD;
up = (iy + HT - 1) % HT; //屏幕上绘出的地图的Y值为上小下大
dn = (iy + HT + 1) % HT;
if (!periodic) { //非周期性边界条件下,必要时调整上下行数或左右列数
lft = (lft == WD - 1 ? WD : lft);
rht = (rht == 0 ? WD : rht);
up = (up == HT - 1 ? HT : up);
dn = (dn == 0 ? HT : dn);
}
cnt = bak[up][lft] + bak[up][ix] + bak[up][rht]
+ bak[iy][lft] + bak[iy][rht]
+ bak[dn][lft] + bak[dn][ix] + bak[dn][rht];
if (!map[iy][ix] ) //若当前为死亡
map [iy][ix] = (cnt == 3 ? true : false); //转换为存活
else if (cnt == 2 || cnt == 3) //当前为存活且周围的存活生命数为2或3
map[iy][ix] = true; //保持存活
else //当前为存活且周围有的生命数小于2或大于3
map[iy][ix] = false; //存活转为死亡
}
}
}
int main() {
char key;
int round = 0; //更新轮数
if (!initMap()) //初始化地图或退出
return 0;
while (true) {
drawMap();//绘制地图
cout << "生命游戏。更新轮数:" << ++round << endl;
cout << "空格键-暂停,ESC-设置或退出" << endl;
Sleep(200);
if (kbhit()) { //检测用户是否按键
key = getch(); //获取字符用作判断
if (key == ' ') { //空格键
cout << "已暂停。按任意键继续。" << endl;
getch();
continue;
}
if (key == 27) { //ESC键
if (!initMap()) //初始化地图或退出
break;
round = 0;
}
}
updateMap(); //根据游戏规则更新地图
}
cout << "\n游戏结束。谢谢使用。" << endl;
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化