我怎样才能改进这个游戏?
#include <iomanip>
#include <iostream>
#include <vector>
#include <random>
#include <conio.h>
struct Random
{
Random(int min, int max)
: mUniformDistribution(min, max)
{}
int operator()()
{
return mUniformDistribution(mEngine);
}
std::default_random_engine mEngine{ std::random_device()() };
std::uniform_int_distribution<int> mUniformDistribution;
};
std::vector<std::vector<int>> stage(22, std::vector<int>(13, 0));
std::vector<std::vector<int>> block =
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 }
};
std::vector<std::vector<int>> field(22, std::vector<int>(13, 0));
// coordinate
int y = 0;
int x = 4;
bool gameover = false;
size_t GAMESPEED = 20000;
Random getRandom{ 0, 6 };
std::vector<std::vector<std::vector<int>>> block_list =
{
{
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 0, 0 },
{ 0, 1, 0, 0 }
},
{
{ 0, 0, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 1, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 1, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 0, 0 }
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 1, 0 }
}
};
int menu();
int gameOver();
void title();
void gameLoop();
void display();
bool makeBlocks();
void initGame();
void moveBlock(int, int);
void collidable();
bool isCollide(int, int);
void userInput();
bool rotateBolck();
void spwanBlock();
int main()
{
switch (menu())
{
case 1:
gameLoop();
break;
case 2:
return 0;
case 0:
std::cerr << "Choose 1~2" << std::endl;
return -1;
}
return 0;
}
int gameOver()
{
using namespace std;
char a;
cout << " ##### # # # ####### ####### # # ####### ######\n" ;
cout << "# # # # ## ## # # # # # # # #\n";
cout << "# # # # # # # # # # # # # # #\n";
cout << "# #### # # # # # ##### # # # # ##### ######\n";
cout << "# # ####### # # # # # # # # # #\n";
cout << "# # # # # # # # # # # # # #\n";
cout << " ##### # # # # ####### ####### # ####### # #\n";
cout << "\n\nPress any key and enter\n";
cin >> a;
return 0;
}
void gameLoop()
{
size_t time = 0;
initGame();
while (!gameover)
{
if (kbhit())
{
userInput();
}
if (time < GAMESPEED)
{
time++;
}
else
{
spwanBlock();
time = 0;
}
}
}
int menu()
{
title();
int select_num = 0;
std::cin >> select_num;
switch (select_num)
{
case 1:
case 2:
case 3:
break;
default:
select_num = 0;
break;
}
return select_num;
}
void title()
{
using namespace std;
system("cls");
cout << "#==============================================================================#\n";
cout << "####### ####### ####### ###### ### #####\n";
cout << " # # # # # # # #\n";
cout << " # # # # # # #\n";
cout << " # ##### # ###### # #####\n";
cout << " # # # # # # #\n";
cout << " # # # # # # # #\n";
cout << " # ####### # # # ### #####\t\tmade for fun \n";
cout << "\n\n\n\n";
cout << "\t<Menu>\n";
cout << "\t1: Start Game\n\t2: Quit\n\n";
cout << "#==============================================================================#\n";
cout << "Choose >> ";
}
void display()
{
system("cls");
for (size_t i = 0; i < 21; i++)
{
for (size_t j = 0; j < 12; j++)
{
switch (field[i][j])
{
case 0:
std::cout << " " << std::flush;
break;
case 9:
std::cout << "@" << std::flush;
break;
default:
std::cout << "#" << std::flush;
break;
}
}
std::cout << std::endl;
}
std::cout << "\n\tA: left\tS: down\tD: right \t Rotation[Space]";
if (gameover)
{
system("cls");
gameOver();
}
}
void initGame()
{
for (size_t i = 0; i <= 20; i++)
{
for (size_t j = 0; j <= 11; j++)
{
if ((j == 0) || (j == 11) || (i == 20))
{
field[i][j] = stage[i][j] = 9;
}
else
{
field[i][j] = stage[i][j] = 0;
}
}
}
makeBlocks();
display();
}
bool makeBlocks()
{
x = 4;
y = 0;
int blockType = getRandom();
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 4; j++)
{
block[i][j] = 0;
block[i][j] = block_list[blockType][i][j];
}
}
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 4; j++)
{
field[i][j + 4] = stage[i][j + 4] + block[i][j];
if (field[i][j + 4] > 1)
{
gameover = true;
return true;
}
}
}
return false;
}
void moveBlock(int x2, int y2)
{
//Remove block
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 4; j++)
{
field[y + i][x + j] -= block[i][j];
}
}
//Update coordinates
x = x2;
y = y2;
// assign a block with the updated value
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 4; j++)
{
field[y + i][x + j] += block[i][j];
}
}
display();
}
void collidable()
{
for (size_t i = 0; i<21; i++)
{
for (size_t j = 0; j<12; j++)
{
stage[i][j] = field[i][j];
}
}
}
bool isCollide(int x2, int y2)
{
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 4; j++)
{
if (block[i][j] && stage[y2 + i][x2 + j] != 0)
{
return true;
}
}
}
return false;
}
void userInput()
{
char key;
key = getch();
switch (key)
{
case 'd':
if (!isCollide(x + 1, y))
{
moveBlock(x + 1, y);
}
break;
case 'a':
if (!isCollide(x - 1, y))
{
moveBlock(x - 1, y);
}
break;
case 's':
if (!isCollide(x, y + 1))
{
moveBlock(x, y + 1);
}
break;
case ' ':
rotateBolck();
}
}
bool rotateBolck()
{
std::vector<std::vector<int>> tmp(4, std::vector<int>(4, 0));
for (size_t i = 0; i < 4; i++)
{ //Save temporarily block
for (size_t j = 0; j < 4; j++)
{
tmp[i][j] = block[i][j];
}
}
for (size_t i = 0; i < 4; i++)
{ //Rotate
for (size_t j = 0; j < 4; j++)
{
block[i][j] = tmp[3 - j][i];
}
}
if (isCollide(x, y))
{ // And stop if it overlaps not be rotated
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 4; j++)
{
block[i][j] = tmp[i][j];
}
}
return true;
}
for (size_t i = 0; i < 4; i++)
{
for (size_t j = 0; j < 4; j++)
{
field[y + i][x + j] -= tmp[i][j];
field[y + i][x + j] += block[i][j];
}
}
display();
return false;
}
void spwanBlock()
{
if (!isCollide(x, y + 1))
{
moveBlock(x, y + 1);
}
else
{
collidable();
makeBlocks();
display();
}
}发布于 2014-12-20 20:53:24
我看到了一些可以帮助您改进这段代码的东西。
system("cls")不使用system("cls")或system("pause")有两个原因。首先,它不能移植到您现在可能关心或可能不关心的其他操作系统上。第二,这是一个安全漏洞,你绝对必须关心。具体来说,如果某个程序被定义并命名为cls或pause,那么您的程序将执行该程序而不是您想要的,而其他程序可能是任何东西。首先,将它们隔离为单独的函数cls()和pause(),然后修改代码以调用这些函数而不是system。然后重写这些函数的内容,以便使用C++执行您想要的操作。例如,如果您的终端支持ANSI逃逸序列,则可以使用以下内容:
void cls()
{
std::cout << "\x1b[2J";
}在这段代码中,有几件事情是DOS/Windows的,其中包括#include <conio.h>、getch()和kbhit()函数,还有我已经提到的system("cls");。如果我提供了这些缺失的函数,那么您的代码在Linux上成功运行,但是如果代码中已经有一个#ifdef WINDOWS,那么您的代码就可以重新编译,而不必修改源代码。
代码有spwanBlock()而不是spawnBlock()和rotateBolck()而不是rotateBlock()。这种类型的排字根本不影响编译器,但它们会困扰代码的人类读者,使其更难理解和维护。
游戏更多地是用C的过程风格编写的,而不是用面向对象的C++风格编写的。游戏本身可以是一个对象,大部分过程都是该对象的函数。这将减少耦合,并使程序更容易理解。而且,每个块显然都是一个对象。它还将消除占用代码的全局变量,如x、y和gameover。
几乎所有的全局变量都可以通过使用对象来消除,但如果仍然存在,它们应该是static,以便将它们限制在文件范围内,或者更好地使用匿名命名空间。
gameOver()和title()函数都有许多重复行,其中ostream operator<<与std::cout和一个固定字符串一起多次使用。这些多个电话不需要发生。您可以简单地依赖于这样一个事实,即C++自动合并单独的常量字符串。例如,下面是一个已编码的gameOver():
void gameOver()
{
std::cout << "\n"
" ##### # # # ####### ####### # # ####### ######\n"
"# # # # ## ## # # # # # # # #\n"
"# # # # # # # # # # # # # # #\n"
"# #### # # # # # ##### # # # # ##### ######\n"
"# # ####### # # # # # # # # # #\n"
"# # # # # # # # # # # # # #\n"
" ##### # # # # ####### ####### # ####### # #\n"
"\n\nPress any key and enter\n";
char a;
std::cin >> a;
}这里要注意一些简单的事情。首先,只有一个输入和一个输出调用,因此using namespace std;似乎不值得,因此被删除了。其次,虚拟变量a是在使用之前声明的,而不是在函数开始时声明的。第三,由于返回变量既不有用也不使用,所以省略了它。
代码,包括initGame()的实现,充满了“神奇数字”--即文本中没有明显意义的原始数字。例如:
void initGame()
{
for (size_t i = 0; i <= 20; i++)
{
for (size_t j = 0; j <= 11; j++)
{
if ((j == 0) || (j == 11) || (i == 20))
{
field[i][j] = stage[i][j] = 9;
}在这段代码中,20、11或9的含义一点也不明显。有意义地命名常量将是更好的方法来做到这一点。
中使用const
像GAMESPEED这样的变量不会被程序改变,因此应该被声明为const。
当前的gameLoop()例程使用一个非常粗糙的增量循环来进行计时。这将更好地使用来自std::chrono的东西来实现,或者更好,可以使用异步编程模型而不是同步方案来重写整个过程。
最初的俄罗斯方块游戏会删除一行,一旦它被完全填充,但这段代码不这样做。它也保持得分,原来的游戏是彩色的。您可以添加所有这些东西,前两项通过对代码进行功能更改,最后一项通过前面提到的ANSI逃逸序列添加。这将是一个更有趣的游戏。
发布于 2014-12-20 20:59:39
您的switch语句的格式在我看来很奇怪。
switch (field[i][j]) { case 0: std::cout << " " << std::flush; break; case 9: std::cout << "@" << std::flush; break; default: std::cout << "#" << std::flush; break; }
我宁愿把案子的陈述写进去,
switch (field[i][j])
{
case 0:
std::cout << " " << std::flush;
break;
case 9:
std::cout << "@" << std::flush;
break;
default:
std::cout << "#" << std::flush;
break;
}这样看来,Case语句就像它们应该是Switch的子语句一样。
https://codereview.stackexchange.com/questions/74293
复制相似问题