mirror of https://github.com/string1995/eee102.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
571 lines
14 KiB
571 lines
14 KiB
#include <iostream> |
|
#include <time.h> |
|
#include <conio.h> |
|
#include <windows.h> |
|
#include "controller.h" |
|
#include "tools.h" |
|
#include "startinterface.h" |
|
#include "map.h" |
|
#include "snake.h" |
|
#include "food.h" |
|
|
|
void Controller::Start()//开始界面 |
|
{ |
|
SetWindowSize(41, 32);//设置窗口大小 |
|
SetColor(2);//设置开始动画颜色 |
|
StartInterface *start = new StartInterface();//动态分配一个StartInterface类start |
|
start->Action();//开始动画 |
|
delete start;//释放内存空间 |
|
|
|
/*设置关标位置,并输出提示语,等待任意键输入结束*/ |
|
SetCursorPosition(13, 26); |
|
std::cout << "Press any key to start... " ; |
|
SetCursorPosition(13, 27); |
|
system("pause"); |
|
} |
|
|
|
void Controller::Select()//选择界面 |
|
{ |
|
/*初始化界面选项*/ |
|
SetColor(3); |
|
SetCursorPosition(13, 26); |
|
std::cout << " " ; |
|
SetCursorPosition(13, 27); |
|
std::cout << " " ; |
|
SetCursorPosition(6, 21); |
|
std::cout << "请选择游戏难度:" ; |
|
SetCursorPosition(6, 22); |
|
std::cout << "(上下键选择,回车确认)" ; |
|
SetCursorPosition(27, 22); |
|
SetBackColor();//第一个选项设置背景色以表示当前选中 |
|
std::cout << "简单模式" ; |
|
SetCursorPosition(27, 24); |
|
SetColor(3); |
|
std::cout << "普通模式" ; |
|
SetCursorPosition(27, 26); |
|
std::cout << "困难模式" ; |
|
SetCursorPosition(27, 28); |
|
std::cout << "炼狱模式" ; |
|
SetCursorPosition(0, 31); |
|
score = 0; |
|
|
|
/*上下方向键选择模块*/ |
|
int ch;//记录键入值 |
|
key = 1;//记录选中项,初始选择第一个 |
|
bool flag = false;//记录是否键入Enter键标记,初始置为否 |
|
while ((ch = getch())) |
|
{ |
|
switch (ch)//检测输入键 |
|
{ |
|
case 72://UP上方向键 |
|
if (key > 1)//当此时选中项为第一项时,UP上方向键无效 |
|
{ |
|
switch (key) |
|
{ |
|
case 2: |
|
SetCursorPosition(27, 22);//给待选中项设置背景色 |
|
SetBackColor(); |
|
std::cout << "简单模式" ; |
|
|
|
SetCursorPosition(27, 24);//将已选中项取消我背景色 |
|
SetColor(3); |
|
std::cout << "普通模式" ; |
|
|
|
--key; |
|
break; |
|
case 3: |
|
SetCursorPosition(27, 24); |
|
SetBackColor(); |
|
std::cout << "普通模式" ; |
|
|
|
SetCursorPosition(27, 26); |
|
SetColor(3); |
|
std::cout << "困难模式" ; |
|
|
|
--key; |
|
break; |
|
case 4: |
|
SetCursorPosition(27, 26); |
|
SetBackColor(); |
|
std::cout << "困难模式" ; |
|
|
|
SetCursorPosition(27, 28); |
|
SetColor(3); |
|
std::cout << "炼狱模式" ; |
|
|
|
--key; |
|
break; |
|
} |
|
} |
|
break; |
|
|
|
case 80://DOWN下方向键 |
|
if (key < 4) |
|
{ |
|
switch (key) |
|
{ |
|
case 1: |
|
SetCursorPosition(27, 24); |
|
SetBackColor(); |
|
std::cout << "普通模式" ; |
|
SetCursorPosition(27, 22); |
|
SetColor(3); |
|
std::cout << "简单模式" ; |
|
|
|
++key; |
|
break; |
|
case 2: |
|
SetCursorPosition(27, 26); |
|
SetBackColor(); |
|
std::cout << "困难模式" ; |
|
SetCursorPosition(27, 24); |
|
SetColor(3); |
|
std::cout << "普通模式" ; |
|
|
|
++key; |
|
break; |
|
case 3: |
|
SetCursorPosition(27, 28); |
|
SetBackColor(); |
|
std::cout << "炼狱模式" ; |
|
SetCursorPosition(27, 26); |
|
SetColor(3); |
|
std::cout << "困难模式" ; |
|
|
|
++key; |
|
break; |
|
} |
|
} |
|
break; |
|
|
|
case 13://Enter回车键 |
|
flag = true; |
|
break; |
|
default://无效按键 |
|
break; |
|
} |
|
if (flag) break;//输入Enter回车键确认,退出检查输入循环 |
|
|
|
SetCursorPosition(0, 31);//将光标置于左下角,避免关标闪烁影响游戏体验 |
|
} |
|
|
|
switch (key)//根据所选选项设置蛇的移动速度,speed值越小,速度越快 |
|
{ |
|
case 1: |
|
speed = 135; |
|
break; |
|
case 2: |
|
speed = 100; |
|
break; |
|
case 3: |
|
speed = 60; |
|
break; |
|
case 4: |
|
speed = 30; |
|
break; |
|
default: |
|
break; |
|
} |
|
} |
|
|
|
void Controller::DrawGame()//绘制游戏界面 |
|
{ |
|
system("cls");//清屏 |
|
|
|
/*绘制地图*/ |
|
SetColor(3); |
|
Map *init_map = new Map(); |
|
init_map->PrintInitmap(); |
|
delete init_map; |
|
|
|
/*绘制侧边栏*/ |
|
SetColor(3); |
|
SetCursorPosition(33, 1); |
|
std::cout << "Greedy Snake" ; |
|
SetCursorPosition(34, 2); |
|
std::cout << "贪吃蛇" ; |
|
SetCursorPosition(31, 4); |
|
std::cout << "难度:" ; |
|
SetCursorPosition(36, 5); |
|
switch (key) |
|
{ |
|
case 1: |
|
std::cout << "简单模式" ; |
|
break; |
|
case 2: |
|
std::cout << "普通模式" ; |
|
break; |
|
case 3: |
|
std::cout << "困难模式" ; |
|
break; |
|
case 4: |
|
std::cout << "炼狱模式" ; |
|
break; |
|
default: |
|
break; |
|
} |
|
SetCursorPosition(31, 7); |
|
std::cout << "得分:" ; |
|
SetCursorPosition(37, 8); |
|
std::cout << " 0" ; |
|
SetCursorPosition(33, 13); |
|
std::cout << " 方向键移动" ; |
|
SetCursorPosition(33, 15); |
|
std::cout << " ESC键暂停" ; |
|
} |
|
|
|
int Controller::PlayGame()//游戏二级循环 |
|
{ |
|
/*初始化蛇和食物*/ |
|
Snake *csnake = new Snake(); |
|
Food *cfood = new Food(); |
|
SetColor(6); |
|
csnake->InitSnake(); |
|
srand((unsigned)time(NULL));//设置随机数种子,如果没有 食物的出现位置将会固定 |
|
cfood->DrawFood(*csnake); |
|
|
|
/*游戏循环*/ |
|
while (csnake->OverEdge() && csnake->HitItself()) //判断是否撞墙或撞到自身,即是否还有生命 |
|
{ |
|
/*调出选择菜单*/ |
|
if (!csnake->ChangeDirection()) //按Esc键时 |
|
{ |
|
int tmp = Menu();//绘制菜单,并得到返回值 |
|
switch (tmp) |
|
{ |
|
case 1://继续游戏 |
|
break; |
|
|
|
case 2://重新开始 |
|
delete csnake; |
|
delete cfood; |
|
return 1;//将1作为PlayGame函数的返回值返回到Game函数中,表示重新开始 |
|
|
|
case 3://退出游戏 |
|
delete csnake; |
|
delete cfood; |
|
return 2;//将2作为PlayGame函数的返回值返回到Game函数中,表示退出游戏 |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
|
|
if (csnake->GetFood(*cfood)) //吃到食物 |
|
{ |
|
csnake->Move();//蛇增长 |
|
UpdateScore(1);//更新分数,1为分数权重 |
|
RewriteScore();//重新绘制分数 |
|
cfood->DrawFood(*csnake);//绘制新食物 |
|
} |
|
else |
|
{ |
|
csnake->NormalMove();//蛇正常移动 |
|
} |
|
|
|
if (csnake->GetBigFood(*cfood)) //吃到限时食物 |
|
{ |
|
csnake->Move(); |
|
UpdateScore(cfood->GetProgressBar()/5);//分数根据限时食物进度条确定 |
|
RewriteScore(); |
|
} |
|
|
|
if (cfood->GetBigFlag()) //如果此时有限时食物,闪烁它 |
|
{ |
|
cfood->FlashBigFood(); |
|
} |
|
|
|
Sleep(speed);//制造蛇的移动效果 |
|
} |
|
|
|
/*蛇死亡*/ |
|
delete csnake;//释放分配的内存空间 |
|
delete cfood; |
|
int tmp = GameOver();//绘制游戏结束界面,并返回所选项 |
|
switch (tmp) |
|
{ |
|
case 1: |
|
return 1;//重新开始 |
|
case 2: |
|
return 2;//退出游戏 |
|
default: |
|
return 2; |
|
} |
|
} |
|
|
|
void Controller::UpdateScore(const int& tmp)//更新分数 |
|
{ |
|
score += key * 10 * tmp;//所得分数根据游戏难度及传人的参数tmp确定 |
|
} |
|
|
|
void Controller::RewriteScore()//重绘分数 |
|
{ |
|
/*为保持分数尾部对齐,将最大分数设置为6位,计算当前分数位数,将剩余位数用空格补全,再输出分数*/ |
|
SetCursorPosition(37, 8); |
|
SetColor(11); |
|
int bit = 0; |
|
int tmp = score; |
|
while (tmp != 0) |
|
{ |
|
++bit; |
|
tmp /= 10; |
|
} |
|
for (int i = 0; i < (6 - bit); ++i) |
|
{ |
|
std::cout << " " ; |
|
} |
|
std::cout << score ; |
|
} |
|
|
|
int Controller::Menu()//选择菜单 |
|
{ |
|
/*绘制菜单*/ |
|
SetColor(11); |
|
SetCursorPosition(32, 19); |
|
std::cout << "菜单:" ; |
|
Sleep(100); |
|
SetCursorPosition(34, 21); |
|
SetBackColor(); |
|
std::cout << "继续游戏" ; |
|
Sleep(100); |
|
SetCursorPosition(34, 23); |
|
SetColor(11); |
|
std::cout << "重新开始" ; |
|
Sleep(100); |
|
SetCursorPosition(34, 25); |
|
std::cout << "退出游戏" ; |
|
SetCursorPosition(0, 31); |
|
|
|
/*选择部分*/ |
|
int ch; |
|
int tmp_key = 1; |
|
bool flag = false; |
|
while ((ch = getch())) |
|
{ |
|
switch (ch) |
|
{ |
|
case 72://UP |
|
if (tmp_key > 1) |
|
{ |
|
switch (tmp_key) |
|
{ |
|
case 2: |
|
SetCursorPosition(34, 21); |
|
SetBackColor(); |
|
std::cout << "继续游戏" ; |
|
SetCursorPosition(34, 23); |
|
SetColor(11); |
|
std::cout << "重新开始" ; |
|
|
|
--tmp_key; |
|
break; |
|
case 3: |
|
SetCursorPosition(34, 23); |
|
SetBackColor(); |
|
std::cout << "重新开始" ; |
|
SetCursorPosition(34, 25); |
|
SetColor(11); |
|
std::cout << "退出游戏" ; |
|
|
|
--tmp_key; |
|
break; |
|
} |
|
} |
|
break; |
|
|
|
case 80://DOWN |
|
if (tmp_key < 3) |
|
{ |
|
switch (tmp_key) |
|
{ |
|
case 1: |
|
SetCursorPosition(34, 23); |
|
SetBackColor(); |
|
std::cout << "重新开始" ; |
|
SetCursorPosition(34, 21); |
|
SetColor(11); |
|
std::cout << "继续游戏" ; |
|
|
|
++tmp_key; |
|
break; |
|
case 2: |
|
SetCursorPosition(34, 25); |
|
SetBackColor(); |
|
std::cout << "退出游戏" ; |
|
SetCursorPosition(34, 23); |
|
SetColor(11); |
|
std::cout << "重新开始" ; |
|
|
|
++tmp_key; |
|
break; |
|
} |
|
} |
|
break; |
|
|
|
case 13://Enter |
|
flag = true; |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
|
|
if (flag) |
|
{ |
|
break; |
|
} |
|
SetCursorPosition(0, 31); |
|
} |
|
|
|
if (tmp_key == 1) //选择继续游戏,则将菜单擦除 |
|
{ |
|
SetCursorPosition(32, 19); |
|
std::cout << " " ; |
|
SetCursorPosition(34, 21); |
|
std::cout << " "; |
|
SetCursorPosition(34, 23); |
|
std::cout << " "; |
|
SetCursorPosition(34, 25); |
|
std::cout << " "; |
|
} |
|
return tmp_key; |
|
} |
|
|
|
void Controller::Game()//游戏一级循环 |
|
{ |
|
Start();//开始界面 |
|
while (true)//游戏可视为一个死循环,直到退出游戏时循环结束 |
|
{ |
|
Select();//选择界面 |
|
DrawGame();//绘制游戏界面 |
|
int tmp = PlayGame();//开启游戏循环,当重新开始或退出游戏时,结束循环并返回值给tmp |
|
if (tmp == 1) //返回值为1时重新开始游戏 |
|
{ |
|
system("cls"); |
|
continue; |
|
} |
|
else if (tmp == 2) //返回值为2时退出游戏 |
|
{ |
|
break; |
|
} |
|
else |
|
{ |
|
break; |
|
} |
|
} |
|
} |
|
|
|
int Controller::GameOver()//游戏结束界面 |
|
{ |
|
/*绘制游戏结束界面*/ |
|
Sleep(500); |
|
SetColor(11); |
|
SetCursorPosition(10, 8); |
|
std::cout << "━━━━━━━━━━━━━━━━━━━━━━" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 9); |
|
std::cout << " ┃ Game Over !!! ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 10); |
|
std::cout << " ┃ ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 11); |
|
std::cout << " ┃ 很遗憾!你挂了 ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 12); |
|
std::cout << " ┃ ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 13); |
|
std::cout << " ┃ 你的分数为: ┃" ; |
|
SetCursorPosition(24, 13); |
|
std::cout << score ; |
|
Sleep(30); |
|
SetCursorPosition(9, 14); |
|
std::cout << " ┃ ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 15); |
|
std::cout << " ┃ 是否再来一局? ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 16); |
|
std::cout << " ┃ ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 17); |
|
std::cout << " ┃ ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 18); |
|
std::cout << " ┃ 嗯,好的 不了,还是学习有意思 ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 19); |
|
std::cout << " ┃ ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(9, 20); |
|
std::cout << " ┃ ┃" ; |
|
Sleep(30); |
|
SetCursorPosition(10, 21); |
|
std::cout << "━━━━━━━━━━━━━━━━━━━━━━" ; |
|
|
|
Sleep(100); |
|
SetCursorPosition(12, 18); |
|
SetBackColor(); |
|
std::cout << "嗯,好的" ; |
|
SetCursorPosition(0, 31); |
|
|
|
/*选择部分*/ |
|
int ch; |
|
int tmp_key = 1; |
|
bool flag = false; |
|
while ((ch = getch())) |
|
{ |
|
switch (ch) |
|
{ |
|
case 75://LEFT |
|
if (tmp_key > 1) |
|
{ |
|
SetCursorPosition(12, 18); |
|
SetBackColor(); |
|
std::cout << "嗯,好的" ; |
|
SetCursorPosition(20, 18); |
|
SetColor(11); |
|
std::cout << "不了,还是学习有意思" ; |
|
--tmp_key; |
|
} |
|
break; |
|
|
|
case 77://RIGHT |
|
if (tmp_key < 2) |
|
{ |
|
SetCursorPosition(20, 18); |
|
SetBackColor(); |
|
std::cout << "不了,还是学习有意思" ; |
|
SetCursorPosition(12, 18); |
|
SetColor(11); |
|
std::cout << "嗯,好的" ; |
|
++tmp_key; |
|
} |
|
break; |
|
|
|
case 13://Enter |
|
flag = true; |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
|
|
SetCursorPosition(0, 31); |
|
if (flag) { |
|
break; |
|
} |
|
} |
|
|
|
SetColor(11); |
|
switch (tmp_key) |
|
{ |
|
case 1: |
|
return 1;//重新开始 |
|
case 2: |
|
return 2;//退出游戏 |
|
default: |
|
return 1; |
|
} |
|
}
|
|
|