今天和人吃晚饭突然想起来
之前西佳佳老师说小学期会要求两星期撸一个小游戏
有人已经撸完一个俄罗斯方块了...
菜逼我决定从最简单的贪吃蛇玩起...
我是直接参考的这个博客
算是相当简单而且很Low的实现了
在我看来
开始和结束界面不是重点
自己随意设计一下吧
然后贪吃蛇的活动问题
由定时清屏再输出字符矩阵来解决
果实位置当然由随机数获得
定时问题直接用ctime函数来计算
这里的开始界面也用到了
清屏再输出的方式进行了倒计时
对蛇身的记录可以使用双端队列deque
操作不是很多也可以手写
获取键盘读入的问题
可以用键盘扫描码来解决
上下左右分别为72 80 75 77
_kbhit()函数判断是否有键盘输入
默认除“上下左右”以外的输入直接导致游戏结束
另一个可行的方案就是使用WASD来控制方向
就不必使用键盘扫描码了
然后代码里虽然同时使用了getch 和 _getch
但其实这似乎只是不同库里的功能一样的函数...
最后放上相当简陋的代码(我好懒就没写注释)
1 #include<ctime> 2 #include<cstdio> 3 #include<conio.h> 4 #include<cstdlib> 5 6 #define map(pos) map[pos.x][pos.y] 7 8 char map[30][30]; 9 10 struct point { 11 int x, y; 12 13 void _rand() { 14 x = rand() % 20 + 1; 15 y = rand() % 20 + 1; 16 } 17 18 bool operator == (const point &a) const { 19 return x == a.x && y == a.y; 20 } 21 22 }; 23 24 int head, tail; 25 point snake[500], food, next; 26 int dir, grade, length, uptime; 27 28 inline void find_food() { 29 do { 30 food._rand(); 31 }while(map(food) != ' '); 32 map(food) = '*'; 33 } 34 35 inline void update() { 36 system("cls"); 37 puts(""); 38 for(int i = 0;i < 22;i ++) { 39 putchar(' '); 40 for(int j = 0;j < 22;j ++) 41 putchar(map[i][j]), putchar(' '); 42 if(i == 0) printf(" 等级为:%d", grade); 43 if(i == 2) printf(" 长度为:%d", length); 44 if(i == 6) printf(" 自动前进时间"); 45 if(i == 8) printf(" 间隔为:%d ms", uptime); 46 puts(""); 47 } 48 } 49 50 inline bool GO() { 51 bool timeover = 1; 52 double start = (double) clock() / CLOCKS_PER_SEC; 53 while((timeover = (double) clock() / CLOCKS_PER_SEC <= start + uptime / 1000.0) && !_CRTIMP::_kbhit()); 54 if(timeover) { 55 _getch(); 56 dir = _getch(); 57 } 58 next = snake[head]; 59 switch (dir) { 60 case 72:next.x -= 1;break; 61 case 80:next.x += 1;break; 62 case 75:next.y -= 1;break; 63 case 77:next.y += 1;break; 64 default: 65 puts(" Game over!"); 66 return 0; 67 } 68 if(!next.x || next.x == 21 || !next.y || next.y == 21) { 69 puts(" Game over!"); 70 return 0; 71 } 72 if(map(next) != ' ' && !(next == food)) { 73 puts(" Game over!"); 74 return 0; 75 } 76 if(length == 400) { 77 puts(" Good game!"); 78 return 0; 79 } 80 return 1; 81 } 82 83 int main() { 84 srand(19980320); 85 for(int i = 1;i <= 20;i ++) 86 for(int j = 1;j <= 20;j ++) 87 map[i][j] = ' '; 88 for(int i = 0;i < 22;i ++) 89 map[i][0] = map[21][i] = map[0][i] = map[i][21] = '!'; 90 map[1][1] = map[1][2] = 'o', map[1][3] = '@'; 91 snake[0] = (point){1, 1}; 92 snake[1] = (point){1, 2}; 93 snake[2] = (point){1, 3}; 94 head = 2, tail = 0, grade = 1, length = 3, uptime = 500; 95 find_food(), dir = 77; 96 97 puts(" 即将开始玩蛇!"); 98 double start; 99 for(int i = 3;i >= 0;i --) { 100 start = (double)clock() / CLOCKS_PER_SEC; 101 while((double)clock() / CLOCKS_PER_SEC <= start + 1); 102 if(i > 0) { 103 system("cls"); 104 printf(" 进入倒计时:%d ", i); 105 } 106 else { 107 update(); 108 } 109 } 110 111 while(1) { 112 if(GO()) { 113 if(next == food) { 114 length ++; 115 if(length % 10 == 0) { 116 grade ++; 117 if(uptime >= 100) uptime -= 50; 118 } 119 map(next) = '@'; 120 map(snake[head]) = 'o'; 121 head = (head + 1) % 500; 122 snake[head] = next; 123 find_food(), update(); 124 } 125 else { 126 map(snake[tail]) = ' '; 127 tail = (tail + 1) % 500; 128 map(next) = '@'; 129 map(snake[head]) = 'o'; 130 head = (head + 1) % 500; 131 snake[head] = next; 132 update(); 133 } 134 } 135 else break; 136 } 137 getch(); 138 return 0; 139 }
没有使用图形
开始界面还能接受
结束界面没有再来一局的提示
也没有最终分数的显示
有待改进
另外想写一个自动玩这个游戏的程序
不考虑最短路径的话
在nm不全为奇数的情况下是有必胜策略的
而这是比较好实现的
但还要考虑一下怎么把它自己玩的过程展现出来?
直接把游戏代码嵌入进去?那岂不是很蠢?
而考虑同等分数下的最少按键次数或最少移动次数呢?
似乎可以尝试用机器学习的方法来搞一搞?
都忘记到底是深度学习还是强化学习了...
但这似乎可能又与随机出来的果实位置有关?
机器学习的话,可以直接尝试让它自己学着玩这个游戏?
......
看上去比上一个想法更有实现的意义?
先到此为止