Крестики-нолики: критика кода - C (СИ)
Формулировка задачи:
В качестве практики, написал консольные крестики-нолики. Хотелось бы услышать мнение опытных людей. Над чем стоит поработать? Что в коде "не так"?
#include <stdio.h> #include <stdlib.h> #include <conio.h> struct coordinates{int x; int y;}; void manual() { printf("*******************************\n"); printf("W/S/A/D - choose cell\n"); printf("Space - put X/O\n"); printf("Esc - exit\n"); printf("*******************************\n"); printf("Press any key to start...\n"); } void initCellCoordinates(struct coordinates *cellCoord, int index) { int i=0,cellX,cellY; for(cellY=1;cellY<=17;cellY+=8) { for(cellX=1;cellX<=21;cellX+=10) { cellCoord[i].x=cellX; cellCoord[i].y=cellY; i++; } } return; } void initMatrix(char *matrix, int y, int x) { int i,j; for(i=0;i<x;i++) { for(j=0;j<y;j++) { *(matrix + i*y + j)='0'; } } return; } void initGrMatrix(char *matrix, int y, int x) { int i,j; for(i=0;i<y;i++) { for(j=0;j<x;j++) { if(i==0 || i==8 || i==16 || i==24) { if(j==0 || j==10 || j==20 || j==30) *(matrix + i*x + j)='+'; else *(matrix + i*x + j)= '-'; } else if(j==0 || j==10 || j==20 || j==30) *(matrix + i*x + j)='|'; else *(matrix + i*x + j) = ' '; } } return; } void printMatrix(char *matrix, int y, int x) { int i,j; for(i=0;i<y;i++) { for(j=0;j<x;j++) { printf("%c", *(matrix + i*x + j)); } printf("\n"); } return; } void moveFrame(char *matrix, int my, int mx, struct coordinates *frameCoord, struct coordinates *cellCoord, struct coordinates *lastFrameCoord) { *(matrix + cellCoord[frameCoord->y * 3 + frameCoord->x].y * mx + cellCoord[frameCoord->y * 3 + (frameCoord->x)].x)='#'; *(matrix + cellCoord[lastFrameCoord->y * 3 + lastFrameCoord->x].y * mx + cellCoord[lastFrameCoord->y * 3 + lastFrameCoord->x].x)=' '; return; } void addPlayerSymbol(char *checkMatrix, char *grMatrix, int gmX, struct coordinates *frameCoord, struct coordinates *cellCoord, char *player, char *paternX, char *paternO) { int i,j; switch(*player) { case 'X': for(i=0;i<5;i++) { for(j=0;j<5;j++) { *(grMatrix + (cellCoord[frameCoord->y * 3 + frameCoord->x].y+1+i) * gmX + cellCoord[frameCoord->y * 3 + (frameCoord->x)].x+2+j) = *(paternX + i*5 + j); } } return; case 'O': for(i=0;i<5;i++) { for(j=0;j<5;j++) { *(grMatrix + (cellCoord[frameCoord->y * 3 + frameCoord->x].y+1+i) * gmX + cellCoord[frameCoord->y * 3 + (frameCoord->x)].x+2+j) = *(paternO + i*5 + j); } } return; default: return; } } void changePlayer(char *player) { if((*player)=='X') (*player)='O'; else (*player)='X'; return; } int control(struct coordinates *frameCoord, struct coordinates *lastFrameCoord, char *checkMatrix,int cmY,int cmX, char *player, int *quit) { //return 0 - ничего не делать; return 1 - передвинуть #(frame); return 2 - ввести символ Х/О switch(getch()) { case 'w': if(frameCoord->y > 0) { lastFrameCoord->x=frameCoord->x; lastFrameCoord->y=frameCoord->y; frameCoord->y--; return 1; } else return 0; case 's': if(frameCoord->y < 2) { lastFrameCoord->x=frameCoord->x; lastFrameCoord->y=frameCoord->y; frameCoord->y++; return 1; } else return 0; case 'a': if(frameCoord->x > 0) { lastFrameCoord->x=frameCoord->x; lastFrameCoord->y=frameCoord->y; frameCoord->x--; return 1; } else return 0; case 'd': if(frameCoord->x < 2) { lastFrameCoord->x=frameCoord->x; lastFrameCoord->y=frameCoord->y; frameCoord->x++; return 1; } else return 0; case 32/*space*/: if(*(checkMatrix + frameCoord->y * cmX + frameCoord->x)=='0') { *(checkMatrix + frameCoord->y * cmX + frameCoord->x)=*player; return 2; } else return 0; case 27/*ESC*/: *quit=1; return; } } int check(char *checkMatrix, int cmX, char *winner) { int i,j; if(!(*(checkMatrix + 0*cmX + 0)=='0') && *(checkMatrix + 0*cmX + 0)==*(checkMatrix + 0*cmX + 1) && *(checkMatrix + 0*cmX + 0)==*(checkMatrix + 0*cmX + 2))//первая строчка(1) { *winner=*(checkMatrix + 0*cmX + 0); return 1; } else if(!(*(checkMatrix + 1*cmX + 0)=='0') && *(checkMatrix + 1*cmX + 0)==*(checkMatrix + 1*cmX + 1) && *(checkMatrix + 1*cmX + 0)==*(checkMatrix + 1*cmX + 2))//вторая строчка(2) { *winner=*(checkMatrix + 1*cmX + 0); return 2; } else if(!(*(checkMatrix + 2*cmX + 0)=='0') && *(checkMatrix + 2*cmX + 0)==*(checkMatrix + 2*cmX + 1) && *(checkMatrix + 2*cmX + 0)==*(checkMatrix + 2*cmX + 2))//третья строчка(3) { *winner=*(checkMatrix + 2*cmX + 0); return 3; } else if(!(*(checkMatrix + 0*cmX + 0)=='0') && *(checkMatrix + 0*cmX + 0)==*(checkMatrix + 1*cmX + 0) && *(checkMatrix + 0*cmX + 0)==*(checkMatrix + 2*cmX + 0))//первый столбец(4) { *winner=*(checkMatrix + 0*cmX + 0); return 4; } else if(!(*(checkMatrix + 0*cmX + 1)=='0') && *(checkMatrix + 0*cmX + 1)==*(checkMatrix + 1*cmX + 1) && *(checkMatrix + 0*cmX + 1)==*(checkMatrix + 2*cmX + 1))//второй столбец(5) { *winner=*(checkMatrix + 0*cmX + 1); return 5; } else if(!(*(checkMatrix + 0*cmX + 2)=='0') && *(checkMatrix + 0*cmX + 2)==*(checkMatrix + 1*cmX + 2) && *(checkMatrix + 0*cmX + 2)==*(checkMatrix + 2*cmX + 2))//третий столбец(6) { *winner=*(checkMatrix + 0*cmX + 2); return 6; } else if(!(*(checkMatrix + 0*cmX + 0)=='0') && *(checkMatrix + 0*cmX + 0)==*(checkMatrix + 1*cmX + 1) && *(checkMatrix + 0*cmX + 0)==*(checkMatrix + 2*cmX + 2))//первая диагональ(7) { *winner=*(checkMatrix + 0*cmX + 0); return 7; } else if(!(*(checkMatrix + 2*cmX + 0)=='0') && *(checkMatrix + 2*cmX + 0)==*(checkMatrix + 1*cmX + 1) && *(checkMatrix + 2*cmX + 0)==*(checkMatrix + 0*cmX + 2))//вторая диагональ(8) { *winner=*(checkMatrix + 2*cmX + 0); return 8; } else //если нет пустых клеток возвращать 9 for(i=0;i<3;i++) { for(j=0;j<3;j++) { if(*(checkMatrix + i*cmX + j)=='0') return 0; } } return 9; } void putWinLine(char *grMatrix, int gmX, int *winLine) { int i,j; switch(*winLine) { case 1: for(i=0;i<27;i++) { *(grMatrix + 4*gmX + 2+i)='o'; } return; case 2: for(i=0;i<27;i++) { *(grMatrix + 12*gmX + 2+i)='o'; } return; case 3: for(i=0;i<27;i++) { *(grMatrix + 20*gmX + 2+i)='o'; } return; case 4: for(i=0;i<23;i++) { *(grMatrix + (i+1)*gmX + 5)='o'; } return; case 5: for(i=0;i<23;i++) { *(grMatrix + (i+1)*gmX+ + 15)='o'; } return; case 6: for(i=0;i<23;i++) { *(grMatrix + (i+1)*gmX+2 + 23)='o'; } return; } } void addWins(int *winsX, int *winsO, char *winner) { switch(*winner) { case 'X': (*winsX)++; (*winner)='0'; break; case 'O': (*winsO)++; (*winner)='0'; break; default: (*winner)='0'; } *winsX++; return; } void printWins(int *winsX, int *winsO) { printf(" Wins\n"); printf(" X:%d O:%d\n", *winsX, *winsO); printf("===============================\n"); return; } //******************************************************** Main ************************************************** void main() { system("mode con cols=32 lines=36"); system("title TicTacToe"); int winLine=0, quit=0, winsX=0, winsO=0; struct coordinates frameCoord, lastFrameCoord, cellCoord[9]; char grMatrix[25][31], checkMatrix[3][3], player='X', winner='0', paternX[5][5]={ {'*',' ',' ',' ','*'}, {' ','*',' ','*',' '}, {' ',' ','*',' ',' '}, {' ','*',' ','*',' '}, {'*',' ',' ',' ','*'} }, paternO[5][5]={ {' ','*','*','*',' '}, {'*',' ',' ',' ','*'}, {'*',' ',' ',' ','*'}, {'*',' ',' ',' ','*'}, {' ','*','*','*',' '} }; initCellCoordinates(cellCoord, 9); frameCoord.x=0; frameCoord.y=0; manual(); while(quit==0) { initGrMatrix(&grMatrix[0][0],25,31); initMatrix(&checkMatrix[0][0],3,3); getch(); grMatrix[cellCoord[frameCoord.y * 3 + frameCoord.x].y][cellCoord[frameCoord.y * 3 + (frameCoord.x)].x]='#'; system("cls"); printWins(&winsX, &winsO); printMatrix(&grMatrix[0][0],25,31); printf("===============================\n"); printf("Your move, %c.\n\n", player); while(check(&checkMatrix[0][0], 3, &winner)==0) { switch(control(&frameCoord, &lastFrameCoord, &checkMatrix[0][0],3,3, &player, &quit)) { case 1://передвинуть # moveFrame(&grMatrix[0][0],25,31, &frameCoord, cellCoord, &lastFrameCoord); system("cls"); printWins(&winsX, &winsO); printMatrix(&grMatrix[0][0],25,31); printf("===============================\n"); printf("Your move, %c.\n\n", player); break; case 2: //нарисовать Х/О addPlayerSymbol(&checkMatrix[0][0], &grMatrix[0][0], 31, &frameCoord, cellCoord, &player, &paternX[0][0], &paternO[0][0]); changePlayer(&player); system("cls"); printWins(&winsX, &winsO); printMatrix(&grMatrix[0][0],25,31); printf("===============================\n"); printf("Your move, %c.\n\n", player); break; case 0: break; } if(quit==1) break; } winLine=check(&checkMatrix[0][0], 3, &winner); putWinLine(&grMatrix[0][0], 31, &winLine); system("cls"); printWins(&winsX, &winsO); printMatrix(&grMatrix[0][0],25,31); printf("===============================\n"); if(winLine!=9) printf("Winner: %c\n", winner); else printf("No empty cells\n"); addWins(&winsX, &winsO, &winner); printf("\n\n"); printf("Press any key to continue"); } return; }
Решение задачи: «Крестики-нолики: критика кода»
textual
Листинг программы
#define MAX_Y 17 #define MAX_X 21 ... //etc
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д