2010-02-20 7 views
6

Tengo esta matriz de 3 x 3 caracteres que se supone que representa un tablero de tres en raya, y antes, usaba un montón de instrucciones "si" para ver si hubo 3 en una fila.C++ - Comprobando 3 en una fila

... if ((Junta [0] [0] == bordo [0] [1]) & & (tablero [0] [1] == bordo [0] [2])) { ... } ...

me di cuenta de que esto es un montón de escribir, y muy propenso a errores, por lo que hay una mejor manera de hacer esto?

+6

9 valores, tres estados cada uno, por lo tanto, dos bits por celda = 18 bits. Eso encaja en una int en cualquier máquina decente. Luego puede hacer un cambio grande o realizar operaciones en modo bit con máscaras predefinidas. –

+0

Mucho mejor idea, Nikolai. +1 –

+0

Tuvimos un concurso de programa corto de tres en raya no hace mucho tiempo: http://stackoverflow.com/questions/2245801/code-golf-tic-tac-toe/2256299#2256299 – Potatoswatter

Respuesta

0

Sí, usted puede hacer esto

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

Tal vez incluso escribir una función

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

Tiene una cara oculta, sin embargo, no lo puedo trabajar si la tarjeta [0] [0], tabla [0] [0], el tablero [0] [1] es igual a 0.

Una alternativa es escribir un bucle for, pero supongo que eso es aún más tipeo.

+0

estaba esperando algo que implique menos tipeo. Todavía necesitaría hacer un 'si' para cada triplete válido. – cornjuliox

+0

No estoy del todo seguro de que esto funcione. Digamos que el primero '==' se evalúa primero y se evalúa como verdadero, luego se obtiene algo como '1 == tablero [0] [2]' que no es lo que el OP pretende. Si va en la dirección opuesta, entonces obtienes 'tabla [0] [0] == 1' que tampoco es lo que el OP intenta. –

+1

Tiene razón, hizo la prueba con int a, b, c = 50,50,50. a == b evalúa a 1 y 1 <> 50. – Tom

1

Puedes repetirlo. Por ejemplo, para verificar todas las filas que puede hacer:

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

Y haga algo similar para las columnas. Entonces solo necesita verificar las diagonales por separado.

+0

Vea el comentario en la respuesta de Tom: no estoy del todo seguro de que el encadenamiento 'operator ==' esté permitido como encadenar 'operator =' is. –

+0

Pero +1 'por' sugerencia de bucles. –

+0

Sí, tampoco estaba seguro, pero solo esperaba que la otra persona tuviera esa parte correcta. Lo cambiaré a lo que sé que es correcto. –

1

Se puede quitar el un paréntesis porque && tiene menor prioridad que ==

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

También puede definir una función línea (o macro) para factorizar la igualdad

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])) 

Nota que a==b==c no devuelve lo que necesita. Por ejemplo, 0==0==1 es verdadero en muchos lenguajes derivados de C.

3

Puede cambiarlo para verificar solo desde donde se realizó el último movimiento.

//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 
} 

O - Comprobación de todos los estados:

//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 
} 

O si lo hace convertirlo en un sistema poco a poco - X mantener separado y juntas S para facilitar la actualización. Entonces solo necesitas 9 bits para x, 9 bits para O, y tus partidas ganadoras son mucho más simples. (Para encontrar espacios abiertos en este caso, solo bit a bit o los tableros y o x)

// 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 
    } 
} 
+0

El único problema con esta respuesta es que no maneja los casos donde un cuadrado está vacío. Si una fila está completamente vacía, informará de éxito, aunque el juego no haya terminado. De lo contrario, +1. –

+0

Buen punto - Lo arreglaré. – Jeff

1

no sé acerca de "mejor", pero se puede romper las cosas en serie:

//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

Adaptado de la competencia Code Golf de la semana pasada. Tenga en cuenta que los patrones lineales a lo largo de la matriz del tablero comienzan en un índice dado y progresan a lo largo de intervalos iguales.

Y si representas al jugador 1 con un 1 y al jugador 2 con un 2, entonces esos son bits independientes y puedes probar 3 seguidos con Y a nivel de bit.

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; 
} 
+0

¡Bastante bonito! Sin embargo, la pregunta se refiere a una matriz de 2 dimensiones, no a una de 1 dimensión. ¿Cómo se puede generalizar este enfoque? ¿Tal vez analizando primero la matriz 2D en una 1D? – Morlock

+0

@Morlock: las matrices 2D y 1D tienen una garantía equivalente. Solo echa, no necesita un análisis. Respuesta editada para caber mejor. – Potatoswatter

0

Aquí es una solución completa, en la forma de una función de comprobación que verifica si un jugador (1 o 2, de pie para X y O) gana:

// 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: He preferido este enfoque (devolver el número del jugador ganador) en lugar de simplemente verificar si hubo un ganador, ya que parecía más práctico para su uso.

Espero que ayude!

+0

¿Por qué molestarse en definir una macro 'DIM' si solo va a codificar las comprobaciones diagonales al final? Además, esta es esencialmente la misma respuesta que publiqué 39 minutos antes que usted. –

+0

Es bastante cierto, excepto que esta solución devuelve al ganador, en lugar de devolver 'verdadera' si hay un ganador. No pretendo que esta sea la mejor respuesta posible, más aún desde que empecé a aprender C++ la semana pasada. Esta puede ser la razón por la cual no identifiqué la similitud de enfoque de su solución, sin embargo, sí se parecen entre sí. Cheers – Morlock

+0

¿Por qué hiciste 'ttt' global? – avakar

0

puede almacenar los índices que componen las filas de ganar, y el uso de un solo bucle:

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; 
} 

También apoyo sugerencias de almacenamiento de los jugadores se mueve en valores independientes y el uso de operaciones bit a bit de Jeff.