Q:

How can I change an int array in a function

Im new with c language and im having difficult while trying to change an array on my main function using another function. Besides seeing the solution I'd also like to get a full explanation what is wrong with my code and what's the explanation to your solution. 
OK so I did too much tryouts and error experimentation but with no success to solve my problem. Eventually this is my current code:
#include <stdio.h>
#define MAX 20
typedef int Values[MAX];

int changeArr(Values *vals2) 
{
    *vals2[0] = 200;
    *vals2[1] = 100;
    printf("%d and ", *vals2[0]);
    printf("%d\n", *vals2[1]);
    return 0;
}   

int main (int argc, char *argv[]) 
{
    Values vals;
    changeArr(&vals);
    printf("%d and ", vals[0]);
    printf("%d\n", vals[1]);
    return 0;
}

Output is:
200 and 100
200 and 0

Instead of:
200 and 100
200 and 100

A:

Version 1:
#include <stdio.h>
#define MAX 20
typedef int Values[MAX];

int changeArr(int vals2[]) {
    vals2[0] = 200;
    vals2[1] = 100;
    printf("%d and ", vals2[0]);
    printf("%d\n", vals2[1]);
    return 0;
}   

int main (int argc, char *argv[]) {

    Values vals;
    changeArr(vals);
    printf("%d and ", vals[0]);
    printf("%d\n", vals[1]);
    return 0;

}

Instead of passing a pointer to the array, pass a pointer to the array's first element.
Version 2:
#include <stdio.h>
#define MAX 20
typedef int Values[MAX];

int changeArr(Values *vals2) {
    (*vals2)[0] = 200;
    (*vals2)[1] = 100;
    printf("%d and ", (*vals2)[0]);
    printf("%d\n", (*vals2)[1]);
    return 0;
}   

int main (int argc, char *argv[]) {

    Values vals;
    changeArr(&vals);
    printf("%d and ", vals[0]);
    printf("%d\n", vals[1]);
    return 0;

}

use parentheses to compensate for the precedence.
The problem in your code is that
*vals2[1]

is *(vals2[1]), so it dereferences a pointer one unit of Values after the passed pointer. You have no accessible memory allocated there, so it's undefined behaviour. In practice, it is the same as accessing
arr[1][0]

for an
int arr[2][MAX];

But your vals is only (equivalent to) an int arr[1][MAX];, so you are accessing out of bounds. But if nothing worse happens, *vals2[1] = 100; in changeArr sets vals[MAX] in main to 100. It may overwrite something crucial, though.
In int changeArr(Values *vals2) you are passing a pointer to an array of MAX ints, resp the first such array in an array of Values. Then vals2[1] is the second array in that array of Values (which doesn't exist here), and *vals2[1] == vals2[1][0] the first int in that second array. You want to modify elements of the first (and only) array in the pointed-to memory block, so you want to access vals2[0][1], or equivalently (*vals2)[1].
A picture:
vals2                          vals2[1]
 |                               |
 v                               v
|vals[0]|vals[1]|...|vals[MAX-1]|x

in changeArr, the pointer vals2 points to the array vals. Since it's a pointer to an int[MAX], vals2+1 points to an int[MAX] at an offset of MAX*sizeof(int) bytes after the start of vals (which is just behind the end of vals). vals2[1], or equivalently *(vals2 + 1), is that array just after vals (which doesn't exist).
You want to change vals[1], which is located in the array vals2[0], at an offset of 1*sizeof(int) bytes, so you need vals2[0][1] or equivalently (*vals2)[1].

