Hello I'm new at programming and I need to print an array (must be 1 dimensionnal) like a grid. I tried for hours now and still don't have the results I want.
The array has 16 values so the grid would be something like this :
___________
|0 |1 |2 |3 |
|4 |5 |6 |7 |
|8 |9 |10|11|
|12|13|14|15|
–––––––––––––
My code :
#include <stdio.h>
void display_grid(void)
{
int i;
int j;
int cell[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
for (i = 0; i < 4; i++)
{
printf("|");
for (j = 0; j < 16; j++)
{
printf("%d|",cell[j]);
}
printf("\n");
}
}
int main()
{
display_grid();
return 0;
}
Displays this :
|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|
|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|
|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|
|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|
I have a feeling that this would work: I changed cell[j] to cell[4 * i + j]
#include <stdio.h>
void display_grid(void)
{
int i;
int j;
int cell[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
for (i = 0; i < 4; i++)
{
printf("|");
for (j = 0; j < 4; j++)
{
printf("%d|",cell[4 * i + j]);
}
printf("\n");
}
}
int main()
{
display_grid();
return 0;
}
Does this help?
You can use the remainder operator % to determine when to print on a new line. Here is an example program with a display_grid() function that takes as arguments an array of int, the size of the array, and the desired size of each row. If the array can be evenly divided into rows of the desired number of columns, zero is returned. Otherwise a non-zero value is returned. This allows you to display a 1d array in various grid formats; nothing is printed if the array can't be evenly divided.
Currently this prints grids containing numbers with at most 2 digits (or 1 digit and a sign). It would be simple to modify it to print more digits, or a little more involved to modify so that the display width fits the maximum width needed for the input.
#include <stdio.h>
#define ARR_SZ 16
int display_grid(int *arr, size_t arr_sz, size_t row_sz);
int main(void)
{
int array[ARR_SZ];
for (size_t i = 0; i < ARR_SZ; i++) {
array[i] = i;
}
size_t row_sz = 4;
if (display_grid(array, ARR_SZ, row_sz) != 0) {
fprintf(stderr, "Array size not evenly divisible by %zu\n", row_sz);
}
row_sz = 8;
if (display_grid(array, ARR_SZ, row_sz) != 0) {
fprintf(stderr, "Array size not evenly divisible by %zu\n", row_sz);
}
row_sz = 2;
if (display_grid(array, ARR_SZ, row_sz) != 0) {
fprintf(stderr, "Array size not evenly divisible by %zu\n", row_sz);
}
row_sz = 1;
if (display_grid(array, ARR_SZ, row_sz) != 0) {
fprintf(stderr, "Array size not evenly divisible by %zu\n", row_sz);
}
row_sz = 16;
if (display_grid(array, ARR_SZ, row_sz) != 0) {
fprintf(stderr, "Array size not evenly divisible by %zu\n", row_sz);
}
row_sz = 6;
if (display_grid(array, ARR_SZ, row_sz) != 0) {
fprintf(stderr, "Array size not evenly divisible by %zu\n", row_sz);
}
row_sz = 32;
if (display_grid(array, ARR_SZ, row_sz) != 0) {
fprintf(stderr, "Array size not evenly divisible by %zu\n", row_sz);
}
return 0;
}
int display_grid(int *arr, size_t arr_sz, size_t row_sz)
{
int ret_val = arr_sz % row_sz;
if (ret_val == 0) {
/* Print top border */
putchar(' ');
for (size_t i = 1; i < 3 * row_sz; i++) {
putchar('_');
}
putchar('\n');
/* Print rows of grid */
for (size_t i = 0; i < arr_sz; i++) {
printf("|%-2d", arr[i]);
if ((i + 1) % row_sz == 0) {
printf("|\n");
}
}
/* Print bottom border */
for (size_t i = 0; i < 3 * row_sz + 1; i++) {
putchar('-');
}
putchar('\n');
}
return ret_val;
}
Program output:
___________
|0 |1 |2 |3 |
|4 |5 |6 |7 |
|8 |9 |10|11|
|12|13|14|15|
-------------
_______________________
|0 |1 |2 |3 |4 |5 |6 |7 |
|8 |9 |10|11|12|13|14|15|
-------------------------
_____
|0 |1 |
|2 |3 |
|4 |5 |
|6 |7 |
|8 |9 |
|10|11|
|12|13|
|14|15|
-------
__
|0 |
|1 |
|2 |
|3 |
|4 |
|5 |
|6 |
|7 |
|8 |
|9 |
|10|
|11|
|12|
|13|
|14|
|15|
----
_______________________________________________
|0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10|11|12|13|14|15|
-------------------------------------------------
Array size not evenly divisible by 6
Array size not evenly divisible by 32
Related
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define MAX_ELEMENTS 1000
#define OFFSET 100
#define MAX_LINES 10
int a[MAX_ELEMENTS] ;
int comp, swap ;
void quicksort(int [],int ,int);
void init_step(void);
void print_step(int);
void print_header(char *);
int sorted(int);
void swap1(int*,int*);
int main(void){
int i;
int n;
srandom(time(0));
print_header("random");
for (n = OFFSET; n <= MAX_ELEMENTS; n += OFFSET) {
init_step();
for (i = 0; i < n; i++) {
a[i] = random() % n ;
}
quicksort(a,0,n-1);
print_step(n);
}
print_header("ascending order");
for (n = OFFSET; n <= MAX_ELEMENTS; n += OFFSET) {
init_step();
for (i = 0; i < n; i++) {
a[i] = i ;
}
quicksort(a,0,n-1);
print_step(n);
}
print_header("descending order");
for (n = OFFSET; n <= MAX_ELEMENTS; n += OFFSET) {
init_step();
for (i = 0; i < n; i++) {
a[i] = n - i ;
}
quicksort(a,0,n-1);
print_step(n);
}
return 0;
}
void init_step(void){
swap = 0; comp = 0;
}
void print_header(char *s) {
printf("%s\n n, comparison, swap, check", s);
printf("\n");
}
void print_step(int n){
printf("%4d, %8d, %8d", n, comp, swap);
if (sorted(n)) {
printf(", sorted\n");
} else {
printf(", unsorted\n");
}
}
int sorted(int n) {
int i;
for (i=0; i < n-1; i++)
if (a[i] > a[i+1]) return 0;
return 1;
}
void swap1(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
swap++;
}
void quicksort(int number[25],int first,int last){
int i, j, pivot, temp;
if(first<last){
pivot=first;
i=first;
j=last;
while(i<j){
while(number[i]<=number[pivot]&&i<last)
i++;
comp++;
while(number[j]>number[pivot])
j--;
comp++;
if(i<j){
swap1(&number[i], &number[j]);
}
}
temp=number[pivot];
number[pivot]=number[j];
number[j]=temp;
quicksort(number,first,j-1);
quicksort(number,j+1,last);
}
}
so i have this code to count comparison and swap of quicksort at c max element means the maximum data and offset means Incremental value of the number of data.
the one i want to ask is for the random case is count perfectly but for descending and ascending case the value of the comparison and swap is all the same. and swap values is always 0
to be more specific i will post the result below
random
| n |comparison| swap| check|
|:---: |:--------:|:---:|:----:|
|100 | 316 | 89 |sorted|
|200 | 756 | 244 |sorted|
|300 | 1156 | 375 |sorted|
|400 | 1630 | 552 |sorted|
|500 | 2164 | 745 |sorted|
|600 | 2682 | 932 |sorted|
|700 | 3202 |1125 |sorted|
|800 | 3776 |1351 |sorted|
|900 | 4286 |1539 |sorted|
|1000 | 4732 |1678 |sorted|
ascending order
| n |comparison| swap| check |
|:---:|:--------:|:---:|:-----:|
|100 | 198 | 0 | sorted|
|200 | 398 | 0 | sorted|
|300 | 598 | 0 | sorted|
|400 | 798 | 0 | sorted|
|500 | 998 | 0 | sorted|
|600 | 1198 | 0 | sorted|
|700 | 1398 | 0 | sorted|
|800 | 1598 | 0 | sorted|
|900 | 1798 | 0 | sorted|
|1000 | 1998 | 0 | sorted|
descending order
| n |comparison| swap| check |
|:---:|:--------:|:---:|:-----:|
|100 | 198 | 0 | sorted|
|200 | 398 | 0 | sorted|
|300 | 598 | 0 | sorted|
|400 | 798 | 0 | sorted|
|500 | 998 | 0 | sorted|
|600 | 1198 | 0 | sorted|
|700 | 1398 | 0 | sorted|
|800 | 1598 | 0 | sorted|
|900 | 1798 | 0 | sorted|
|1000 | 1998 | 0 | sorted|
is there any one know why my ascending and descending case show same value of comparison and swap count?
and i think for the ascending comparison count is not supposed to be this high isn't it?
You have:
temp = number[pivot];
number[pivot] = number[j];
number[j] = temp;
That looks like a swap, but you don't count it as one. You also have:
while (number[i] <= number[pivot] && i < last)
i++;
comp++;
The comp++; is outside the loop, so you are miscounting the comparisons too. That occurs twice.
With this version of your code, I get more plausible results:
/* SO 7273-8321 */
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define MAX_ELEMENTS 1000
#define OFFSET 100
#define MAX_LINES 10
int a[MAX_ELEMENTS];
int comp, swap;
void quicksort(int[], int, int);
void init_step(void);
void print_step(int);
void print_header(char *);
int sorted(int);
void swap1(int *, int *);
int main(void)
{
int i;
int n;
srandom(time(0));
print_header("random");
for (n = OFFSET; n <= MAX_ELEMENTS; n += OFFSET)
{
init_step();
for (i = 0; i < n; i++)
{
a[i] = random() % n;
}
quicksort(a, 0, n - 1);
print_step(n);
}
print_header("ascending order");
for (n = OFFSET; n <= MAX_ELEMENTS; n += OFFSET)
{
init_step();
for (i = 0; i < n; i++)
{
a[i] = i;
}
quicksort(a, 0, n - 1);
print_step(n);
}
print_header("descending order");
for (n = OFFSET; n <= MAX_ELEMENTS; n += OFFSET)
{
init_step();
for (i = 0; i < n; i++)
{
a[i] = n - i;
}
quicksort(a, 0, n - 1);
print_step(n);
}
return 0;
}
void init_step(void)
{
swap = 0;
comp = 0;
}
void print_header(char *s)
{
printf("%s\n n, comparison, swap, check", s);
printf("\n");
}
void print_step(int n)
{
printf("%4d, %8d, %8d", n, comp, swap);
if (sorted(n))
{
printf(", sorted\n");
}
else
{
printf(", unsorted\n");
}
}
int sorted(int n)
{
int i;
for (i = 0; i < n - 1; i++)
if (a[i] > a[i + 1])
return 0;
return 1;
}
void swap1(int *xp, int *yp)
{
int temp = *xp;
*xp = *yp;
*yp = temp;
swap++;
}
void quicksort(int number[25], int first, int last)
{
int i, j, pivot, temp;
if (first < last)
{
pivot = first;
i = first;
j = last;
while (i < j)
{
while (number[i] <= number[pivot] && i < last)
{
i++;
comp++;
}
while (number[j] > number[pivot])
{
j--;
comp++;
}
if (i < j)
{
swap1(&number[i], &number[j]);
}
}
temp = number[pivot];
number[pivot] = number[j];
number[j] = temp;
swap++;
quicksort(number, first, j - 1);
quicksort(number, j + 1, last);
}
}
Example output:
random
n, comparison, swap, check
100, 644, 172, sorted
200, 1703, 367, sorted
300, 2845, 592, sorted
400, 3493, 840, sorted
500, 5020, 1094, sorted
600, 6206, 1327, sorted
700, 7279, 1617, sorted
800, 8784, 1827, sorted
900, 9342, 2143, sorted
1000, 10185, 2470, sorted
ascending order
n, comparison, swap, check
100, 5049, 99, sorted
200, 20099, 199, sorted
300, 45149, 299, sorted
400, 80199, 399, sorted
500, 125249, 499, sorted
600, 180299, 599, sorted
700, 245349, 699, sorted
800, 320399, 799, sorted
900, 405449, 899, sorted
1000, 500499, 999, sorted
descending order
n, comparison, swap, check
100, 4999, 99, sorted
200, 19999, 199, sorted
300, 44999, 299, sorted
400, 79999, 399, sorted
500, 124999, 499, sorted
600, 179999, 599, sorted
700, 244999, 699, sorted
800, 319999, 799, sorted
900, 404999, 899, sorted
1000, 499999, 999, sorted
I am getting an exception when printing a two-dimensional array after initializing it using memset. If I initialize each element and then access it, then there is no error.
Please help to figure out the bug in the code.
#include "stdafx.h"
#include "stdlib.h"
int r = 0;
int c = 0;
int **twoDArray() {
int *arr[5];
for (r = 0; r < 5; r++) {
arr[r] = (int*)malloc(2 * sizeof(int));
}
//
for (r = 0; r < 5; r++) {
for (c = 0; c < 2; c++) {
arr[r][c] = 1;
printf("%d \n", arr[r][c]);
}
}
memset(arr, 0, 2 * 5 * sizeof(arr[0][0]));
for (r = 0; r < 5; r++) {
for (c = 0; c < 2; c++) {
printf("%d \n", arr[r][c]); //getting exception here.
}
}
return arr;
}
int main()
{
int **arr;
arr = twoDArray();
for (r = 0; r < 5; r++) {
for (c = 0; c < 2; c++) {
arr[r][c] = 0;
printf("%d \n", arr[r][c]);
}
}
return 0;
}
You don't have a 2D array. You have a 1D array of pointers to 1D arrays; each of these arrays can be (and 99.9% likely is) at a different address in memory. You therefore cannot treat them as one continuous block, as memset does.
The best (and most cache-friendly) option is to allocate the entire array dynamically:
int *arr = malloc(2 * 5 * sizeof(int));
This will require you to then do manual indexing:
for (r = 0; r < 5; r++) {
for (c = 0; c < 2; c++) {
arr[r * 2 + c] = 1;
printf("%d \n", arr[r * 2 + c]);
}
}
If you know the array size at compile time (if the 2 and 5 are actual constants), you can also make arr a pointer to an actual array, to allow syntactic 2D indexing:
typedef int Array[2];
Array *arr = malloc(5 * sizeof(Array));
for (r = 0; r < 5; r++) {
for (c = 0; c < 2; c++) {
arr[r][c] = 1;
printf("%d \n", arr[r][c]);
}
}
Note that in your original code, there was also the problem you were returning a pointer into arr, which is a local variable, making the pointer immediately dangling.
This is an array of pointers. You can be sure of two things
arr[0] to arr[4] is contiguous.
The chunk allocated is contiguous.
But who told you that the memory block allocated by each malloc which each of the pointer points to is contiguous also? Nobody did. You assumed it wrong.
In your case that's definitely not the case. That's why you invoked undefined behavior by accessing memory out of bound. (in memset).
Do this though - it would work
int (*arr)[2];
arr = malloc(sizeof *arr * 5);
// do memset - it's fine.
Don't cast the return value of malloc. It's redundant.
Something like this in earlier case:-
+-------------+
+-------+ +------>+ arr[0][0] |
arr[0] | | | | | arr[0][1]
| +-------------+ +------+------+
+-------+
| | +------+------+
arr[1] | +------->+ | |
+-------+ | | |
| | +-------------+ +------+------+
arr[2] | +-------------------------------------+ | |
+-------+ | | |
| | | +------+------+ +------+------+
arr[3] | +------------------>+ | |
+-------+ | | |
| | +------+------+
arr[4] | + |
+-------+
| +------+------+
+----------------------->+ | |
| | |
+------+------+
I have some problem about Nested Loop on C programming
I tried to print the list like this:
| |0|1|2|3|4|5|6|7|8|9|
|0| | | | | | | | | | |
|1| | | | | | | | | | |
|2| | | | | | | | | | |
|3| | | | | | | | | | |
|4| | | | | | | | | | |
|5| | | | | | | | | | |
|6| | | | | | | | | | |
|7| | | | | | | | | | |
|8| | | | | | | | | | |
|9| | | | | | | | | | |
but there are something problem when i type my code and display:
| |0|1|2|3|4|5|6|7|8|9|
|0|0|0|0|0|0|0|0|0|0|0|
|1|0|1|1|1|1|1|1|1|1|1|
|2|0|2|2|2|2|2|2|2|2|2|
|3|0|3|3|3|3|3|3|3|3|3|
|4|0|4|4|4|4|4|4|4|4|4|
|5|0|5|5|5|5|5|5|5|5|5|
|6|0|6|6|6|6|6|6|6|6|6|
|7|0|7|7|7|7|7|7|7|7|7|
|8|0|8|8|8|8|8|8|8|8|8|
|9|0|9|9|9|9|9|9|9|9|9|
There is my code :
void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player)
{
int i, j;
printf("| ");
for (j = 0; j < BOARD_WIDTH; j++)
{
printf("|%d",j);
}
printf("|\n");
for (i = 0; i < BOARD_HEIGHT; i++)
{
for (j = 0; j < BOARD_WIDTH; j++)
{
printf("|%d",i);
if (j == 0)
{
printf("|%d",j);
}
}
printf("|\n");
}
printf("\n");
}
Have someone can help for this condition: only one row and one column, other is empty.
At no point in the body of the inner loop are you printing spaces. You're instead printing the value of i, which is the column number.
printf("|%d",i);
if (j == 0)
{
printf("|%d",j);
}
Instead, print i only on the first iteration and print the space each time:
if (j == 0) {
printf("|%d",i);
}
printf("| ");
Output:
| |0|1|2|3|4|5|6|7|8|
|0| | | | | | | | | |
|1| | | | | | | | | |
|2| | | | | | | | | |
|3| | | | | | | | | |
|4| | | | | | | | | |
|5| | | | | | | | | |
|6| | | | | | | | | |
|7| | | | | | | | | |
|8| | | | | | | | | |
The key to getting this done correct is enclosing the repeating logic (the blank cells) in the loop while confining the specialized logic to be outside the loop:
void displayBoard(int height, int width)
{
int i, j;
printf("| ");
for (j = 0; j < width; j++) {
printf("|%d", j);
}
printf("|\n");
for (i = 0; i < height; i++) {
printf("|%d", i);
for (j = 0; j < width; j++) {
printf("| ");
}
printf("|\n");
}
}
Look mom! no ifs
This is how you should code it:
void displayBoard(Cell board[BOARD_HEIGHT][BOARD_WIDTH], Player * player)
{
int i, j;
printf("| ");
for (j = 0; j < BOARD_WIDTH; j++)
{
printf("|%d",j);
}
printf("|\n");
for (i = 0; i < BOARD_HEIGHT; i++)
{
for (j = 0; j < BOARD_WIDTH; j++)
{
if (j == 0)
{
printf("|%d",i);
}
printf("| ");
}
printf("|\n");
}
printf("\n");
}
There are couple of issues with your current code:
You printf("|%d",i); in the inner loop for every j while what you really want is just to print it when j == 0 once. The rests, you want to printf("| "):
printf("| "); //you want to make this blank
if (j == 0)
{
printf("|%d",i); //you want to print i here, not j
}
between the print of number when j == 0 and the print of blank should be reversed:
if (j == 0)
{
printf("|%d",i); //you want to print i here, not j
}
printf("| "); //put the blank printing after the number
You are printing the number i in every line, when you want a blank or the array data. you also need to get rid of printing a zero every row, which is what you have coded in. Here is that part of the code corrected:
for (i = 0; i < BOARD_HEIGHT; i++)
{
for (j = 0; j < BOARD_WIDTH; j++)
{
if (j == 0)
{
printf("|%d",i);
}
printf("| "); ///or printf("|%d",board[i][j]) if you are after stored data
}
printf("|\n");
}
hope this helps.
Try this:
#define BOARD_HEIGHT 10
#define BOARD_WIDTH 10
void displayBoard()
{
int i, j;
printf("| ");
for (j = 0; j < BOARD_WIDTH; j++)
{
printf("|%d", j);
}
printf("|\n");
for (i = 0; i < BOARD_HEIGHT; i++)
{
printf("|%d", i);
for (j = 1; j < BOARD_WIDTH; j++)
{
printf("| ");
}
printf("| |\n");
}
}
BTW, there is no need to pass any arguments to this function.
I am trying to recreate the game 2048 in C, but I can't get the algorithms to move or merge tiles together to function properly.
In the original 2048 game you would move tiles together like this:
2 | 2 | 4 | 4 4 | 8 | |
---+---+---+--- *swipes to the left* -> ---+---+---+---
8 | | 8 | 16| | |
So two tiles that are the same can merge into one tile that is twice the size. My version is almost the same, but instead of using numbers I use characters that increment by one when they merge, so[A|A] would merge to [B], etc. I did that only to not have to deal with varying size tiles.
So my board is stored as a 4*4 char array inside a struct I called grid (I know probably a bit redundant)
typedef struct grid {
char tiles[4][4];
} Grid;
I have tried to make algorithms to move and merge up, down, left and right, but they don't work properly.
void pushLeft(Grid * grid)
{
int i, j, k;
for(i = 0; i < 4; i++) //Row number i
{
for(j = 1; j < 4; j++) //Column number j
{
if(grid->tiles[i][j] != ' ') //tile is not empty
{
int flag = 1; //flag to prevent merging more than one level at a time
//Starting on column k, push tile as far to the left as possible
for(k = j; k > 0; k--)
{
if(grid->tiles[i][k-1] == ' ') //neighbor tile is empty
{
grid->tiles[i][k-1] = grid->tiles[i][k];
grid->tiles[i][k] = ' ';
}
else if(grid->tiles[i][k-1] == grid->tiles[i][k] && flag) //neighbor equals
{
grid->tiles[i][k-1]++;
grid->tiles[i][k] = ' ';
flag = 0;
}
else //Can't push or merge
{
flag = 1;
break;
}
}
}
} // Done with row
}
}
void pushRight(Grid * grid)
{
int i, j, k;
for(i = 0; i < 4; i++) //Row number i
{
for(j = 2; j >= 0; j--) //Column number j
{
if(grid->tiles[i][j] != ' ') //tile is not empty
{
int flag = 1; //flag to prevent merging more than one level at a time
//Starting on column k, push tile as far to the right as possible
for(k = j; k < 3; k++)
{
if(grid->tiles[i][k+1] == ' ') //neighbor tile is empty
{
grid->tiles[i][k+1] = grid->tiles[i][k];
grid->tiles[i][k] = ' ';
}
else if(grid->tiles[i][k+1] == grid->tiles[i][k] && flag) //neighbor equals
{
grid->tiles[i][k+1]++;
grid->tiles[i][k] = ' ';
flag = 0;
}
else //Can't push or merge
{
flag = 1;
break;
}
}
}
} // Done with row
}
}
void pushUp(Grid * grid)
{
int i, j, k;
for(i = 0; i < 4; i++) //Column number i
{
for(j = 1; j < 4; j++) //Row number j
{
if(grid->tiles[j][i] != ' ') //tile is not empty
{
int flag = 1; //flag to prevent merging more than one level at a time
//Starting on row k, push tile as far upwards as possible
for(k = j; k > 0; k--)
{
if(grid->tiles[k-1][i] == ' ') //neighbor tile is empty
{
grid->tiles[k-1][i] = grid->tiles[i][k];
grid->tiles[k][i] = ' ';
}
else if(grid->tiles[k-1][i] == grid->tiles[i][k] && flag) //neighbor equals
{
grid->tiles[k-1][i]++;
grid->tiles[k][i] = ' ';
flag = 0;
}
else //Can't push or merge
{
flag = 1;
break;
}
}
}
} // Done with column
}
}
void pushDown(Grid * grid)
{
int i, j, k;
for(i = 0; i < 4; i++) //Column number i
{
for(j = 2; j >= 0; j--) //Row number j
{
if(grid->tiles[j][i] != ' ') //tile is not empty
{
int flag = 1; //flag to prevent merging more than one level at a time
//Starting on row k, push tile as far down as possible
for(k = j; k < 3; k++)
{
if(grid->tiles[k+1][i] == ' ') //neighbor tile is empty
{
grid->tiles[k+1][i] = grid->tiles[i][k];
grid->tiles[k][i] = ' ';
}
else if(grid->tiles[k+1][i] == grid->tiles[i][k] && flag) //neighbor equals
{
grid->tiles[k+1][i]++;
grid->tiles[k][i] = ' ';
flag = 0;
}
else //Can't push or merge
{
flag = 1;
break;
}
}
}
} // Done with column
}
}
I tested these algorithms with some hardcoded testdata. The algorithm to push the tiles to the left seems to be working correctly. pushRight almost works, but it merges two levels at the same time, so [B|A|A] merges into [C] but should merge into [B|B].
pushUp seems to be almost always just wiping the entire board with empty tiles (spaces).
pushDows seems to be removing some tiles.
Does anyone see the problem or know a way to do this? I have thought about using recursive algorithms, but I just can't wrap my head around it.
I would personally break the swipe into two steps as the swipe left and swipe right are actually functionally the same regarding tile combination. The only difference is that the remaining tiles are bunched to either the left or the right depending on direction.
Below is a quick algorithm to replace two tiles with the a new one. I scan left->right and replace the left tile with the new tile, zero the right tile and then make sure I exclude this new tile from comparison:
typedef struct grid {
char tiles[4][4];
} Grid;
void eliminateHoriz (Grid* g)
{
int row, col, col2;
for (row=0; row<4; row++)
{
for (col=0; col<4; col++)
{
if (g->tiles[row][col])
{
for (col2=col+1; col2<4; col2++)
{
if (g->tiles[row][col2])
{
if (g->tiles[row][col] == g->tiles[row][col2])
{
g->tiles[row][col++] *= 2;
g->tiles[row][col2] = 0;
}
break;
}
}
}
}
}
}
void showGrid (Grid* g)
{
int row, col;
for (row=0; row<4; row++)
for (col=0; col<4; col++)
printf ("%4d%c",
g->tiles[row][col],
col == 3 ? '\n' : ' ');
printf ("\n");
}
int main()
{
Grid g = {{2,2,4,4,
8,0,8,0,
8,8,8,4,
2,2,2,2}};
showGrid (&g);
eliminateHoriz (&g);
showGrid (&g);
system ("pause");
return 0;
}
Output of this:
2 2 4 4
8 0 8 0
8 8 8 4
2 2 2 2
4 0 8 0
16 0 0 0
16 0 8 4
4 0 4 0
After this a simple compaction step could be made, or output realtime to a second buffer, or which ever. Less duplication.
I only have done the case of pushing the lines to the left, but it the same method for every direction. I took the code of the answer and modify it; take a look:
typedef struct grid {
int tiles[4][4];
} Grid;
/* Functions prototypes */
void pushLeft(Grid* grid);
void showGrid (Grid* g);
void find_great_tile(Grid* grid);
/* Main function */
int main()
{
Grid g = {{4,2,2,8,
2,8,2,2,
16,2,0,2,
128,128,64,64}};
/*
The sequence is:
--> Show the grid
--> PushLeft
--> Find great tile
--> PushLeft
--> Show the grid
*/
printf("\n\n\n\n");
showGrid (&g);
printf("\n\n\n\n");
pushLeft(&g);
showGrid (&g);
printf("\n\n\n\n");
find_great_tile(&g);
showGrid(&g);
printf("\n\n\n\n");
pushLeft(&g);
showGrid(&g);
printf("\n\n\n\n");
return 0;
}
/* Functions definitions */
void pushLeft(Grid* grid){
int row, col, col2;
for (row = 0; row < 4; row++)
{
for (col = 0; col < 4; col++)
{
if (!grid->tiles[row][col])
{
for (col2 = col+1; col2 < 4; col2++)
{
if (grid->tiles[row][col2])
{
/*
if (grid->tiles[row][col] == grid->tiles[row][col2])
{
grid->tiles[row][col++] *= 2;
grid->tiles[row][col2] = 0;
}
break;
*/
grid->tiles[row][col] = grid->tiles[row][col2];
grid->tiles[row][col2] = 0;
break;
}
}
}
}
}
}
void showGrid (Grid* grid){
int row, col;
for(row = 0; row < 4; row++){
fprintf(stdout, "\t\t |");
for(col = 0; col < 4; col++)
{
/*
In case there's any number in the matrix, it will print those numbers, otherwise, it'll print a space (it is the alternative of putting a 0)
*/
if(grid->tiles[row][col])
{
printf("%4d |", grid->tiles[row][col]);
}else
printf("%4c |", ' ');
}
fprintf(stdout, "\n\n");
}
}
void find_great_tile(Grid* grid){
int row, col, col2;
for(row = 0; row < 4; row++)
{
for(col = 0; col < 4; col++)
{
if(grid->tiles[row][col])
{
col2 = col+1;
if(grid->tiles[row][col2])
{
if(grid->tiles[row][col] == grid->tiles[row][col2])
{
grid->tiles[row][col++] *= 2;
grid->tiles[row][col2] = 0;
}
}
}
}
}
}
Output of this:
| 4 | 2 | 2 | 8 |
| 2 | 8 | 2 | 2 |
| 16 | 2 | | 2 |
| 128 | 128 | 64 | 64 |
| 4 | 2 | 2 | 8 |
| 2 | 8 | 2 | 2 |
| 16 | 2 | 2 | |
| 128 | 128 | 64 | 64 |
| 4 | 4 | | 8 |
| 2 | 8 | 4 | |
| 16 | 4 | | |
| 256 | | 128 | |
| 4 | 4 | 8 | |
| 2 | 8 | 4 | |
| 16 | 4 | | |
| 256 | 128 | | |
Of course, you can compress the steps doing:
--> PushLeft
--> FindGreatTile
--> PushLeft
So my task is to produce randomly generate weights and profits for batches of items(for 0/1 knapsack problem). I represented the batches in arrays in batch[]. My problem is that:
rand() is not generating unique random values in the second for loop. Is it because of the nested for loops?
The second for loop assigns values to p[j] and w[j] but as it follows j, at each iteration assigning of values start at j, how can I start it from 0 each time?
The output:
| 231 |25
| 231 |25
| 231 |25
| 231 |25
| 0 | 0
|19 | 4
|19 | 4
|19 | 4
|19 | 4
|19 | 4
main(){
srand(time(NULL));
int i, j, t;
int batch[] = { 4, 5 };
int sizeOfBatch = sizeof(batch) / sizeof(batch[0]);
for (i = 0; i < sizeOfBatch ; i++){
int *p = (int*)calloc(batch[i], sizeof(int));
int *w = (int*)calloc(batch[i], sizeof(int));
for (j = 0; j < batch[i]; j++){
p[j] = rand() % 500;
printf("\n| %d ", p[i]);
w[j] = rand() % 100;
printf("| %d ", w[i]);
}
You are assigning to p[j] (and w[j]) and printing p[i] (and w[i]); your problem is unrelated to srand() or rand().
p[j] = rand() % 500; // assign to p[j]
printf("\n| %d ", p[i]); // print p[i]
w[j] = rand() % 100;
printf("| %d ", w[i]);
In the 2nd loop, everytime the loop starts, j begins at 0
for (j = 0; j < batch[i]; j++) {
// first time through the loop, j is 0
}