[QUOTE=Tommyx50;46544284]Make a 3d array (where the first 2 dimensions are x and y, and the third being a list of points) and then figure out in what part of the array a point should be in simply by doing:
[code]
arrayX = Math.floor(point.x / gridCellSize);
arrayY = Math.floor(point.y / gridCellSize);
grid[arrayX][arrayY].add(pointID)
[/code]
The third dimension should probably be a linked list, due to the dynamically sized nature of it, while the first 2 dimensions can be a static array due to the fixed size of your game world.[/QUOTE]
That helps, and I'm almost ready to make the class, but how would I get gridCellSize? Say I wanted to divide up my map into 32 squares. I know this is probably a [I]really[/I] dumb question.
[QUOTE=bean_xp;46549186]A little late now but incase you get stuck with something like this again, I recommend checking getting an opengl debugger that lets you capture a frame and inspect states. If you're using an AMD chip I recommend GpuPerfStudio, but nvidia offer equivalent software too.[/QUOTE]
Ya, I was using gDEBugger which is how I found out about what other states to disable. I'm just not experienced with opengl so I didn't think about shaders. Probably would have helped if gDEBugger actually displayed state changes when stepping. Although GL_CURRENT_PROGRAM doesn't sound like shaders.
Edit:
Actually I guess I didn't look at the output hard enough. I could have seen that program is shaders.
[t]http://i.imgur.com/HercvnV.png[/t]
Although outside help when bashing your head at a problem really helps.
[QUOTE=NixNax123;46549233]That helps, and I'm almost ready to make the class, but how would I get gridCellSize? Say I wanted to divide up my map into 32 squares. I know this is probably a [I]really[/I] dumb question.[/QUOTE]
gridCellSize = mapSize / 32
(assuming a square map with square grids)
[QUOTE=Tommyx50;46551559]gridCellSize = mapSize / 32
(assuming a square map with square grids)[/QUOTE]
Alright, thanks!
So I'm totally stuck making this class. I don't understand how to implement it or use it. The implementation of a quadtree makes sense to me, but why can't I just implement a regular grid?
I'm looking into networking using winsock, but it doesn't really have an easy way to send anything else than a char buffer.
Right now I'm thinking of doing something like this to encode integers into a char buffer that you can send through the internet.
[code]
void EncodeInt(char *buffer, int a_int)
{
buffer[0] = (a_int & (0xFF000000)) >> 24;
buffer[1] = (a_int & (0x00FF0000)) >> 16;
buffer[2] = (a_int & (0x0000FF00)) >> 8;
buffer[3] = a_int & (0x000000FF);
}
void DecodeInt(char *buffer, int &a_int)
{
int a = (buffer[0] & 0xFF);
int b = (buffer[1] & 0xFF);
int c = (buffer[2] & 0xFF);
int d = (buffer[3] & 0xFF);
a_int = (a << 24) + (b << 16) + (c << 8) + d;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a = 0x66778899;
char buffer[4];
EncodeInt(buffer, a);
int b = 0;
DecodeInt(buffer, b);
return 0;
}
[/code]
This works, but I was wondering if there are any better ways of doing this?
[QUOTE=FalconKrunch;46555198]I'm looking into networking using winsock, but it doesn't really have an easy way to send anything else than a char buffer.
Right now I'm thinking of doing something like this to encode integers into a char buffer that you can send through the internet.
[code]
void EncodeInt(char *buffer, int a_int)
{
buffer[0] = (a_int & (0xFF000000)) >> 24;
buffer[1] = (a_int & (0x00FF0000)) >> 16;
buffer[2] = (a_int & (0x0000FF00)) >> 8;
buffer[3] = a_int & (0x000000FF);
}
void DecodeInt(char *buffer, int &a_int)
{
int a = (buffer[0] & 0xFF);
int b = (buffer[1] & 0xFF);
int c = (buffer[2] & 0xFF);
int d = (buffer[3] & 0xFF);
a_int = (a << 24) + (b << 16) + (c << 8) + d;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a = 0x66778899;
char buffer[4];
EncodeInt(buffer, a);
int b = 0;
DecodeInt(buffer, b);
return 0;
}
[/code]
This works, but I was wondering if there are any better ways of doing this?[/QUOTE]
If you're sending binary data which isn't packed in any way for sending, ntohs et al are useful:
[cpp]void EncodeUint16(char *buf, uint16_t i)
{
i = htons(i);
memcpy(buf, &i, sizeof(uint16_t));
}
uint16_t DecodeUint16(const char *buf)
{
uint16_t i;
memcpy(&i, buf, sizeof(uint16_t));
return ntohs(i);
}[/cpp]
Low-level networking often uses C structs for defining the memory layout, and then conversion functions to convert between network and host byte order.
[cpp]#pragma pack(push, 2)
struct net_packet {
uint32_t magic;
uint16_t index;
};
#pragma pack(pop)
void encode_packet(struct net_packet *p)
{
p->magic = htonl(p->magic);
p->index = htons(p->index);
}
void decode_packet(struct net_packet *p)
{
p->magic = ntohl(p->magic);
p->index = ntohs(p->index);
}
void send_packet(SOCKET s, const struct net_packet *p)
{
send(s, (const char*)p, sizeof(struct net_packet), 0);
}[/cpp]
If you're defining a lot of different structs and you need to serialize/deserialize them all, and possibly handle support with older communication formats, you should be using something like Apache Thrift.
I feel stupid for forgetting about memcpy...
Thanks.
[QUOTE=NixNax123;46552034]Alright, thanks!
So I'm totally stuck making this class. I don't understand how to implement it or use it. The implementation of a quadtree makes sense to me, but why can't I just implement a regular grid?[/QUOTE]
It's essentially the same concept as having a quadtree which never subdivides. What exactly is the issue? What code do you have so far, for both your quadtree and grid?
[QUOTE=Tommyx50;46556990]It's essentially the same concept as having a quadtree which never subdivides. What exactly is the issue? What code do you have so far, for both your quadtree and grid?[/QUOTE]
Here was my quadtree class, renamed to be a partitioned grid. As you can see, I've started on trying to implement a grid, but nothing other than a few variables.
[code]public class PartionedGrid {
// how many elements can be stored in this quad tree node
private final int QT_NODE_CAPACITY = 4;
// axis-aligned bounding box stored as a center with half-dimensions
private final AABB boundary;
// size of each cell in the grid
private final float gridCellSize;
// points in this quad tree node
private final List<Vector2f> points = new ArrayList<>(QT_NODE_CAPACITY);
// children
private PartionedGrid northWest;
private PartionedGrid northEast;
private PartionedGrid southWest;
private PartionedGrid southEast;
/**
* Constructs a QuadTree with the specified boundary.
*
* @param boundary the boundary of the QuadTree.
*/
public PartionedGrid(AABB boundary) {
this.boundary = boundary;
gridCellSize = (boundary.getRadius().x * 2) / 32;
}
/**
* Inserts a point into this PartionedGrid.
*
* @param p the point to be inserted.
* @return true if the point was inserted, false if not.
*/
public boolean insert(Vector2f p) {
// ignore objects that do not belong in this quad tree
if (!boundary.containsPoint(p)) {
return false;
}
// if there is space in this quad tree, add the object here
if (points.size() < QT_NODE_CAPACITY) {
points.add(p);
return true;
}
// if there is no space, subdivide and add the point to whichever node
// will accept it
if (northWest == null) {
subDivide();
}
if (northWest.insert(p)) {
return true;
}
if (northEast.insert(p)) {
return true;
}
if (southWest.insert(p)) {
return true;
}
if (southEast.insert(p)) {
return true;
}
return false;
}
/**
* creates four children that fully divide this PartionedGrid.
*/
public void subDivide() {
float cX = boundary.getCenter().x;
float cY = boundary.getCenter().y;
float rX = boundary.getRadius().x;
float rY = boundary.getRadius().y;
Vector2f quarterR = Vector2f.div(boundary.getRadius(), 4);
AABB topLeft = new AABB(new Vector2f(cX - rX, cY - rY),
quarterR);
AABB topRight = new AABB(new Vector2f(cX + rX, cY - rY),
quarterR);
AABB bottomLeft = new AABB(new Vector2f(cX - rX, cY + rY),
quarterR);
AABB bottomRight = new AABB(new Vector2f(cX + rX, cY + rY),
quarterR);
northWest = new PartionedGrid(topLeft);
northEast = new PartionedGrid(topRight);
southWest = new PartionedGrid(bottomLeft);
southEast = new PartionedGrid(bottomRight);
}
/**
* Returns in the points in the specified range of this PartionedGrid.
* @param range the bounding box to be checked.
* @return a List of points within the specified range.
*/
public List<Vector2f> queryRange(AABB range) {
// prepare result list
List<Vector2f> pointsInRange = new ArrayList<>();
// abort if range does not intersect this quad
if (!boundary.intersectsAABB(range)) {
return pointsInRange; // empty list
}
// check objects at this quad level
for (Vector2f p : points) {
if (range.containsPoint(p)) {
pointsInRange.add(p);
}
}
// terminate if no children
if (northWest == null) {
return pointsInRange;
}
// otherwise, add points from the children
pointsInRange.addAll(northWest.queryRange(range));
pointsInRange.addAll(northEast.queryRange(range));
pointsInRange.addAll(southWest.queryRange(range));
pointsInRange.addAll(southEast.queryRange(range));
return pointsInRange;
}
}[/code]
I understand this completely, because the functions spell everything out for you, and I would have to make a queryEntitiesRange to get objects to only 'see' objects near them, but I don't understand how I would make a grid class.
I currently have a problem with AVR assembly. I want to send a constant as a parameter to a macro that I wrote, but I don't know how to go about doing that. The macro looks like this:
.MACRO LCD_POS
LDI R24 @0
RCALL lcd_write_instr
.ENDMACRO
What is bad about this code? And how could I improve it
[code] public String readFile(){
File f = null;
FileReader fr = null;
StringBuffer content = null;
try{
f = new File("c:/samplefile.txt");
fr = new FileReader(f);
int c;
while((c = fr.read()) != -1){
if(content == null){
content = new StringBuffer();
}
content.append((char)c);
}
fr.close();
}
catch (Exception e) {
throw new RuntimeException("An error occured reading your file");
}
return content.toString();
}[/code]
[QUOTE=Over-Run;46563526]What is bad about this code? And how could I improve it
[code] public String readFile(){
File f = null;
FileReader fr = null;
StringBuffer content = null;
try{
f = new File("c:/samplefile.txt");
fr = new FileReader(f);
int c;
while((c = fr.read()) != -1){
if(content == null){
content = new StringBuffer();
}
content.append((char)c);
}
fr.close();
}
catch (Exception e) {
throw new RuntimeException("An error occured reading your file");
}
return content.toString();
}[/code][/QUOTE]
Not a java expert (looks like java), but i would do this.
[code]
public String readFile() {
FileReader fr = new FileReader(new File("c:/samplefile.txt"));
StringBuffer content = new StringBuffer();
int c;
while((c = fr.read()) != -1) {
content.append((char)c);
}
fr.close();
return content.toString();
}
[/code]
Not sure if the try statement is really necessary, and even if it was, you could wrap everything inside it, like this.
[code]
public String readFile() {
try {
FileReader fr = new FileReader(new File("c:/samplefile.txt"));
StringBuffer content = new StringBuffer();
int c;
while((c = fr.read()) != -1) {
content.append((char)c);
}
fr.close();
return content.toString();
} catch (Exception e) {
throw new RuntimeException("An error occured reading your file");
}
}
[/code]
It is Java.
Just wondering why do you think you need to make those changes?
Basically it is for a job coding test I have to find bugs and errors and bad code in general for this bit of code and then improve it.
From looking at it I think:
Naming conventions are bad, doesn't close file reader if exception is thrown, I think the file location should be a global variable to easily change it, it should be an IOException and not an Exception, doesn't specify the charset.
Am I missing anything or on the right track with it?
Wouldn't set the file name a global variable, but a parameter to the function. I agree with the rest.
I changed the method to this. Is this better code do you think?
[code] public String readFileFixed(String fileName){
StringBuffer fileText = new StringBuffer();
String currentLine = null;
try {
FileInputStream fileInputStream = new FileInputStream(fileName);
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(fileInputStream));
while((currentLine = bufferedReader.readLine()) != null){
fileText.append(currentLine + "\n");
}
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return fileText.toString();
}[/code]
-snip
got it figured out
[QUOTE=Over-Run;46563990]I changed the method to this. Is this better code do you think?
[code] public String readFileFixed(String fileName){
StringBuffer fileText = new StringBuffer();
String currentLine = null;
try {
FileInputStream fileInputStream = new FileInputStream(fileName);
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(fileInputStream));
while((currentLine = bufferedReader.readLine()) != null){
fileText.append(currentLine + "\n");
}
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return fileText.toString();
}[/code][/QUOTE]
You're getting there (and using a string buffer, which is good), but here's some tips:
If an exception was to be thrown in your method, your file streams will not be closed - leading to leaks the longer the application is running. You could do this yourself in the catch/finally block, but Java has a [url=https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html]try-with-resources[/url] statement, which means it'll handle opening and closing the streams for you (either by it completing successfully or an error). For instance:
[code]
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName))))
{
//load our file
}
catch (IOException ioException)
{
//do something here, but we don't need to close resources
}
[/code]
Secondly, you shouldn't be manually specifying the new line character yourself. This could lead to further problems down the line if you run it on different platforms and your new lines aren't working. You should be using [url=https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#lineSeparator%28%29]System.lineSeparator()[/url] instead.
[code]
fileText.append(currentLine + System.lineSeparator());
[/code]
I hope this is useful.
Can anyone check my homework? I'm using a few things we haven't learned in class yet that I've known for a while. The homework says:
[quote]
Write a program that checks the mileage of a car, assigns it a category based on the mileage, and checks the gas emissions required to pass each category of car for each category of gases. The constraints are:
Category 1 - <= 50,000 miles
Category 2 - > 50,000 miles
Gases:
[code]
Gas Cat1 Cat2
CO 3.4 4.2
HC 0.31 0.39
NO 0.4 0.4
NMHC 0.21 0.31
[/code]
My code is:
[code]
import java.util.Scanner;
public class Gas{
public static void main(String[] args){
//Input phase
Scanner inp = new Scanner(System.in);
//Checks whether or not a valid value has been input for miles.
boolean completed = false;
//used to access the gases array,
//to check which category of gases
//to compare to
final int CAT_1 = 0;
final int CAT_2 = 1;
//gas array; the elements are:
// category 1 cateogory 2
double[][] gases = { {3.4, 0.31, 0.4, 0.21}, {4.2,0.39, 0.4, 0.31} };
//used to input mileage
double miles;
//constraint phase.
do{
System.out.println("Enter mileage!");
miles = inp.nextDouble();
if(miles <= 0){
System.out.println("Enter a value greater than 0!");
}
else{
//miles are greater than 0
//continue to next step.
completed = true;
}
//check if a value greater than
//0 has been entered.
}while(!completed);
//assigns category.Says:
//if Miles are less than or equal to 50000,
//return CAT_1,
//else, return CAT_2
int category = (miles <= 50000) ? CAT_1 : CAT_2;
//formulation phase.
//go from check to check.
//If any check is returned true
//exit with an error code.
System.out.println("Enter Carbon Monoxide");
if(inp.nextDouble() > gases[category][0]){
System.out.println("Failed Inspection on Carbon Monoxide");
System.exit(1);
}
System.out.println("Enter Hydrocarbons");
if(inp.nextDouble() > gases[category][1]){
System.out.println("Failed Inspection on Hydrocarbons");
System.exit(2);
}
System.out.println("Enter Nitrogen Oxide");
if(inp.nextDouble() > gases[category][2]){
System.out.println("Failed Inspection on Nitrogen Oxide");
System.exit(3);
}
System.out.println("Enter Non-Methane Hydrocarbons");
if(inp.nextDouble() > gases[category][3]){
System.out.println("Failed Inspection on Non-methane Hydrocarbons");
System.exit(4);
}
//all checks returned false
//car has passed
//output phase
System.out.println("\nThe car has passed!\nHappy driving!\nHonk Honk Beep Beep\n");
System.exit(0);
}
}[/code]
I understand if nobody feels like checking code.
I'm actually curious about disposing an object with a long running task in c#. I got a state machine with a long running asynchronously running task which evaluates the next task and performs the actions. If I want to dispose the state machine I will have to stop the task by setting its CancellationToken to Cancel. After that I will have to dispose the CancellationToken itself and the evaluation task as well as some other resources. But here comes the problem: I have to wait for the task to complete before I can dispose it. At the moment I'm just busy waiting for it to complete, but I don't like that way since the task could take some time to end.
Is there any pattern which suits this problem?
[QUOTE=NixNax123;46562113]Here was my quadtree class, renamed to be a partitioned grid. As you can see, I've started on trying to implement a grid, but nothing other than a few variables.
I understand this completely, because the functions spell everything out for you, and I would have to make a queryEntitiesRange to get objects to only 'see' objects near them, but I don't understand how I would make a grid class.[/QUOTE]
You are completely stuck in the mindset of a quadtree. A grid is much less complicated - you shouldn't be thinking about how to overcomplicate a grid to fit your quadtree class, you should be thinking about how to simplify your quadtree class to fit a grid!
Most of the stuff there is fluff. You NEVER subdivide a grid, so you should completely remove all functions which subdivide it or any references to it's children.
There's also things which need changing - for example, you give a max of entities that can be in any grid square before subdivision, but with a grid there is no such limit!
Remove all the excess stuff you don't need anymore which talks about subdivision, and rethink exactly what you are trying to do. It's much simpler than you are trying to make it.
Let's think about it in 1 dimension first, instead of 2d, as hopefully this'll make it easier to think about.
[code]
X_X_X_X__X_X
[/code]
So each X here is a point, and _ is empty space. Our goal is to split the world into cells (or grid squares), and place each X into the appropriate one.
[code]
|X_X_|X_X_|_X_X|
[/code]
So now I've overlaid a grid over our positions. We have 3 cells, and we want to figure out which cell each X is in. How do we do this?:
[code]
0 1 2
|X_X_|X_X_|_X_X|
1 3 5 7 10 12
[/code]
At the top, you can see the cell numbers - 0, 1 and 2. Below, you can see the positions of each X. We want to convert every position into it's corresponding cell number.
How do we do this? Well, it's pretty simple. We just do this:
[code]
cell = math.floor(X.pos / cellSize);
[/code]
When we apply this to our world above, we get:
[code]
0 1 2
|X_X_|X_X_|_X_X|
0 0 1 1 2 2
[/code]
So we can successfully find out which cell each position should be in. Now we just need to store that as a data structure. Because we are working in 1 dimension here, we need a 2d array; one dimension to represent the cell positions, and another to represent their contents:
[code]
-0-1-2-
|X|X|X|
|X|X|X|
[/code]
Every frame, we clear the old data, recalculate what cell every X is in, and put it all into the data structure.
When we get to the stage of doing our collision detection, instead of looping through every game entity and checking against every other, instead we loop through every grid cell and check the collision between every entity in the same cell.
That's the basics - to do this in 2d, we do the same, but with both the x and y positions, and store it in a 3d array instead of a 2d one - 2 dimensions to represent the cells, and 1 more to hold the list of points in each cell.
There is one more slight complexity - this only handles the positions of points, not 2d areas (which your asteroids are). To get around this, we actually put each point in several cells - in 2d, we'd put it into it's own cell and the 8 surrounding ones. Then, as long as our cell size is always qual to or bigger than the maximum size of an object in our game, all the calculations are done correctly.
Alright dude, thank you so much! Here's my edited class:
[code]public class PartionedGrid {
// axis-aligned bounding box stored as a center with half-dimensions
private final AABB boundary;
// size of each cell in the grid
private final float gridCellSize;
// points in this quad tree node
private final List<Vector2f> points = new ArrayList<>();
/**
* Constructs a QuadTree with the specified boundary.
*
* @param boundary the boundary of the QuadTree.
*/
public PartionedGrid(AABB boundary) {
this.boundary = boundary;
gridCellSize = (boundary.getRadius().x * 2) / 32;
}
/**
* Inserts a point into this PartionedGrid.
*
* @param p the point to be inserted.
* @return true if the point was inserted, false if not.
*/
public boolean insert(Vector2f p) {
// insert point into the grid
}
/**
* Returns in the points in the specified range of this PartionedGrid.
* @param range the bounding box to be checked.
* @return a List of points within the specified range.
*/
public List<Vector2f> queryRange(AABB range) {
// prepare result list
List<Vector2f> pointsInRange = new ArrayList<>();
// abort if range does not intersect this quad
if (!boundary.intersectsAABB(range)) {
return pointsInRange; // empty list
}
// check objects at this quad level
for (Vector2f p : points) {
if (range.containsPoint(p)) {
pointsInRange.add(p);
}
}
return pointsInRange;
}
}[/code]
I will have to modify the query function to only return points in the cell. Also, I don't know how to insert a 2d entity. And I know how to make a dynamic array of points, but I'm not sure how to make the grid itself.
[QUOTE=NixNax123;46571504]Alright dude, thank you so much! Here's my edited class:
I will have to modify the query function to only return points in the cell. Also, I don't know how to insert a 2d entity. And I know how to make a dynamic array of points, but I'm not sure how to make the grid itself.[/QUOTE]
I'm not 100 percent how to make the a dynamic grid because of how weird java is, but something static like this should work:
[code]
GameObject[][][] gridCells = new GameObject[numOfGridsX][numOfGrids][15]
[/code]
This would allow 15 GameObjects in each cell, which should be plenty. I'm unsure how to make it dynamic on the Z dimension due to the weirdness of java...
How would you do it with any other language?
[QUOTE=proboardslol;46566876]Can anyone check my homework? I'm using a few things we haven't learned in class yet that I've known for a while. The homework says:
I understand if nobody feels like checking code.[/QUOTE]
Break your code up into multiple methods and then write unit tests
Or just manually test it yourself with all the possible inputs
[editline]25th November 2014[/editline]
[QUOTE=Dyler;46569724]I'm actually curious about disposing an object with a long running task in c#. I got a state machine with a long running asynchronously running task which evaluates the next task and performs the actions. If I want to dispose the state machine I will have to stop the task by setting its CancellationToken to Cancel. After that I will have to dispose the CancellationToken itself and the evaluation task as well as some other resources. But here comes the problem: I have to wait for the task to complete before I can dispose it. At the moment I'm just busy waiting for it to complete, but I don't like that way since the task could take some time to end.
Is there any pattern which suits this problem?[/QUOTE]
Look into wait handles / reset events. You could have a property that is the reset event and do something like
[code]
AutoResetEvent resetEvent = ...;
bool looping = true;
void loop()
{
while(looping)
{
// stuff
}
// done looping
resetEvent.Set();
}
void Dispose()
{
looping = false;
resetEvent.WaitOne(); // blocks the running thread until the event is set
// event has been set so we know the looping method has reached the end
}
[/code]
[editline]25th November 2014[/editline]
[QUOTE=Tommyx50;46572394]I'm not 100 percent how to make the a dynamic grid because of how weird java is, but something static like this should work:
[code]
GameObject[][][] gridCells = new GameObject[numOfGridsX][numOfGrids][15]
[/code]
This would allow 15 GameObjects in each cell, which should be plenty. I'm unsure how to make it dynamic on the Z dimension due to the weirdness of java...[/QUOTE]
[QUOTE=NixNax123;46571504]Alright dude, thank you so much! Here's my edited class:
I will have to modify the query function to only return points in the cell. Also, I don't know how to insert a 2d entity. And I know how to make a dynamic array of points, but I'm not sure how to make the grid itself.[/QUOTE]
What does nixnax mean by "a dynamic array"? Fyi nax that usually means an array who's size is determiend at run time
ie
[code]
int arr[5]; // not dynamic. Also this isn't valid Java, but is valid C++
int i = getSize();
int[] arr2 = new int[i]; // dynamic
[/code]
This matters more for C++:
[code]
int i = 10;
int foo[10]; // valid
int foo3[i]; // invalid
int* foo2 = new int[10]; // valid
int* foo2 = new int[i]; // valid
[/code]
However if you mean an array that can resize or something then that isn't an array. You need something like a list. Java has [URL="https://docs.oracle.com/javase/7/docs/api/java/util/Vector.html"]Vector [/URL]and [URL="https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html"]ArrayList [/URL]and [URL="https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html"]LinkedList[/URL].
[QUOTE=NixNax123;46573684]How would you do it with any other language?[/QUOTE]
In C++, I'd probably typically just use a 1 dimensional array and access it as if it as 2d, and probably use a vector or linked list (depending on how much cache friendlyness plays into it). I'd also store game objects as an int ID instead of using pointers (or in Java, references).
[code]
std::forwards_list<int> *gridCells = new std::forwards_list<int>[rows * columns];
// To access as 2d, use:
gridCells[x * rows + y].push_front(id);
// This example inserts an object into the cell at x, y
[/code]
On further thought, you should probably do the same with Java... :downs:
[editline]25th November 2014[/editline]
[QUOTE=thrawn2787;46573926]What does nixnax mean by "a dynamic array"? Fyi nax that usually means an array who's size is determiend at run time
ie
[code]
int[] arr = new int[5]; // not dynamic
int i = getSize();
int[] arr2 = new int[i]; // dynamic
[/code]
This matters more for C++:
[code]
int i = 10;
int foo[10]; // valid
int foo3[i]; // invalid
int* foo2 = new int[10]; // valid
int* foo2 = new int[i]; // valid
[/code]
However if you mean an array that can resize or something then that isn't an array. You need something like a list. Java has Vectory and [URL="https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html"]ArrayList [/URL]and [URL="https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html"]LinkedList[/URL].[/QUOTE]
He's wanting a 3d array, where the first 2 dimensions are static and the 3rd is dynamically resizeable.
Then he wants a 2d array of a list or something.
[code]
// don't have to use vector, use whatever container you want
Vector<Foo>[][] array = new Vector<Foo>[y][x];
for(int i = 0; i < y; i++)
for(int j = 0; j < x; j++)
array[i][j] = new Vector<Foo>();
// now we can get our vectors and add stuff to them
array[0][0].add(new Foo());
[/code]
[QUOTE=thrawn2787;46573926]Break your code up into multiple methods and then write unit tests
Or just manually test it yourself with all the possible inputs[/QUOTE]
I was gonna do that but figured my teacher is the kind who will deduct points if you don't do it exactly as he wants, so methods outside of main would get me points deducted
I was told by lecturer: "Part B is service oriented application. You can have the application hosted localhost or online. It is up to you."
Basically I need to make an java application that can has login/reg etc..
I am a bit lost about what she means by service oriented application. What is it?
[QUOTE=thrawn2787;46574089]Then he wants a 2d array of a list or something.
[code]
// don't have to use vector, use whatever container you want
Vector<Foo>[][] array = new Vector<Foo>[y][x];
for(int i = 0; i < y; i++)
for(int j = 0; j < x; j++)
array[i][j] = new Vector<Foo>();
// now we can get our vectors and add stuff to them
array[0][0].add(new Foo());
[/code][/QUOTE]
Which is exactly as I've been explaining :eng101:
could anyone help me understand exactly how fscanf_s works in C++? I have this code which works totally as expected here: it opens a file named testfile.txt and reads the first character in the file to decide on whether not to try to read floats that come after it. the textfile looks like this:
[img]http://i.imgur.com/JmJhlKN.png[/img]
and the working code looks like this:
[code]
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <string>
int loadFloats(float *outFloats) //Function to get three floats from a text file and place them in outFloats
{
//Create a file object and get a pointer reference to it
FILE testFile;
FILE * testFilePtr = &testFile;
//Open file in read mode
fopen_s(&testFilePtr, "testfile.txt", "r");
char lineChar[2]; //Create a char array to hold the first letter in the text file + null terminator
fscanf_s(testFilePtr, "%c", &lineChar); //Use fscanf_s to get first character in text file and place in lineChar
if (strcmp(lineChar, "g") == 0) //If first characters in file are g + null terminator, then
{
fscanf_s(testFilePtr, "%f %f %f", outFloats, outFloats + 1, outFloats + 2); //Get first three floats from file, place in outFloats
//fscanf_s(testFilePtr, "%f %f %f", outFloats, outFloats + 1, outFloats + 2); //Get next three floats from file, overwrite outFloats with them
}
else
{
std::cout << lineChar << std::endl; //Print what the lineChar actually was, if not g, and don't try to load floats
std::cout << "Could not load floats" << std::endl;
return 1;
}
return 0;
}
[/code]
this seems to work fine, providing the right output in my main program. HOWEVER, when I uncomment the commented fscanf_s line (the one that's identical to the uncommented one before it), the program seems to think that the lineChar suddenly is [I]not[/I] equal to g, even though the textfile is unchanged - the program outputs lineChar as a blank character and prints the "Could not load floats" error message. I was expecting it to just scan in the next three floats and overwrite the outFloats with them.
what the hell? how could calling fscanf_s at that point in the code change what lineChar is? I'd be so grateful if someone could tell me what I'm doing wrong - I'm pretty much a beginner at C++ and come from a physics background so am probably violating lots of best practices, sorry. I don't technically need to know why this is happening to continue with my project but I feel very uncomfortable at this point since it seems there's something fundamental I don't understand about the function I'm using.
[editline]26th November 2014[/editline]
okay, so I removed the conditional and just did fscanf_s twice. that overwrites the values as expected, but the addition of that line still changes the contents of lineChar. why?
Sorry, you need to Log In to post a reply to this thread.