我做了这个简单的俄罗斯方块游戏,我只有两个街区,正方形和线。此外,游戏结束后,20个街区被创造和球员获胜。我在想怎样才能让它更好。
下面是代码:
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <time.h>
#define RIGA 21
#define COLONNA 10
#define DESTRA 77
#define SINISTRA 75
#define GIU 80
#define SU 72
void GotoXY(int x, int y)
{
COORD CursorPos = {x, y};
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hConsole, CursorPos);
}
// FUNCTION PER RALLENTARE I MOVIMENTI
void ritardo()
{
long double i;
for(i=0;i<=(30000000);i++);
}
int i, j; // CONTATORI
int sposta, random; // VARIABILI BOOLEANE
int punti = 0; // VARIABILE PER ASSEGNAZIONE DEI PUNTI
int contatore_pezzi = 1; // VARIABILE PER CONTARE IL NUMERO DI OGGETTI CREATI
char griglia[21][10]; // DICHIARAZIONE ARRAY DI CHAR
char pezzo[2][2] = {{'X', 'X'}, // DICHIARAZIONE CUBO
{'X', 'X'}};
char linea[3][1] = {{'X'},
{'X'},
{'X'}}; // DICHIARAZIONE LINEA
char linea_or[1][3] = { {'X'},{'X'},{'X'}};
void caricaArray() // INIZIALIZZA L'ARRAY VUOTO CON CICLI FOR INNESTATI
{
for (i = 0; i < RIGA; i++)
{
for (j = 0; j < COLONNA; j++)
{
griglia[i][j] = ' ';
}
}
}
// PROTOTIPI FUCTION
void movimenti();
void assegnaPezzo();
void eliminaRiga();
void stampaBordi();
int main()
{
caricaArray();
movimenti();
printf("\n\n");
return 0;
}
void visualizzaArray() // VISUALIZZA L'ARRAY ALLO STATO ATTUALE
{
printf("\n");
for (i = 0; i < RIGA; i++)
{
printf(" "); //Spazio per visualizzare tutti i punti all'interno del bordo
for (j = 0; j < COLONNA; j++)
{
printf("%c ", griglia[i][j]);
}
printf("\n");
}
stampaBordi();
}
void movimenti() // GESTISCE TUTTI I POSSIBILI MOVIMENTI DELLA FORMA
{
do {
eliminaRiga(); // Ad ogni ciclo verifica la presenza di righe piene
int r = 0;
int c = 4;
srand(time(NULL)); // Random
random = rand() % 2;
assegnaPezzo();
visualizzaArray();
do {
GotoXY(r,c); // Inizia a scorrere verso il basso
r++;
system("cls");
if (random == 0) { // Se l'oggetto creato e' il cubo
griglia[r-1][c] = ' '; // Libera le posizioni precedenti
griglia[r-1][c+1] = ' ';
griglia[r][c] = pezzo[0][0]; // Riassegna l'oggetto nella nuova posizione
griglia[r][c+1] = pezzo[0][1];
griglia[r+1][c] = pezzo[1][0];
griglia[r+1][c+1] = pezzo[1][1];
}
if (random == 1) { // Se l'oggetto creato e' la linea
if ( !kbhit() ) // Se non si premono tasti
{
griglia[r-1][c] = ' '; // Libera le posizioni precedenti
griglia[r][c] = linea[0][0]; // Riassegna l'oggetto nella nuova posizione
griglia[r+1][c] = linea [1][0];
griglia[r+2][c] = linea [2][0];
}
}
visualizzaArray();
ritardo();
if ( kbhit() ) // Se durante lo scroll verticale si preme un tasto
{
sposta = getch(); // Prende in input un tasto e lo assegna alla variabile sposta
if (sposta==SU) // E se e' la freccia SU
{
griglia[r-1][c] = ' ';
griglia[r][c-1] = linea_or[0][0];
griglia[r][c] = linea_or[1][0];
griglia[r][c+1] = linea_or[2][0];
}
if (sposta == DESTRA ) // E se e' la freccia DESTRA
{
c++; // L'oggetto si sposta a destra
system("cls");
if (random == 0) {
if (c+1>COLONNA-1) { break; } // Se supera il bordo destro
griglia[r][c-1] = ' '; // Libera le posizioni precedenti
griglia[r+1][c-1] = ' ';
}
else if (random == 1) {
griglia[r-2][c-1] = ' '; // Libera le posizioni precedenti
griglia[r-1][c-1] = ' ';
griglia[r][c-1] = ' ';
griglia[r+1][c-1] = ' ';
griglia[r+2][c-1] = ' ';
}
visualizzaArray(); //visualizza il tutto
}
if (sposta == SINISTRA ) // E se e' la freccia SINISTRA
{
c--; // L'oggetto si sposta a sinistra
if (c<0) { break; } // Se supera il bordo sinistro
system("cls");
if (random == 0) {
griglia[r][c+2] = ' '; // Libera le posizioni precedenti
griglia[r+1][c+2] = ' ';
}
else if (random == 1) {
griglia[r-1][c+2] = ' '; // Libera le posizioni precedenti
griglia[r-1][c+1] = ' ';
griglia[r][c+1] = ' ';
griglia[r+1][c+1] = ' ';
griglia[r+2][c+1] = ' ';
}
visualizzaArray();
}
}
if (random == 0) {
if (griglia[r+2][c] == 'X' || griglia[r+2][c+1] == 'X') // Se il pezzo tocca un altro pezzo inferiormente
{
if (griglia[0][c] == 'X' || griglia[1][c] == 'X') // Se lo spazio superiore e' troppo piccolo
{
system("cls");
printf("HAI PERSO!\nPremi ESC per uscire.");
break;
}
contatore_pezzi++;
return movimenti(); //Allora attiva la ricorsivita'
}
}
if (random == 1) {
if (griglia[r+3][c] == 'X') {
if (griglia[0][c] == 'X' || griglia[1][c] == 'X')
{
system("cls");
printf("HAI PERSO!\nPremi ESC per uscire.");
break;
}
contatore_pezzi++;
return movimenti();
}
}
if (random == 0) {
if (r+1==20) { // Se tocca il borso inferiore crea un altro oggetto
contatore_pezzi++;
return movimenti(); }
}
else if (random == 1) {
if (r+2==20) { // Se tocca il borso inferiore crea un altro oggetto
contatore_pezzi++;
return movimenti(); }
}
} while ( sposta != 27 );
} while ( getch() != 27 );
}
void stampaBordi() // STAMPA LA CORNICE DEL CAMPO DI GIOCO
{
for(i=1;i<=19;i++)
{
GotoXY(i,22); putch('-');
GotoXY(i,0); putch('-');
}
printf(" PUNTI:%d - PEZZO No %d", punti, contatore_pezzi);
for (j=1;j<22; j++) {
GotoXY(0,j); putch('|');
GotoXY(20,j); putch('|');
}
}
void assegnaPezzo()
{
int i1 = 0;
int j1 = 4;
if (random==0) {
griglia[i1][j1] = pezzo[0][0]; // Assegna il pezzo nella posizione iniziale
griglia[i1][j1+1] = pezzo[0][1];
griglia[i1+1][j1] = pezzo[1][0];
griglia[i1+1][j1+1] = pezzo[1][1];
}
if (random==1) {
griglia[i1][j1] = linea[0][0];
griglia[i1+1][j1] = linea [1][0];
griglia[i1+2][j1] = linea [2][0];
}
}
void eliminaRiga() // ELIMINA UNA O PIU' RIGHE, SE PIENE
{
int k;
int cont_riga;
int colonna;
char aus[COLONNA];
for (cont_riga=0; cont_riga<=20; cont_riga++)
{
if (griglia[cont_riga][0] == 'X' && griglia[cont_riga][1] == 'X' && griglia[cont_riga][2] == 'X' && griglia[cont_riga][3] == 'X' && griglia[cont_riga][4] == 'X' && griglia[cont_riga][5] == 'X' && griglia[cont_riga][6] == 'X' && griglia[cont_riga][7] == 'X' && griglia[20][8] == 'X' && griglia[20][9] == 'X')
{
for (colonna=0; colonna<10; colonna++) {
aus[colonna] = griglia[cont_riga-1][colonna];
}
for (colonna=0; colonna<10; colonna++) {
griglia[cont_riga][colonna] = aus[colonna];
}
for (colonna=0; colonna<10; colonna++) {
griglia[cont_riga-1][colonna] = '.';
}
punti++;
for (k=2; k<11; k++) {
if (griglia[cont_riga-k][0] == 'X' || griglia[cont_riga-k][1] == 'X' || griglia[cont_riga-k][2] == 'X' || griglia[cont_riga-k][3] == 'X' || griglia[cont_riga-k][4] == 'X' || griglia[cont_riga-k][5] == 'X' || griglia[cont_riga-k][6] == 'X' || griglia[cont_riga-k][7] == 'X' || griglia[cont_riga-k][8] == 'X' || griglia[cont_riga-k][9] == 'X' )
{
for (colonna=0; colonna<10; colonna++) {
aus[colonna] = griglia[cont_riga-k][colonna];
}
for (colonna=0; colonna<10; colonna++) {
griglia[cont_riga-k+1][colonna] = aus[colonna];
}
for (colonna=0; colonna<10; colonna++) {
griglia[cont_riga-k][colonna] = '.';
}
}
}
system("cls");
visualizzaArray();
}
}
}发布于 2021-02-04 08:32:10
ritardo繁忙的延迟应该被Windows Sleep所取代。在使用线程和事件的更高级的Windows编程中,您也不会使用Sleep,而是使用WaitForSingleObject等。多线程是一个比较高级的主题,但是您最终需要学习这个主题。然后这个程序将使用一个线程来绘制图形,一个线程用于输入,另一个线程用于计算。而不是使用旧的MS风格的kbhit - DOS没有线程。i需要声明为volatile。否则,编译器就会优化整个循环。for(int i=0; ...中声明循环迭代器。void caricaArray()中使用过时的样式空括号函数。这意味着函数接受任何参数,这种样式在任何时候都可能从C中删除,因为它正式过时了。正确的形式是void caricaArray(void)。(不要与C++混淆,这里的空括号很好,相当于(void)。)srand();只应该在程序开始时调用一次,在循环中调用它。发布于 2021-02-03 22:43:15
有些建议没有具体的顺序:
i和j应该是局部变量。ritardo()似乎是POSIX sleep()或WindowsSleep()的糟糕替代品。memset在caricaArray中初始化您的griglia:memset(griglia,SPACE,sizeof(griglia));void对不带参数的函数进行原型。(C++允许空父母表示没有参数。)因此,像: void ();这样的一行实际上并不是一个原型,而是一个声明。main()的定义应该是第一个函数,或者是最后一个函数。如果您喜欢“读取我的程序”,那么main是第一位的,并且函数将随着它们的使用而附加到末尾(主调用A、A调用B等)。如果您倾向于“避免前向声明”,那么在调用每个函数之前都会尝试定义它。所以最低级别的函数位于文件的顶部,然后是更高的,最后是main()。如果你喜欢“一切都应该按字母顺序排列”,那么你就是个精神病患者,但至少你知道事情该在哪里。这是一个风格的问题,所以选择一个并坚持下去。cls来清除屏幕。写你自己的函数。enum型?kbhit()的结果。该函数检查键是否已被击中。这意味着每次你打电话的时候,你都要做另一次检查。在循环中,可能更容易在循环顶部调用它一次,记住结果,然后等到下一次遍历循环时再调用它。#defines或enum常量的常量。您已经有了一个良好的开端,但是随后您会陷入诸如'X'和20这样的值的泥潭。20是什么?也许还有更多的话要说,但现在看来已经足够了。
发布于 2021-02-04 12:59:16
总的来说,它看起来是相当不错的过程代码。
int i, j; // CONTATORI这些索引可以是函数的局部索引。全球是好的,但在这种情况下不是。
而且,sposta可能总是movimenti()函数的本地函数。
void stampaBordi() // STAMPA LA CORNICE DEL CAMPO DI GIOCO
{
for(i=1;i<=19;i++)
{
GotoXY(i,22); putch('-');
GotoXY(i,0); putch('-');i是columnIndex还是numberOfIterations,或者其他类似的东西?char griglia[21][10]; // DICHIARAZIONE ARRAY DI CHAR
...
void stampaBordi() // STAMPA LA CORNICE DEL CAMPO DI GIOCO
{
for(i=1;i<=19;i++)
{
GotoXY(i,22); putch('-');
GotoXY(i,0); putch('-');这些都与董事会有关。将这些变量组合在一起通常是个好主意,因为当相关的值是toghether (理解/可读性原因)时,更容易思考。
struct Grid {
char cells[21][10];
int rows;
int columns;
};
Grid grid = {
rows = 21;
columns = 10;
}
...
void stampaBordi(Grid * grid) // STAMPA LA CORNICE DEL CAMPO DI GIOCO
{
for(int i=1;i<= grid->rows - 2;i++)
{
GotoXY(i, grid->rows + 1 ); putch('-');
GotoXY(i, 0 ); putch('-');我确信这些常量中的一些也应该是网格结构的成员:)
#define RIGA 21
#define COLONNA 10
#define DESTRA 77
#define SINISTRA 75
#define GIU 80
#define SU 72在这种情况下..。
if (sposta == DESTRA ) // E se e' la freccia DESTRA
{
c++; // L'oggetto si sposta a destra
system("cls");
if (random == 0) {
if (c+1>COLONNA-1) { break; } // Se supera il bordo destro
griglia[r][c-1] = ' '; // Libera le posizioni precedenti
griglia[r+1][c-1] = ' ';
}
else if (random == 1) {
griglia[r-2][c-1] = ' '; // Libera le posizioni precedenti
griglia[r-1][c-1] = ' ';
griglia[r][c-1] = ' ';
griglia[r+1][c-1] = ' ';
griglia[r+2][c-1] = ' ';
}
visualizzaArray(); //visualizza il tutto
}将相关信息提取到结构中,以便更容易地制作新的内容并阅读。
// code like this repeats on multiple places
// and it seems like You are working with an array of offsets
// and You are doing single operation to them
griglia[r-2][c-1] = ' '; // Libera le posizioni precedenti
griglia[r-1][c-1] = ' ';
griglia[r][c-1] = ' ';
griglia[r+1][c-1] = ' ';
griglia[r+2][c-1] = ' ';
// this can be compressed like this
struct Offset { int x; int y; }
Offset offsets = [{-2,-1},{-1,-1},{0,-1},{1,-1},{2,-1}];
int offsetCount = 5;
for(auto i = 0; i < offsetCount; i++) {
auto offset = offsets[i];
griglia[r + offset.x][c + offset.y] = ' ';
}
// and it can be pulled into function
clearOffsets( Offsets * offsets, int offsetCount )
// Also these offsets seem to be always asociated with a tetromino
// each tetromino has it's own offsets, so
struct Offset { int x; int y; }
struct Tetromino { Offset cellOffsets[]; int offsetCount; ... }
Tetromino l_shape = { cellOffsets = [{-2,-1},{-1,-1},{0,-1},{1,-1},{2,-1}], 5}
// now You can make functions like this
clearTetromino(l_shape);
rotateTetrominoLeft(l_shape);
// also You can reuse function to rotate another shape or shapes ...
rotateTetrominoLeft(box_shape);
rotateTetrominoRight(shapes[shapeIndex]);有关代码压缩的更多信息,请参见优秀的https://caseymuratori.com/blog_0015。
else if (random == 1) {
if (r+2==20) { // Se tocca il borso inferiore crea un altro oggetto这对我来说很难快速扫描,因为我已经习惯了K&R支撑风格和Allman支撑风格(大多数人都使用它们)。
英文评论很好:)
我有这样的启发:我避免解释变量或函数的含义的注释,而是为函数/变量设置更好(更长、更描述性)的名称。我评论一些不太明显的东西.
这个没问题
if (r+2==20) { // Se tocca il borso inferiore crea un altro oggetto但是,也许通过引入变量来删除注释可以使事情变得清晰(而且您可以在多个地方重复使用变量)。
auto touchesLongerEdge = r + 2 === 20;https://codereview.stackexchange.com/questions/255574
复制相似问题