PPP2 Chapter 13 Drill

Pages: 12
I've just started on the Chapter 13 Drill. Here are the specifications:

1. Make an 800-by-1000 Simple_window.
2. Put an 8-by-8 grid on the leftmost 800-by-800 part of that window (so that each square is 100 by
100).
3. Make the eight squares on the diagonal starting from the top left corner red (use Rectangle).
4. Find a 200-by-200-pixel image (JPEG or GIF) and place three copies of it on the grid (each
image covering four squares). If you can’t find an image that is exactly 200 by 200, use
set_mask() to pick a 200-by-200 section of a larger image. Don’t obscure the red squares.
5. Add a 100-by-100 image. Have it move around from square to square when you click the “Next”
button. Just put wait_for_button() in a loop with some code that picks a new square for your
image.


I need help with number 2 onwards because I've done number 1 already. I'd like to draw the 8-by-8 grid using the code for the grid that we earlier in the chapter if possible:

1
2
3
4
5
6
7
8
9
10
int x_size = win3.x_max(); // get the size of our window
int y_size = win3.y_max();
int x_grid = 80;
int y_grid = 40;

Lines grid;
for (int x=x_grid; x<x_size; x+=x_grid)
    grid.add(Point{x,0},Point{x,y_size}); // vertical line
for (int y = y_grid; y<y_size; y+=y_grid)
    grid.add(Point{0,y},Point{x_size,y}); // horizontal line 


Because it feels like there might be a clue here as to how I should draw the 8-by-8 grid. As for putting it on the leftmost 800-by-800 part of the window, I think I'd have to set the y-value at 800+win.y_max() and the x-value at 800-win.x-max() (win.x_max() and win.y_max() being the maximum x and y values of the window, or in other words the window's dimensions). Would that be correct? If so, I just need to know what kinds of variables to express them in and do the calculations and I'll draw the grid like that easily. I hope.

The code I have so far is like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Osman Zakir
// 5 / 3 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 13 Drill
// Drill Specifications:
/**
 * 1. Make an 800-by-1000 Simple_window.
 * 2. Put an 8-by-8 grid on the leftmost 800-by-800 part of that window (so that each square is 100 by
 *    100).
 * 3. Make the eight squares on the diagonal starting from the top left corner red (use Rectangle).
 * 4. Find a 200-by-200-pixel image (JPEG or GIF) and place three copies of it on the grid (each
 *    image covering four squares). If you can’t find an image that is exactly 200 by 200, use
 *    set_mask() to pick a 200-by-200 section of a larger image. Don’t obscure the red squares.
 * 5. Add a 100-by-100 image. Have it move around from square to square when you click the “Next”
 *    button. Just put wait_for_button() in a loop with some code that picks a new square for your
 *    image.
 */

#include <iostream>
#include "../../cust_std_lib_facilities.h"
#include "../../Simple_window.h"
#include "../../Graph.h"

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };

	constexpr int win_width = 800, win_height = 1000;

	Simple_window win{ top_left, win_width, win_height, "grid-image drill" };


}


Any help would be greatly appreciated.

Edit: I think I'll need more help with the grid first. This is what I have for the grid right now:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Lines grid;
int x_grid = win_width + win.x_max();
int y_grid = win_height - win.y_max();
for (int x = x_grid; x < win.x_max(); x += x_grid)
{
	grid.add(Point{ x, 0 }, Point{ x, win.y_max() });
}
for (int y = y_grid; y < win.y_max(); y += y_grid)
{
	grid.add(Point{ 0, y }, Point{ win.x_max(), y });
}

grid.set_color(Color::black);
win.attach(grid);


Could someone please help me out here?
Last edited on
I edited the opening post to add something just now. I'm waiting for answer right now.
I am not sure where your problem is. Maybe get a piece of paper and draw the lines and then add the coordinates.
Vertical lines:
1. x1 = 0, y1 = 0, x2 = 0, y2 = height of grid
2. x1 = 100, y1 = 0, x2 = 100, y2 = height of grid

and so on

Maybe you will see the pattern how the values should change inside your loops.

In case you fancy a quick solution have a look here.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const int COL_COUNT = 8;
const int ROW_COUNT = 8;
const int ROW_HEIGHT = 100;
const int COL_WIDTH = 100;
const int GRID_WIDTH = COL_COUNT * COL_WIDTH;
const int GRID_HEIGHT = ROW_HEIGHT * ROW_COUNT;

for (int x = 0; x <= GRID_WIDTH; x += COL_WIDTH) // hor coord
  for (int y = 0; y <= GRID_HEIGHT; y += ROW_HEIGHT)  // ver coord
  {
    // draw a line from (x, 0) to (x, GRID_HEIGHT);
    // draw a line from (0, y), (GRID_WIDTH, y); 
  }
}
There's nothing showing up on the window, for example. Previously, I had it going completely black instead of showing a grid. So there's gotta be something major that wrong.

As for the quick solution: I'll try that. Thanks. The problem is I don't have a pen and paper to use.

How do I have the grid start from the leftmost 800-by-800 part of the window? Right now the grid is covering the whole window. I didn't misunderstand what it's saying, did I (referring to the drill specs)?

Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Osman Zakir
// 5 / 3 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 13 Drill
// Drill Specifications:
/**
 * 1. Make an 800-by-1000 Simple_window.
 * 2. Put an 8-by-8 grid on the leftmost 800-by-800 part of that window (so that each square is 100 by
 *    100).
 * 3. Make the eight squares on the diagonal starting from the top left corner red (use Rectangle).
 * 4. Find a 200-by-200-pixel image (JPEG or GIF) and place three copies of it on the grid (each
 *    image covering four squares). If you can’t find an image that is exactly 200 by 200, use
 *    set_mask() to pick a 200-by-200 section of a larger image. Don’t obscure the red squares.
 * 5. Add a 100-by-100 image. Have it move around from square to square when you click the “Next”
 *    button. Just put wait_for_button() in a loop with some code that picks a new square for your
 *    image.
 */

#include <iostream>
#include "../../cust_std_lib_facilities.h"
#include "../../Simple_window.h"
#include "../../Graph.h"

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };

	constexpr int win_width = 800, win_height = 1000;

	Simple_window win{ top_left, win_width, win_height, "grid-image drill" };

	Lines grid;
	constexpr int col_count = 8;
	constexpr int row_count = 8;
	constexpr int row_height = 100;
	constexpr int col_width = 100;
	constexpr int grid_width = col_count * col_width;
	constexpr int grid_height = row_height * row_count;

	for (int x = 0; x <= grid_width; x += col_width)
	{
		for (int y = 0; y <= grid_height; y += row_height)
		{
			grid.add(Point{ x , 0 }, Point{ x, grid_height });
			grid.add(Point{ 0, y }, Point{ grid_width, y });
		}
	}

	grid.set_color(Color::black);
	win.attach(grid);
	win.wait_for_button();
}


Edit: Never mind. It seems to be correct, it's just that the window is too big vertically to fit on my screen. So I can't see it all.

Edit2: I tried drawing the colored squares, but right now I could only hard code Graph_lib::Rectangle rect{Point{0, 0}, 100, 100}; and am having trouble putting 8 of those diagonally on the window in a for loop. This is the code I have right now:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Vector_ref<Graph_lib::Rectangle> rect_vr;
for (int x = 0; x < rect_vr.size(); x += 100)
{
	for (int y = 0; y < rect_vr.size(); y += 100)
	{
		rect_vr.push_back(Graph_lib::Rectangle{ Point{x, y}, 100, 100 });
	}
}
for (int i = 0; i < rect_vr.size(); ++i)
{
	rect_vr[i].set_color(Color::black);
	rect_vr[i].set_fill_color(Color::red);
	win.attach(rect_vr[i]);
}


How do I get it to put 8 squares diagonally on the window, separated by 100 pixels x and 100 pixels y each time (if that'd be correct)?
Last edited on
You need a simple loop for 8 rectangles.
First 0ne starts at 0,0 top left
Second one starts at 100, 100 top left and so on...

If you want to see a little demo in C# have a look here.
https://www.dropbox.com/sh/6ny7faw6x2nvzgu/AAAzJ6kTxsMwKVzZPSsXzPgVa?dl=0
I'll look at that C# demo after this post. First I have some questions I need to ask.

I understand that I have to loop for 8 rectangles, but is there a way to put them into the Vector_ref and then loop over the filled vector while drawing the rectangles?

Would it be a good idea to put another outer loop in there going from 0 to rect_vr.size() - 1, with the inner x and y loops being used to draw rectangles? What I'm thinking of is having the outer-most loop have the variable i and having it control the whole thing. I just need to know what to iterate until in the x and y loops. It'd be funny if get the answer when I look at that C# demo.

Edit: I'm not sure what to take away from that C# project.
Last edited on
I did it in two steps. First I have this two nested loops to draw the lines. After that I have another loop to draw the rectangles. There might be other or better ways but I found this the easiest way.
Of course the drawing in C# is different, but the most important parts are actually the formulas to calc the coordinates.
OK, but how should I implement the loop for the rectangles? Does it have to go from 0 to 8? And since I want to keep adding 100 to the x- and y-coordinates, where does the incrementing code have to go (if not in the same loop as the one going from 0 to 8)? And do I just need one loop? No nesting? Though it does seem like I have to nest for the x and y values for the rectangles.
Last edited on
Since you need 8 rectangles the easiest way is to loop from 0 to 7, have a look again at the code
1
2
3
4
5
6
for (int r = 0; r < 8; r++)
{
   int x = r * COL_WIDTH;
   int y = r * ROW_HEIGHT;
   g.DrawRectangle(pen, x, y, COL_WIDTH, ROW_HEIGHT);
}


1. iteration x = 0 , y =0
2. iteration x =100, y = 100
3. iteration x =200, y = 200

and so on
Right now I have it like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Osman Zakir
// 5 / 3 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 13 Drill
// Drill Specifications:
/**
 * 1. Make an 800-by-1000 Simple_window.
 * 2. Put an 8-by-8 grid on the leftmost 800-by-800 part of that window (so that each square is 100 by
 *    100).
 * 3. Make the eight squares on the diagonal starting from the top left corner red (use Rectangle).
 * 4. Find a 200-by-200-pixel image (JPEG or GIF) and place three copies of it on the grid (each
 *    image covering four squares). If you can’t find an image that is exactly 200 by 200, use
 *    set_mask() to pick a 200-by-200 section of a larger image. Don’t obscure the red squares.
 * 5. Add a 100-by-100 image. Have it move around from square to square when you click the “Next”
 *    button. Just put wait_for_button() in a loop with some code that picks a new square for your
 *    image.
 */

#include <iostream>
#include "../../cust_std_lib_facilities.h"
#include "../../Simple_window.h"
#include "../../Graph.h"

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };

	constexpr int win_width = 800, win_height = 1000;

	Simple_window win{ top_left, win_width, win_height, "grid-image drill" };

	Lines grid;
	constexpr int col_count = 8;
	constexpr int row_count = 8;
	constexpr int row_height = 100;
	constexpr int col_width = 100;
	constexpr int grid_width = col_count * col_width;
	constexpr int grid_height = row_height * row_count;

	for (int x = 0; x <= grid_width; x += col_width)
	{
		for (int y = 0; y <= grid_height; y += row_height)
		{
			grid.add(Point{ x , 0 }, Point{ x, grid_height });
			grid.add(Point{ 0, y }, Point{ grid_width, y });
		}
	}

	Vector_ref<Graph_lib::Rectangle> rect_vr;
	for (int i = 0; i < 8; ++i)
	{
		int x = i * col_width;
		int y = i * row_height;
		rect_vr.push_back(Graph_lib::Rectangle{ Point{x, y}, 100, 100 });
	}

	grid.set_color(Color::black);
	win.attach(grid);
	win.wait_for_button();
}


I can't get it to draw the rectangles after this, though. Would it be good to use new to dynamically allocate memory for a new instance of a Rectangle each time (it wouldn't be overwritten, would it?)? And will that work without the need for Vector_ref, so that I can just add points to the Rectangle normally and then color and display it?
I don't see a point in using dynamic memory for the rectangles. I am not sure how you are supposed to draw a rectangle. What does the book say ?
Normally, all I have to do to draw a Rectangle is what I have here on lines 51-54:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Osman Zakir
// 5 / 3 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 13 Drill
// Drill Specifications:
/**
 * 1. Make an 800-by-1000 Simple_window.
 * 2. Put an 8-by-8 grid on the leftmost 800-by-800 part of that window (so that each square is 100 by
 *    100).
 * 3. Make the eight squares on the diagonal starting from the top left corner red (use Rectangle).
 * 4. Find a 200-by-200-pixel image (JPEG or GIF) and place three copies of it on the grid (each
 *    image covering four squares). If you can’t find an image that is exactly 200 by 200, use
 *    set_mask() to pick a 200-by-200 section of a larger image. Don’t obscure the red squares.
 * 5. Add a 100-by-100 image. Have it move around from square to square when you click the “Next”
 *    button. Just put wait_for_button() in a loop with some code that picks a new square for your
 *    image.
 */

#include <iostream>
#include "../../cust_std_lib_facilities.h"
#include "../../Simple_window.h"
#include "../../Graph.h"

int main()
{
	using namespace Graph_lib;

	Point top_left{ 100, 100 };

	constexpr int win_width = 800, win_height = 1000;

	Simple_window win{ top_left, win_width, win_height, "grid-image drill" };

	Lines grid;
	constexpr int col_count = 8;
	constexpr int row_count = 8;
	constexpr int row_height = 100;
	constexpr int col_width = 100;
	constexpr int grid_width = col_count * col_width;
	constexpr int grid_height = row_height * row_count;

	for (int x = 0; x <= grid_width; x += col_width)
	{
		for (int y = 0; y <= grid_height; y += row_height)
		{
			grid.add(Point{ x, 0 }, Point{ x, grid_height });
			grid.add(Point{ 0, y }, Point{ grid_width, y });
		}
	}

	Graph_lib::Rectangle rect{ Point{0, 0}, 100, 100 };
	rect.set_color(Color::black);
	rect.set_fill_color(Color::red);
	win.attach(rect);

	grid.set_color(Color::black);
	win.attach(grid);
	win.wait_for_button();
}


But like this, I'll have to hard-code all 8 Rectangle which would be bad design and is really something one should use a loop for.
Last edited on
You can do it like I did on my demo. Instead of drawing it you create it and add it to the win.
1
2
3
4
5
6
7
  for (int r = 0; r < 8; r++)
  {
     int x = r * COL_WIDTH;
     int y = r * ROW_HEIGHT;
     // create rect with x, y, COL_WIDTH, ROW_HEIGHT) and add to win;
  }
That's exactly what I'm doing in the above code, though. I'm not even sure if draw_lines() works. But using the new operator worked perfectly with Graph_lib::Vector_ref, though. The book also shows it like that:
1
2
3
4
5
6
7
8
Vector_ref<Rectangle> rect;

Rectangle x {Point{100,200},Point{200,300}};
rect.push_back(x); // add named

rect.push_back(new Rectangle{Point{50,60},Point{80,90}}); // add unnamed

for (int i=0; i<rect.size(); ++i) rect[i].move(10,10); // use rect 


This is the explanation given in the book for a Graph_lib::Vector_ref:
Naming those 256 squares would not only be tedious, it would be silly. The obvi-
ous “name” of the top left square is its location in the matrix (0,0), and any other
square is similarly identified (“named”) by a coordinate pair (i,j). What we need
for this example is the equivalent of a matrix of objects. We thought of using a
vector<Rectangle> , but that turned out to be not quite flexible enough. For ex-
ample, it can be useful to have a collection of unnamed objects (elements) that are
not all of the same type. We discuss that flexibility issue in §14.3. Here, we’ll just
present our solution: a vector type that can hold named and unnamed objects:


1
2
3
4
5
6
7
8
9
10
11
template<class T> class Vector_ref {
public:
    // . . .
    void push_back(T&); // add a named object
    void push_back(T*); // add an unnamed object

    T& operator[](int i); // subscripting: read and write access
    const T& operator[](int i) const;

    int size() const;
};


With this, it added Rectangles to rect_vr so that using Window::attach successfully displayed the rectangles on the window (well, more like squares, but yeah) when I did this:
1
2
3
4
5
6
7
8
9
10
11
constexpr int rect_width = 100;
constexpr int rect_height = 100;
constexpr int num_rects = 8;
Vector_ref<Graph_lib::Rectangle> rect_vr;
for (int i = 0, x = 0, y = 0; i < num_rects; ++i, x += rect_width, y += rect_height)
{
	rect_vr.push_back(new Graph_lib::Rectangle{ Point{ x, y }, rect_width, rect_height });
	rect_vr[i].set_color(Color::black);
	rect_vr[i].set_fill_color(Color::red);
	win.attach(rect_vr[i]);
}
Okay, I'm almost done with this now. I just need to get the code for getting the 100-by-100 pixel image to move from square to square when the "next" button is pressed correct. Right now, it just moves to the right until reaching win.x_max() and then I can't see it anymore for a while, then it reappears at 8th square at the top of the window, disappears again, then reappears on the same square. That keeps happening after that no matter how many times I click "next".

Here's the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Osman Zakir
// 5 / 3 / 2017
// Bjarne Stroustrup: Programming: Principles and Practice Using C++ 2nd Edition
// Chapter 13 Drill
// Drill Specifications:
/**
 * 1. Make an 800-by-1000 Simple_window.
 * 2. Put an 8-by-8 grid on the leftmost 800-by-800 part of that window (so that each square is 100 by
 *    100).
 * 3. Make the eight squares on the diagonal starting from the top left corner red (use Rectangle).
 * 4. Find a 200-by-200-pixel image (JPEG or GIF) and place three copies of it on the grid (each
 *    image covering four squares). If you can’t find an image that is exactly 200 by 200, use
 *    set_mask() to pick a 200-by-200 section of a larger image. Don’t obscure the red squares.
 * 5. Add a 100-by-100 image. Have it move around from square to square when you click the “Next”
 *    button. Just put wait_for_button() in a loop with some code that picks a new square for your
 *    image.
 */

#include "../../cust_std_lib_facilities.h"
#include "../../Simple_window.h"
#include "../../Graph.h"

int main()
{
	using namespace Graph_lib;

	constexpr int win_x = 100, win_y = 100;
	const Point top_left{ win_x, win_y };
	constexpr int win_width = 800, win_height = 1000;
	Simple_window win{ top_left, win_width, win_height, "grid-image drill" };

	Lines grid;
	constexpr int col_count = 8;
	constexpr int row_count = 8;
	constexpr int row_height = 100;
	constexpr int col_width = 100;
	constexpr int grid_width = col_count * col_width;
	constexpr int grid_height = row_height * row_count;
	for (int x = 0; x < grid_width; x += col_width)
	{
		for (int y = 0; y < grid_height; y += row_height)
		{
			grid.add(Point{ x, 0 }, Point{ x, grid_height });
			grid.add(Point{ 0, y }, Point{ grid_width, y });
		}
	}
	grid.set_color(Color::black);
	win.attach(grid);

	constexpr int rect_width = 100;
	constexpr int rect_height = 100;
	constexpr int num_rects = 8;
	Vector_ref<Graph_lib::Rectangle> rect_vr;
	for (int i = 0, x = 0, y = 0; i < num_rects; ++i, x += rect_width, y += rect_height)
	{
		rect_vr.push_back(new Graph_lib::Rectangle{ Point{ x, y }, rect_width, rect_height });
		rect_vr[i].set_color(Color::black);
		rect_vr[i].set_fill_color(Color::red);
		win.attach(rect_vr[i]);
	}

	Image rock1{ Point{500, 0}, "20051121_Peace_rock_th200.jpg" };
	win.attach(rock1);

	Image rock2{ Point{200, 0}, "20051121_Peace_rock_th200.jpg" };
	win.attach(rock2);

	Image rock3{ Point{200, 500}, "20051121_Peace_rock_th200.jpg" };
	win.attach(rock3);

	Image ichigo_flying{ Point{0, 0}, "ichigo-flying.gif" };
	win.attach(ichigo_flying);

	for (int i = 0; i < 8; ++i)
	{
		for (int j = 0; j < 8; ++j)
		{
			if (win.wait_for_button() && ichigo_flying.point(0).x != win.x_max())
			{
				ichigo_flying.move(100, 0);
			}
			else if (win.wait_for_button() && ichigo_flying.point(0).x != -win.x_max())
			{
				ichigo_flying.move(-100, 0);
			}
			else if (win.wait_for_button() && ichigo_flying.point(0).y != win.y_max())
			{
				ichigo_flying.move(0, 100);
			}
			else if (win.wait_for_button() && ichigo_flying.point(0).y != -win.y_max())
			{
				ichigo_flying.move(0, -100);
			}
		}
	}

	win.wait_for_button();
}


Should I also put each of the different things into its own function? I think I probably should.

But anyway, yeah, please help (if possible).

I'm sorry for another double post, but I wasn't sure if this would've fit in my previous post.
Last edited on
I would use two variables, one for current col, and one for current row.
When the button is clicked inc current col, if current col is maxcol set current col to 0 and inc current row. if current row is max row set current row to 0. Move your image to current row and current rol.
Hope it makes sense. If not have a look at my new demo.
https://www.dropbox.com/s/p4m8vid60an9dzd/GridDemo%202.zip?dl=0
I want to move it to the right first, such that it'll go down one and start going left after reaching the end of the first row. Though if there's a way to easily move it back to point 100, 200 after it reaches the end of the first row, then 100, 300, and so on, that would also be great.

Edit: It's not working right now with what I currently have:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int current_row = 0, current_col = 0;
while (current_row != win.x_max() && current_col != win.y_max())
{
	if (win.wait_for_button())
	{
		if (current_row != win.x_max())
		{
			current_row += 100;
			ichigo_flying.move(current_row, current_col);
			if (current_row == win.x_max())
			{
				current_row = 0;
			}
		}
		else if (current_col != win.y_max())
		{
			current_col += 100;
			ichigo_flying.move(current_row, current_col);
			if (current_col == win.y_max())
			{
				current_col = 0;
			}
		}
		ichigo_flying.move(current_row, current_col);
	}
}
Last edited on
if (current_row == win.x_max())
You need to check rows for win.y_max() and cols for win.x_max()
Then is this also incorrect?
ichigo_flying.move(current_row, current_col);

And it also skips squares and then disappears off of the edge of the window, at which point I can't see it anymore no matter how many times I click the "Next" button.
Last edited on
The edges can be a bit tricky. Look how I checked them in my demo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void btnNext_Click(object sender, EventArgs e)
{
  mCurrentCol++;
  if (mCurrentCol > COL_COUNT - 1) // right edge
  {
    mCurrentCol = 0; // move to beginning
    mCurrentRow++; // next row
    if (mCurrentRow > ROW_COUNT - 1) // bottom row
      mCurrentRow = 0; // // move to beginning
  }
  // set pos of image
  pictureBox1.Top = mCurrentRow * ROW_HEIGHT;
  pictureBox1.Left = mCurrentCol* COL_WIDTH;
}
}
Pages: 12