How to place a domino piece to the left of 6|6 in C?

Asked

Viewed 129 times

4

I’m having trouble with the domino game I created.

I can add the pieces to the right, but when I try to add to the left it does not perform as intended.

Here is an example:

  • Move 1 -> Table 6|6

  • Move 2 -> Table 6|6 6|2

  • Move 3 -> Table 1|6 1|6 6|2 (replace 6|6 by the piece on the left)

  • Move 4 -> Mesa 2|1 2|1 1|6 6|2 (continue)

My code:

void jogarpeca(pdomino vp[], int *n, pdomino t,char x) {
    (*n)++;
    int i;

    if(x=='f') {
        vp[*n]=t;
    }
    else {
        for(i=*n;i>=2;i--) {
            vp[i]=vp[i-1];
            vp[1]=t;
        }
    }
}

void retirarpeca(pdomino vp[], int *n, int t) {
   (*n)--;
   int i;

    for(i=t;i<=*n;i++) {
        vp[i]=vp[i+1];
    }
}

void jogar(jogador vj[],pdomino vp[], int *n, int j, int i, char c) {
    int ini,fim;

    ini=vp[1].lado1;
    fim=vp[*n].lado2;

    printf("NA MESA ");
    escreverpecas(vp,*n);
    printf("\n\n");
    escreverjogadores(vj);

    if(i==0) {
        printf("%s passa a sua vez...\n\n",vj[j].nome);
    }
    else {
        if(c=='i') {
            if(vj[j].pecas[i].lado2!=ini) {
                rodarpeca(&(vj[j].pecas[i]));
                printf("%s joga %d|%d no Inicio\n\n\n",vj[j].nome,vj[j].pecas[i].lado1,vj[j].pecas[i].lado2);
            }
            else {
                printf("%s joga %d|%d no Inicio\n\n\n",vj[j].nome,vj[j].pecas[i].lado1,vj[j].pecas[i].lado2);
            }
        }
        else {
            if(vj[j].pecas[i].lado1!=fim) {
                rodarpeca(&(vj[j].pecas[i]));
                printf("%s joga %d|%d no Fim\n\n\n",vj[j].nome,vj[j].pecas[i].lado1,vj[j].pecas[i].lado2);
            }
            else {
                printf("%s joga %d|%d no Fim\n\n\n",vj[j].nome,vj[j].pecas[i].lado1,vj[j].pecas[i].lado2);
            }
        }

        jogarpeca(vp, &(*n), vj[j].pecas[i], c);
        retirarpeca(vj[j].pecas,&(vj[j].totalpecas), i);
    }

    getchar();
}

void jogadas(pdomino vp[], int *n, jogador vj[], int j) {
    int ini,fim,i;
    int k=0;

    int p[9];
    char c[9];

    ini=vp[1].lado1;
    fim=vp[*n].lado2;

    for(i=1;i<=vj[j].totalpecas;i++) {
        if(vj[j].pecas[i].lado1==ini) {
            k++;
            p[k]=i;
            c[k]='i';
        }

        if(vj[j].pecas[i].lado2==ini) {
            k++;
            p[k]=i;
            c[k]='i';
        }

        if(vj[j].pecas[i].lado1==fim) {
            k++;
            p[k]=i;
            c[k]='f';
        }

        if(vj[j].pecas[i].lado2==fim) {
            k++;
            p[k]=i;
            c[k]='f';
        }
    }

    if(k==0) {
        jogar(vj,vp, &(*n), j, 0, 'x');
    }
    else {
        printf("funcao jogadas o k : %d",k);
        getchar();
        int x=k/*randi(1,k)*/;
        printf("funcao jogadas o x : %d",x);
        getchar();
        jogar(vj,vp, &(*n), j, p[x], c[x]);
    }
}

int jogar66(jogador vj[],pdomino vp[], int *n) {
    int j,i,j1,p1;

    for(j=1;j<=totaljogadores;j++) {
        for(i=1;i<=vj[j].totalpecas;i++) {
            if(vj[j].pecas[i].lado1==6 && vj[j].pecas[i].lado2==6) {
                j1=j;
                p1=i;
            }
        }
    }
    jogar(vj,vp,&(*n),j1,p1, 'f');
    return j1;
}

int ganha(jogador vj[]) {
    int jg,j;
    jg=0;

    for(j=1;j<=totaljogadores;j++) {
        if(vj[j].totalpecas==0) {
            jg=j;
        }
    }
    return jg;
}

int fecha(pdomino vp[], int n) {
    int p,q,i,c;
    c=0;
    p=vp[1].lado1;

    for(i=1;i<=n;i++) {
        if(vp[i].lado1==p) {
            c++;
        }

        if(vp[i].lado2==p) {
            c++;
        }
    }

    return c==8;
}

int acaba(jogador vj[], pdomino vp[], int n) {
    return ganha(vj) || fecha(vp, n);
}

int main() {
    srand(time(0));

    int i,j,p,x,contax;
    contax=0;
    pdomino vp[29];
    jogador vj[5];
    int n=0;

    criartodaspecas(vp);
    baralharpecas(vp);
    criarjogadores(vj,vp);

    x=1;
    printf("\n**********Jogada n' %d **********\n\n",x);
    j=jogar66(vj,vp,&n);
    getchar();

    while(!acaba(vj,vp,n)) {
        j=j+1;
        if(j==5) {
            j=1;
        }
        x++;

        printf("\n**********Jogada n' %d **********\n\n",x);
        jogadas(vp, &n, vj, j);
    }
}

1 answer

3


Before addressing the question, I will point out some problems in your code:

  • its modular calculation is problematic
    5 is equivalent to 0 mod 5, not 1
    5 is only equivalent to 1 mod 4 or mod 2
  • at several points in your code, you are considering that the vector starts at index 1, not at index 0
    and still have confusion points where you put things on the index 0
  • 0 is not NULL to be argument of time()
  • the function jogarpeca() has two responsibilities, when it should have only one:
    1. place the piece in the appropriate position (due responsibility)
    2. increase the turn counter (undue liability)
  • in the iteration of the operation shift, you’re doing an assignment that has nothing to do with

With that out of the way, let’s get to the answer.

Data structure

To represent a domino world (not the players), we need to store pieces that are played at both ends. But it cannot be any piece that can be played, only those that match the already existing piece at the end (with the exception of the first piece thrown, which is placed by convention).

With this description, we need to have two operations for each of the ends:

  • peek, where it is checked which part is at the end
  • push, which pushes the piece to the end

As dominoes are a linear world, the ends are left and right, so we have 4 operations:

  • peek_left
  • peek_rigth
  • push_left
  • push_right

For a more complete strategy it is necessary to iterate on the pieces, but I will not go into detail on how to do this.

We then need to have a linear storage scheme. C provides us with two alternatives to this:

  • contiguous positioning
  • pointer to the next element

These alternatives are:

  • vector
  • linked list

Satellite features

To be able to access the extremes properly, simply storing the vector/pointer for the first element of the list is not enough.

In the case of the vector, it is necessary to know how many positions have already been occupied. It is also suitable to know the total size of the vector to burst, to give security to the program.

For linked lists, to access o(1) and to facilitate coding, both for peek how much to push, we need to know who is the beginning and who is the end. In the first move, the start and end pointers of the list point to this piece.

The pieces have two properties each:

  • left, indicating the number on the left
  • right, indicating the number on the right

It is possible to rotate a part, where the values left and right are exchanged.

Operation peek

  • peek_left
    • vector: v[0].left
    • list: inicio->peca.left
  • peek_right
    • vector: v[ocupados - 1].right
    • list: fim->peca.right

If you want to get the part, just don’t get the value of the field.

Operations of push

in the example, the pieces A, B and C are already on the board in that order. The piece to be inserted is Ω

To make the push, the considerations are different. In the case of the vector, one should check if it has position remaining to include the new element or then, if not, treat in some way the absence of positions (either allocating more space or returning error code). I will not dwell on this, but be aware of it.

For vector, the push_right is just putting into position v[ocupado] Ω and increase the value of ocupado:

enter image description here

To then get the following result:

enter image description here

For the list, the next node C for the node of Ω, then point the end to the node of Ω.

enter image description here

Sort of like this:

fim->next = novo;
fim = novo;

To get the following result:

enter image description here

For the left push operation, the list is easier. You point the following of the Ω node to A and then points the beginning to node Ω.

You start like this:

enter image description here

Do the pointer change operation:

novo->next = inicio;
inicio = novo;

Then get the following result:

enter image description here

In the case of the vector, pushing the left is first required to make a shift to have a free position on the left. You start with that state:

enter image description here

Does the shift:

enter image description here

To have the following intermediate state:

enter image description here

So just do v[0] = peca_nova:

enter image description here

The only care to be taken is that you need to do the shift right to left:

int i;
for (i = ocupado - 1; i >= 0; i--) {
  v[i + 1] = v[i];
}
  • Thank you for your reply. As I am beginning to learn how to program in C, I have not yet learned these operations. for(i=t;i<=*n;i++) { Vp[i]=Vp[i+1]; Vp[i]=t; &##Xa; and should have for(i=t;i<=*n;i+) Vp[i]=Vp[i+1]; Vp[i]=t; &##Xa; or without braces.

  • I just finished my reply. I had put in submit unintentionally. Should answer your questions

Browser other questions tagged

You are not signed in. Login or sign up in order to post.