C ++ - check for 3 lines

I have this 3 x 3 char array, which should be a tic-tac-toe board, and before, I would use a bunch of if statements to see if there are 3 lines.

... if ((board [0] [0] == board [0] [1]) && (board [0] [1] == board [0] [2])) {...} .. .

I realized that this is gaining a lot and is quite error prone, so is there a better way to do this?

+6
c ++ search
source share
8 answers

You can change it to check only where the last step was taken.

//lr = lastMoveRow //lc = lastMoveCol // no need to check blank with last move known if (board[0][lc] == board[1][lc] && board[0][lc] == board[2][lc] || board[lr][0] == board[lr][1] && board[lr][0] == board[lr][2]){ // Game over } // Check diagonals if (board[1][1] != blank && (board[0][0] == board[1][1] && board[0][0] == board[2][2] || board[2][0] == board[1][1] && board[2][0] == board[0][2])){ // Game over } 

Or - check all states:

 //Check horizontals and verticals at once for (int i = 0; i < 3; ++i){ // Check column and row at once if (board[0][i] != blank && board[0][i] == board[1][i] && board[0][i] == board[2][i] || board[i][0] != blank && board[i][0] == board[i][1] && board[i][0] == board[i][2]){ // Game over } } // Check diagonals if (board[1][1] != blank && (board[0][0] == board[1][1] && board[0][0] == board[2][2] || board[2][0] == board[1][1] && board[2][0] == board[0][2])){ // Game over } 

Or, if you turn it into a battered system, keep separate X and O boards for easy updating. Then you only need 9 bits for x, 9 bits for O, and matching your winning cards is much easier. (To find open spaces in this case, just bitwise or x and o boards)

 // winning 9 bit boards // int winningBoards[8] 000000111 000111000 111000000 001001001 010010010 100100100 100010001 001010100 //xBoard and yBoard can be ints for (int i = 0; i < 8; ++i){ if (xBoard & winningBoards[i] == winningBoards[i]){ //Game over } } 
+3
source share

You can encode it. For example, to check all the lines you can do:

 for(int i = 0; i < 3; i++){ if((board[i][0]==board[i][1]) && (board[i][1]==board[i][2])){ .... } } 

And do something similar for the columns. Then you just need to check the diagonals separately.

+1
source share

You can remove the parenthesis because && has a lower priority than ==

 if (board[0][0] == board[0][1] && board[0][1] == board[0][2]) 

You can also define an inline function (or macro) to split equality

 inline bool are_equal(int a, int b, int c) { return a == b && b == c; } ... if (are_equal(board[0][0], board[0][1], board[0][2])) 

Note that a==b==c does not return what you need. For example, 0==0==1 is true in many C-type languages.

+1
source share

I donโ€™t know about โ€œbetter,โ€ but you can break it down in order:

 //Set empty to whatever value you're using for an empty square. #define empty '\0' bool thereIsALine(char matrix[3][3]) { char c; //Check all columns: for(int i = 0; i < 3; i++) { c = matrix[i][0]; if (c == empty) break; if (c == matrix[i][1] && c == matrix[i][2]) return true; } //Check all rows: for(int i = 0; i < 3; i++) { c = matrix[0][i]; if (c == empty) break; if (c == matrix[1][i] && c == matrix[2][i]) return true; } //Check diagonals c = matrix[1][1]; if (c == empty) return false; if (c == matrix[0][2] && c == matrix[2][0] ) return true; if (c == matrix[0][0] && c == matrix[2][2] ) return true; return false; } 
+1
source share

Adapted from Code Golf last week. Please note that linear patterns along the matrix of boards begin at a given index and run evenly.

And if you represent player 1 with 1, and player 2 with 2, then these are independent bits, and you can test 3 on a line with bitwise I.

 char check_1row( char *board, int base, int stride ) { return board[ base ] & board[ base + stride ] & board[ base + 2 * stride ]; } char check_win( char (&board)[3][3] ) { char winner = 0; winner |= check1row( board, 0, 4 ); // check NW/SE diagonal for ( int i = 0; i < 3; i ++ ) { winner |= check1row( board, i, 3 ); // check verticals } winner |= check1row( board, 2, 2 ); // check NE/SW diagonal for ( int i = 0; i < 9; i += 3 ) { winner |= check1row( board, i, 1 ); // check horizontals } return winner; } 
+1
source share

Yes you could do it

 if (board[0][0]==board[0][1]==board[0][2]) {...} 

Itโ€™s even possible to write a function

 inline boolean row_win(int row_num){ return (board[row_num][0]==board[row_num][1]==board[row_num][2]); } 

It has a hidden side, although it will not work if board [0] [0], board [0] [0], board [0] [1] are 0. Strike>

An alternative is to write a for loop, but I think it prints even more.

0
source share

Here is a complete solution in the form of a check function that checks if a player wins (1 or 2 standing for X and O):

 // tic tac toe win checker #include<iostream> using namespace std; const int DIM = 3; int check (int t[DIM][DIM]) { // 0 is empty, 1 is X, 2 is O // return 1 or 2 if there is a win from either for (int row=0; row<DIM; row++) { if (t[row][0] == t[row][1] && t[row][1] == t[row][2]) { if (t[row][0] != 0) return t[row][0]; } } for (int col=0; col<DIM; col++) { if (t[0][col] == t[1][col] && t[0][col] == t[2][col]) { if (t[0][col] != 0) return t[0][col]; } } if (t[0][0] == t[1][1] && t[1][1] == t[2][2]) { if (t[0][0] != 0) return t[0][0]; } if (t[0][2] == t[1][1] && t[1][1] == t[2][0] != 0) { if (t[0][2] != 0) return t[0][2]; } return 1; } int main() { int ttt[DIM][DIM]; ttt[1][0] = 2; // Initialyzing row no. 2 to values "2" to test ttt[1][1] = 2; ttt[1][2] = 2; if (check(ttt) != 0) { cout << "Player " << check(ttt) << " wins\n"; } else { cout << "No winner yet\n"; } } 

EDIT: I preferred this approach (by returning the number of the winning player), rather than just checking if the winner was, as it seemed more practical to use.

Hope this helps!

0
source share

You can store the indices that make up the winning lines and use one loop:

 int win_row[][3] = {{0, 0, 0}, {1, 1, 1}, {2, 2, 2}, {0, 1, 2}, {0, 1, 2}, {0, 1, 2}, {0, 1, 2}, {0, 1, 2}}; int win_col[][3] = {{0, 1, 2}, {0, 1, 2}, {0, 1, 2}, {0, 0, 0}, {1, 1, 1}, {2, 2, 2}, {0, 1, 2}, {2, 1, 0}}; bool has_winner(char board[][3]) { //'\0' means unoccupied for (int i = 0; i != 8; ++i) { char c = board[win_row[i][0]][win_col[i][0]]; if (c && c == board[win_row[i][1]][win_col[i][1]] && c == board[win_row[i][2]][win_col[i][2]]) { return true; } } return false; } 

I also support Jeff's suggestions for storing player movements in separate values โ€‹โ€‹and using bitwise operations.

0
source share

All Articles