Text adventure game--randomly connecting rooms together - C - c

I'm trying to create a text adventure game that 7 rooms, with the information saved in files. This question IS similar to Connect Rooms Randomly in Adventure Game however the answer didn't exactly help me. I've gone about my program in a different way than that OP so I'm not sure how to use that answer to help me.
The idea is you have 7 rooms, named say A, B, C, D, E, F, and G. After the rooms are created, I need to randomly connect them to each other. Each room needs between 3 and 6 random connections. If room A is connected to B, C, and D, each of those rooms should be connected to A. This information is then saved to a file which is read later.
The code I have for this section so far is:
char *connections[7];
int j = 0;
int randomRoom;
for (j = 0; j <= randConnections; j++) {
randomRoom = rand() % 10;
if (randomRoom == randName) {
randomRoom = rand() % 10;
} else {
connections[j] = names[randomRoom];
}
randConnections is a random int between 3 and 6, defined earlier in the code. names is a string array that holds the names of the rooms, also defined earlier in my program.
I am pretty new to C (I'm mostly experienced with Java) so I can't figure it out. I should mention, this is all in one function defined as:
void createRooms(FILE *fp)
I know there are probably more efficient ways to do this, but at this point I'm just trying to get the code working and deal with efficiency later.
I've done a ton of googling and am honestly beating my head against the wall right now. Any help would be greatly appreciated. If there's any more code I should post or any other information let me know.

C-style strings can get a bit confusing. A "string" in pure C is a char array. Arrays in C are strongly related to pointers. In fact, instead of defining
char myCString[6] = "hello";
You could define
char * myCString = "hello";
In fact, in the first case, myCString used alone will just return a pointer to the first element. The [] operator is just a convenient dereference and increment operator. So &(myCString+1) becomes myCString[1]
So long story short, your "string" array in C is really an array of char* - pointers to the first element of an array of characters
You're trying to assign this to a single character, which doesn't make logical sense. If you mean for the connections to truly be strings, do like kcraigie says.
Here's some backup I found, I'm afraid there are more nuances and I'm not an expert, but that's the gist - https://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays#Pointers_and_Arrays
This may seem absurd coming from java - that's C for ya. C++'s standard library includes a string construct like what you'd be familiar with. It's a class that wraps a "raw" C array and controls access to it and manages it like Java and C# strings. Modern C++ best practices try to stay away from the raw arrays. You'll also notice that nothing stops you from calling MyCString[4000], which is just going to grab a piece of memory from the middle of nowhere and do heaven knows what. There is no bounds checking on raw arrays in C. Be careful!

Related

Theory of arrays in Z3: (1) model is difficult to understand, (2) do not know how to implement functions and (3) difference with sequences

Following to the question published in How expressive can we be with arrays in Z3(Py)? An example, I expressed the following formula in Z3Py:
Exists i::Integer s.t. (0<=i<|arr|) & (avg(arr)+t<arr[i])
This means: whether there is a position i::0<i<|arr| in the array whose value a[i] is greater than the average of the array avg(arr) plus a given threshold t.
The solution in Z3Py:
t = Int('t')
avg_arr = Int('avg_arr')
len_arr = Int('len_arr')
arr = Array('arr', IntSort(), IntSort())
phi_1 = And(0 <= i, i< len_arr)
phi_2 = (t+avg_arr<arr[i])
phi = Exists(i, And(phi_1, phi_2))
s = Solver()
s.add(phi)
print(s.check())
print(s.model())
Note that, (1) the formula is satisfiable and (2) each time I execute it, I get a different model. For instance, I just got: [avg_a = 0, t = 7718, len_arr = 1, arr = K(Int, 7719)].
I have three questions now:
What does arr = K(Int, 7719)] mean? Does this mean the array contains one Int element with value 7719? In that case, what does the K mean?
Of course, this implementation is wrong in the sense that the average and length values are independent from the array itself. How can I implement simple avg and len functions?
Where is the i index in the model given by the solver?
Also, in which sense would this implementation be different using sequences instead of arrays?
(1) arr = K(Int, 7719) means that it's a constant array. That is, at every location it has the value 7719. Note that this is truly "at every location," i.e., at every integer value. There's no "size" of the array in SMTLib parlance. For that, use sequences.
(2) Indeed, your average/length etc are not related at all to the array. There are ways of modeling this using quantifiers, but I'd recommend staying away from that. They are brittle, hard to code and maintain, and furthermore any interesting theorem you want to prove will get an unknown as answer.
(3) The i you declared and the i you used as the existential is completely independent of each other. (Latter is just a trick so z3 can recognize it as a value.) But I guess you removed that now.
The proper way to model such problems is using sequences. (Although, you shouldn't expect much proof performance there either.) Start here: https://microsoft.github.io/z3guide/docs/theories/Sequences/ and see how much you can push it through. Functions like avg will need a recursive definition most likely, for that you can use RecAddDefinition, for an example see: https://stackoverflow.com/a/68457868/936310
Stack-overflow works the best when you try to code these yourself and ask very specific questions about how to proceed, as opposed to overarching questions. (But you already knew that!) Best of luck..

No double picks in image Array Processing 3.0

i've been trying to make a program that takes (for example) 3 cards at random.
But i don't want my program to grab the same card twice, so that means it can't have duplicates, but i don't know how to do this with a image Array.
String[] card = {
"Aclubs.png",
"2clubs.png",
"3clubs.png",
};
PImage[] cards = new PImage [card.length];
void setup() {
size(1000,1000);
randomCards();
drawCards();
}
int randomCards() {
int i = (round(random(0,2)));
cards[i] = loadImage(card[i]);
return i;
}
void drawCards() {
for (int g = 0; g < 12000; g = g+round((displayWidth * 0.9))/12) {
image(cards[randomCards()], 25+g, 50);
}
}
Instead of using an array, use an ArrayList. Then remove the cards you use. Here's a small example:
ArrayList<String> things = new ArrayList<String>();
things.add("cat");
things.add("dog");
things.add("lizard");
while (!things.isEmpty()) {
int index = int(random(things.size()));
String thing = things.remove(index);
println(thing);
}
Of course, this isn't the only way to do it. You could use a Java Set, or you could use a data structure that holds what you've already picked, or you could store all of the options in a data structure, then shuffle it, then just chose from an index that you increment. Or you could use one of the array functions in the reference to do it.
It's hard to answer general "how do I do this" type questions. Stack Overflow is designed for more specific "I tried X, expected Y, but got Z instead" type questions. So you really should get into the habit of trying things out first. Ask yourself how you would do this in real life, then look at the reference to see if there are any classes or functions that would help with that. Break your problem down into smaller pieces. Write down how you would do this in real life, in English. Pretend you're handing those instructions to a friend. Could they follow your instructions to accomplish the goal? When you have those instructions written out, that's an algorithm that you can start thinking about implementing in code. Staring at code you've already written won't get you very far. Then when you do get stuck, you can ask a more specific question, and it'll be a lot easier to help you.

I am not able to create arrays in Nes-C language. any suggestions ?

Can anyone tell me how to create arrays in nes-c. Also i would like to print them. I just saw on google that this is a way but its giving me errors.
uint8_t i;*
uint8_t in[16] =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
A bit late to the party, but maybe it's still useful to answer this.
Creating an array
Arrays in nesC are defined the same way as in normal C language, since nesC is simply an extension of C:
type arrayName [ arraySize ];
I use tutorialspoint for concise tutorials on C, but you can find explanations on a multitude of websites. In your case I would define the array like this:
uint8_t in[16];
Initializing the array with zeroes is best done with the command memset:
memset(in, 0, sizeof(in));
Why? It's clean code, works efficiently, and doesn't need adjusting when you decide to increase the size of the array.
Printing an array
For this I'll refer you to the TinyOS Printf Library tutorial, this explains how you print stuff to the console in TinyOS. I assume you're working with this since you're asking a nesC question.
Printing an array can be done through a simple for-loop.
for (i = 0; i < sizeof(in); ++i) {
printf("%u", in[i]);
}
printfflush();
Good luck!

Need suggestion on Code conversion to Matlab_extension 2

This is an extension of the previously asked question: link. In a short, I am trying to convert a C program into Matlab and looking for your suggestion to improve the code as the code is not giving the correct output. Did I convert xor the best way possible?
C Code:
void rc4(char *key, char *data){
://Other parts of the program
:
:
i = j = 0;
int k;
for (k=0;k<strlen(data);k++){
:
:
has[k] = data[k]^S[(S[i]+S[j]) %256];
}
int main()
{
char key[] = "Key";
char sdata[] = "Data";
rc4(key,sdata);
}
Matlab code:
function has = rc4(key, data)
://Other parts of the program
:
:
i=0; j=0;
for k=0:length(data)-1
:
:
out(k+1) = S(mod(S(i+1)+S(j+1), 256)+1);
v(k+1)=double(data(k+1))-48;
C = bitxor(v,out);
data_show =dec2hex(C);
has = data_show;
end
It looks like you're doing bitwise XOR on 64-bit doubles. [Edit: or not, seems I forgot bitxor() will do an implicit conversion to integer - still, an implicit conversion may not always do what you expect, so my point remains, plus it's far more efficient to store 8-bit integer data in the appropriate type rather than double]
To replicate the C code, if key, data, out and S are not already the correct type you can either convert them explicitly - with e.g. key = int8(key) - or if they're being read from a file even better to use the precision argument to fread() to create them as the correct type in the first place. If this is in fact already happening in the not-shown code then you simply need to remove the conversion to double and let v be int8 as well.
Second, k is being used incorrectly - Matlab arrays are 1-indexed so either k needs to loop over 1:length(data) or (if the zero-based value of k is used as i and j are) then you need to index data by k+1.
(side note: who is x and where did he come from?)
Third, you appear to be constructing v as an array the same size of data - if this is correct then you should take the bitxor() and following lines outside the loop. Since they work on entire arrays you're needlessly repeating this every iteration instead of doing it just once at the end when the arrays are full.
As a general aside, since converting C code to Matlab code can sometimes be tricky (and converting C code to efficient Matlab code very much more so), if it's purely a case of wanting to use some existing non-trivial C code from within Matlab then it's often far easier to just wrap it in a MEX function. Of course if it's more of a programming exercise or way to explore the algorithm, then the pain of converting it, trying to vectorise it well, etc. is worthwhile and, dare I say it, (eventually) fun.

Fortran Array to C array. Stupid macro tricks wanted

I have this 'simplified' fortran code
real B(100, 200)
real A(100,200)
... initialize B array code.
do I = 1, 100
do J = 1, 200
A(J,I) = B(J,I)
end do
end do
One of the programming gurus warned me, that fortran accesses data efficiently in column order, while c accesses data efficiently in row order. He suggested that I take a good hard look at the code, and be prepared to switch loops around to maintain the speed of the old program.
Being the lazy programmer that I am, and recognizing the days of effort involved, and the mistakes I am likely to make, I started wondering if there might a #define technique that would let me convert this code safely, and easily.
Do you have any suggestions?
In C, multi-dimensional arrays work like this:
#define array_length(a) (sizeof(a)/sizeof((a)[0]))
float a[100][200];
a[x][y] == ((float *)a)[array_length(a[0])*x + y];
In other words, they're really flat arrays and [][] is just syntactic sugar.
Suppose you do this:
#define at(a, i, j) ((typeof(**(a)) *)a)[(i) + array_length((a)[0])*(j)]
float a[100][200];
float b[100][200];
for (i = 0; i < 100; i++)
for (j = 0; j < 200; j++)
at(a, j, i) = at(b, j, i);
You're walking sequentially through memory, and pretending that a and b are actually laid out in column-major order. It's kind of horrible in that a[x][y] != at(a, x, y) != a[y][x], but as long as you remember that it's tricked out like this, you'll be fine.
Edit
Man, I feel dumb. The intention of this definition is to make at(a, x, y) == at[y][x], and it does. So the much simpler and easier to understand
#define at(a, i, j) (a)[j][i]
would be better that what I suggested above.
Are you sure your FORTRAN guys did things right?
The code snippet you originally posted is already accessing the arrays in row-major order (which is 'inefficient' for FORTRAN, 'efficient' for C).
As illustrated by the snippet of code and as mentioned in your question, getting this 'correct' can be error prone. Worry about getting the FORTRAN code ported to C first without worrying about details like this. When the port is working - then you can worry about changing column-order accesses to row-order accesses (if it even really matters after the port is working).
One of my first programming jobs out of college was to fix a long-running C app that had been ported from FORTRAN. The arrays were much larger than yours and it was taking something around 27 hours per run. After fixing it, they ran in about 2.5 hours... pretty sweet!
(OK, it really wasn't assigned, but I was curious and found a big problem with their code. Some of the old timers didn't like me much despite this fix.)
It would seem that the same issue is found here.
real B(100, 200)
real A(100,200)
... initialize B array code.
do I = 1, 100
do J = 1, 200
A(I,J) = B(I,J)
end do
end do
Your looping (to be good FORTRAN) would be:
real B(100, 200)
real A(100,200)
... initialize B array code.
do J = 1, 200
do I = 1, 100
A(I,J) = B(I,J)
end do
end do
Otherwise you are marching through the arrays in row-major, which could be highly inefficient.
At least I believe that's how it would be in FORTRAN - it's been a long time.
Saw you updated the code...
Now, you'd want to swap the loop control variables so that you iterate on the rows and then inside that iterate on the columns if you are converting to C.

Resources