Just For Fun!
(下一步:AI模式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
/************************************************************************ > File Name: gluttonous_snake.cpp > Author: gou4shi1 > Mail: gou4shi1@qq.com > Created Time: 2016年05月17日 星期二 20时19分21秒 ************************************************************************/ #include <iostream> //cin cout #include <cstdlib> //srand();rand();system(); #include <ctime> //time(); #include <conio.h> //kbhit();getch(); #include <windows.h> //Sleep();SetWindow()、SetCursorPosition()、SetTextColorToXXX()内调用的函数 using namespace std; //把方向按顺时针顺序映射成数字 #define LEFT 0 #define UP 1 #define RIGHT 2 #define DOWN 3 //速度相关常量(每走一步后的等待时间越短,蛇走得越快): //t0:初始间隔时间;k:蛇身长度对速度的影响因子;min,max:控制间隔时间范围 const int sleep_time_t0 = 200,sleep_time_k = 25,sleep_time_min = 75,sleep_time_max = 250; //蛇可走的空间的范围、初始长度 const int snake_map_min = 1,snake_map_max = 18,snake_initila_len = 3; //向各方向走的坐标偏移量 const int dx[] = {-1,0,1,0}; const int dy[] = {0,-1,0,1}; //返回一个在[l,r]间的随机数 int random(int l,int r) { return l + rand() % (r - l + 1); //采用对区间大小求余的方法 } //设置窗口属性 void SetWindow() { SetConsoleTitle("gluttonous snake"); //设置窗口标题 COORD size = {100,60}; SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),size); //设置窗口缓存区大小 SMALL_RECT rect = {1,1,50,30}; SetConsoleWindowInfo(GetStdHandle(STD_OUTPUT_HANDLE),true,&rect); //设置窗口大小 } //设置光标位置 void SetCursorPosition(int x,int y) { COORD coord = {x,y}; //warning: narrowing conversion of 'x' from 'int' to 'SHORT {aka short int}' SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord); } //设置文本颜色为白色 void SetTextColorToWhite() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); } //设置文本颜色为红色 void SetTextColorToRed() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_INTENSITY); } //设置文本颜色为绿色 void SetTextColorToGreen() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN|FOREGROUND_INTENSITY); } //设置文本颜色为蓝色 void SetTextColorToBlue() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE|FOREGROUND_INTENSITY); } //设置文本颜色为黄色 void SetTextColorToYello() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY); } //在(x*2+1,y)处输出字符ch //x*2+1是为了美观整齐,故内在坐标与屏幕坐标存在这一映射关系 //控制台坐标系:原点为左上角;x轴正方向为向右;y轴正方向为向下; void print(int x,int y,char ch) { SetCursorPosition(x * 2 + 1,y); cout << ch; } //屏幕内容初始化 void ScreenInit() { system("cls"); //调用控制台命令清除屏幕内容 SetTextColorToWhite(); for (int i = snake_map_min - 1; i <= snake_map_max + 1; ++i) for (int j = snake_map_min - 1; j <= snake_map_max + 1; ++j) if (i < snake_map_min || i > snake_map_max || j < snake_map_min || j > snake_map_max) print(i,j,'#'); //输出白色的围墙 SetTextColorToGreen(); SetCursorPosition(25,25); cout << "-----copyright by cgq" << endl; //在右下角输出绿色的版权声明 } //蛇的结点,蛇采用链表实现 struct SNAKE_NODE { SNAKE_NODE(int X = 0,int Y = 0,SNAKE_NODE *SUC = NULL,SNAKE_NODE *PRE = NULL) : x(X),y(Y),suc(SUC),pre(PRE) {} int x,y; //坐标 SNAKE_NODE *suc,*pre; //前驱与后继 }; //蛇 class SNAKE { public: SNAKE(); //初始化蛇 void GenerateFood(); //生成食物 void ChangeDir(char); //改变方向 bool move(); //移动一步 bool exist(int x,int y) { return snake_map[x][y]; } //返回(x,y)处是否存在蛇 int GetLen() { return len; } //返回蛇身长度 private: void AddHead(int x,int y); //在蛇头前方(x,y)处插入结点 void DelTail(); //删除蛇尾结点 SNAKE_NODE *head,*tail; //分别指向蛇头与蛇尾 int dir,len,food_x,food_y; //前进方向,蛇身长度,食物坐标 bool snake_map[snake_map_max + 1][snake_map_max + 1]; //蛇身地图:true表示那一点有蛇 }; SNAKE::SNAKE() { food_x = food_y = 0; tail = head = NULL; for (int i = snake_map_min; i <= snake_map_max; ++i) for (int j = snake_map_min; j <= snake_map_max; ++j) snake_map[i][j] = false; len = 0; dir = random(0,3); int snake_initial_x = random(snake_map_min+snake_initila_len,snake_map_max-snake_initila_len); int snake_initial_y = random(snake_map_min+snake_initila_len,snake_map_max-snake_initila_len); //随机初始化蛇 for (int i = 0; i != snake_initila_len; ++i) AddHead(snake_initial_x + dx[dir] * i,snake_initial_y + dy[dir] * i); } void SNAKE::GenerateFood() { food_x = random(snake_map_min,snake_map_max); food_y = random(snake_map_min,snake_map_max); if (exist(food_x,food_y)) { GenerateFood(); //若随机出来的点有蛇,则再随机一蛇身次,此方案可保证蛇外各点生成食物的概率一样 return; } SetTextColorToRed(); print(food_x,food_y,'@'); //在食物处输出红色的'@'标志 SetCursorPosition(head->x * 2 + 1,head->y); //把光标位置设置为蛇头 } void SNAKE::ChangeDir(char x) { switch (x) //若x不是wasd之一,则方向不变 { case 'a' : //用wasd控制方向 case 'A' : if (dir != RIGHT) //当前方向为向左时,不能一下子变成向右,下同 dir = LEFT; break; case 'w' : case 'W' : if (dir != DOWN) dir = UP; break; case 'd' : case 'D' : if (dir != LEFT) dir = RIGHT; break; case 's' : case 'S' : if (dir != UP) dir = DOWN; break; } } bool SNAKE::move() { int x_new = head->x + dx[dir]; int y_new = head->y + dy[dir]; if (x_new < snake_map_min || x_new > snake_map_max) return false; if (y_new < snake_map_min || y_new > snake_map_max) return false; //若撞墙则返回false,游戏结束 if (exist(x_new,y_new)) //若撞蛇则返回false,游戏结束 if (!(x_new == tail->x && y_new == tail->y)) //但可以“撞”蛇尾,因为实际上蛇头与蛇尾是同时移动的,实际上并不会撞上去 return false; if (x_new == food_x && y_new == food_y) { AddHead(x_new,y_new); //在蛇头前方插入新结点,即向前走一步 GenerateFood(); //若吃到了食物,则不用删除蛇尾,即蛇身变长一格,且需生成新的食物 return true; } AddHead(x_new,y_new); DelTail(); //若没吃到食物,则需删除蛇尾,以达到蛇向前走一步而蛇身长度不变的效果 return true; } void SNAKE::AddHead(int x,int y) { SNAKE_NODE *node_new = new SNAKE_NODE(x,y,NULL,head); //新结点的suc为NULL,pre为旧蛇头 if (head == NULL) tail = node_new; //若旧蛇头为NULL,即向空蛇插入新结点,需把蛇尾指向新结点 else { head->suc = node_new; //把旧蛇头的suc指向新结点 SetTextColorToBlue(); print(head->x,head->y,'O'); //把旧蛇头处显示的字符改成'O'(O代表蛇身) } head = node_new; //蛇头指向新结点 SetTextColorToBlue(); print(head->x,head->y,'X'); //在新蛇头处输出'X'(X代表蛇头) snake_map[head->x][head->y] = true; //更新蛇身地图 ++len; //更新蛇身长度 } void SNAKE::DelTail() { SNAKE_NODE *p = tail; //p指向旧蛇尾 print(p->x,p->y,' '); //在旧蛇尾处输出空格,以达到删除的视觉效果 snake_map[p->x][p->y] = false; //更新蛇身地图 tail = p->suc; //更新蛇尾 tail->pre = NULL; //更新新蛇尾的pre delete p; //回收旧蛇尾占用的内存 --len; //更新蛇身长度 } //开始游戏 void work() { ScreenInit(); SNAKE snake; snake.GenerateFood(); while (true) { snake.ChangeDir(getch()); //改变方向(除了第一次要等待用户输入,后来执行到这一行时,保证缓冲区内已有输入) while (kbhit()) //kbhit()返回键盘是否有输入(缓冲区内是否有新字符),且不会吞下输入的字符 getch(); //吞下多余的输入(避免输入间隔快于行走间隔时可连续改变方向引起) while (!kbhit()) //若键盘无输入,则蛇向前走一步 { if (!snake.move()) //若撞墙或撞蛇,则游戏结束 { SetTextColorToRed(); SetCursorPosition(10,21); cout << "Game Over!"; SetCursorPosition(10,22); cout << "Your Score: "; SetTextColorToYello(); cout << snake.GetLen(); SetTextColorToRed(); SetCursorPosition(10,23); system("pause"); work(); //输出结果后开始下一轮游戏 return; } int sleep_time = sleep_time_t0 - sleep_time_k * (snake.GetLen() - snake_initila_len); //间隔时间与蛇身长度呈一次函数关系 if (sleep_time < sleep_time_min) sleep_time = sleep_time_min; if (sleep_time > sleep_time_max) sleep_time = sleep_time_max; //但不会超过[min,max]这一范围,避免过快或过慢 Sleep(sleep_time); //注意S要大写 } } } int init() //初始化 { srand(time(0)); //设置随机种子 SetWindow(); //设置窗口 } int main() { init(); cout << "Welcome to the world of gluttonous snakes!" << endl; cout << "You can control your gluttonous snake by 'WASD'" << endl; cout << "Please input any key to begin!" << endl; SetCursorPosition(0,0); getch(); //getch()会等待键盘输入(不用按回车键,不会在屏幕上回显输入的字符)返回输入的字符 work(); return 0; } |
stO膜拜
gcc 编译不了?