Retrieving a character at X , Y

It's basically what the title says. I am making a console program and want help. How can I get a character somewhere on the screen? Like, get the char that is at X2, Y3?

I am on Windows. I don't worry if your code is system dependant. Try to simplify it the best you can. I am using Visual C++ 2010.

Thanks.
I'm confused by your question, do you mean you want to print whatever you have stored at the address X2, Y3? I think you have to use a pointer and then cout << the reference to the address. Maybe be more specific about your problem.
I was very spefic...

Here is how it would work. Let's say this is the console:
---------------------



---------------------

Now I print "Hello World!" at the console.

---------------------
Hello World!


---------------------

Now I specify to whatever character is at Y 0, X 6- That would be the "O" from "Hello".
---------------------
Hell*o* World!


---------------------

Understand what I want now?
Last edited on
Are you talking about arrays or strings?

If you're talking about arrays, arrayName[0][4]; is 'o'.

If you're talking about strings, and trying to copy that character, stringName.substr(4, 1); is "o".
Nope, I want to get a char somewhere at the console.
In all likelyhood you shouldn't be trying to do this. Output is not input and you shouldn't use it as such. Trying to retrieve something that has been previously output is more trouble than it's worth.

If you need to keep track of what you output, a better way would be to record what you output before you actually output it.

Why would you need to do such a thing anyway? If you can explain why you need this I should be able to provide some alternative approaches.
you can make a 2D char array:
1
2
3
4
char grid[3][3] = 
{ ' ', ' ', ' '},  //x = 0; y = 0, 1, 2
{ ' ', ' ', ' '},  //x = 1; y = 0, 1, 2
{ ' ', ' ', ' '};  //x = 2; y = 0, 1, 2 

This makes an empty 3x3 grid of spaces, you can make a bigger 10x10 grid if you want.
You can then assign a character to one of the array positions:
 
grid[1][2] = 'o';  //'o' assigned to grid position x = 1, y= 2 

You can then print out the whole array:
1
2
cout<<grid[0][0]<<grid[0][1]<<grid[0][2]<<grid[1][0]<<grid[1][1]<<grid[1][2]
       <<grid[2][0]<<grid[2][1]<<grid[2][2];
In all likelyhood you shouldn't be trying to do this. Output is not input and you shouldn't use it as such. Trying to retrieve something that has been previously output is more trouble than it's worth.

If you need to keep track of what you output, a better way would be to record what you output before you actually output it.

Why would you need to do such a thing anyway? If you can explain why you need this I should be able to provide some alternative approaches.


I am making a roguelike. There is no up-to-date tutorials on that area, so I have to do it using what I know... I am asking that because I want to detect colision with walls. IE: If the player moves left, check if theres a solid tile in -1 X of him.

I will appreciate if you tell me how to do it with alternatives.

@Bacia

Thanks for the idea. I have another question.

I am making a roguelike. It's very OS dependent though.
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
#include <iostream>
#include <windows.h>
#include <conio.h>

using namespace std;

void gotoXY(int x, int y)
{
	 //Initialize the coordinates
	 COORD coord = {x, y};
	 //Set the position
	 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
	 return;
}

void ClearConsole()
{
	 //Get the handle to the current output buffer...
	 HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
	 //This is used to reset the carat/cursor to the top left.
	 COORD coord = {0, 0};
	 //A return value... indicating how many chars were written
	 //   not used but we need to capture this since it will be
	 //   written anyway (passing NULL causes an access violation).
	 DWORD count;
	 //This is a structure containing all of the console info
	 // it is used here to find the size of the console.
	 CONSOLE_SCREEN_BUFFER_INFO csbi;
	 //Here we will set the current color
	 if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
	 {
		  //This fills the buffer with a given character (in this case 32=space).
		  FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
		  FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count );
		  //This will set our cursor position for the next print statement.
		  SetConsoleCursorPosition(hStdOut, coord);
	 }
	 return;
}
	char ct = 0;
	int px = 0;
	int py = 0;

int main() {
	int pX = 22;
	int pY = 10;
	int K = 0;
	HANDLE textOut;
while(K != 27)	{
	ClearConsole();
	textOut=GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(textOut, 8);
	cout << "++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n++++++++++++++""+++++++++++++++++++++++++++++++\n++++++++++++++++++++++++++++++++++++++++++++++\n"
;
	gotoXY(pX,pY);
    SetConsoleTextAttribute(textOut, 6);
	cout<<"@";
	SetConsoleTextAttribute(textOut, 9);
	gotoXY(30,24);
	cout << "X = "<< pX;
	gotoXY(60,24);
	cout << "Y ="<< pY;
	cout.flush();
	K = getch();
	switch(K){
	case 75:if(pX != 0){ pX--;} break;
	case 77: pX++; break;
	case 72:if(pY != 0){ pY--;} break;
	case 80: pY++; break;
	}
	Sleep(15);
	}
	return 0;
}


However, when I use ClearConsole(), it will clear the whole console, and it takes some time to re-print/re-cOut the map. How I clear only the previous position of the player?
I am using Windows 7 and Visual Studio 2010 as well, so there shouldn't be any problems.
For rogue-like games I usually make two functions, one which initializes a 2D char array with all of the chars being spaces; and one which prints out the whole 2D array.
Then I have x and y variables for the player's position:
 
grid[x][y] = 'P'   //'P' for player 

then to move the player, 1 to the left for example, I do:
1
2
grid[x][y] = ' '   //player's previous position erased.
grid[x-=1][y] = 'P'    //player's x position is now one to the left 

this will only affect the 2 positions.
That is genious! I will use it and see if I have nice results.
i thought you want some function like gotoxy() (which an old function, as far as i know. and i never use it)
You should remove all the goto's, do not use them under any circumstance.

And how are you getting along with the game?
Last edited on
It's easier to make a roguelike in a Windowed application than in the console. By faaaaaaar.
Also, you can do it using:

int coords[MAX_X*MAX_Y];

and next:

array[i+k*(MAX_X * MAX_Y)] = 15;


It has been used by Carmack (the creator of quake, doom etc.), but I am not sure in 100%.
Last edited on
It's easier to make a roguelike in a Windowed application than in the console. By faaaaaaar.


I doubt so. Do you have any tutorials? If it involves SDL and that crap, I am not interested though...

You should remove all the gotos.


I am not really developing the game at all, just looking for tutorials for user input before I start it. But anyways, why I shouldn't use gotos?

Also, you can do it using...


I didn't understand what you mean?
The WinAPI keeps an array that it uses to display the contents of the console.
Access it using ReadConsoleOutput().
http://www.google.com/search?btnI=1&q=msdn+ReadConsoleOutput

Another function of use is GetConsoleScreenBufferInfo[Ex]()

Hope this helps.
I find the MSDN's explanation a bit complicated. Could you explain the ReadConsoleOutput function?

Or should I use the second one?
You need to read through the descriptions of each argument.

The Windows Console window keeps a 2D array of information about what character is displayed on the screen and what colors it is displayed with.

If you want to access part of it, you need to make yourself a place to put the copy:

1
2
3
4
#include <windows.h>
...

CHAR_INFO a[ 3 /*rows*/ ][ 6 /*columns*/ ];


Let's fill it in with the top-left-most 6 columns and 3 rows:

6
7
8
9
10
11
12
13
14
15
COORD x0y0 = { 0, 0 };
SMALL_RECT coords_to_read = { /*left=*/0, /*top=*/0, /*right=*/5, /*bottom=*/2 };
if (!ReadConsoleOutput(
  GetStdHandle( STD_OUTPUT_HANDLE ),
  &a,
  3/*rows*/ * 6/*columns*/,
  x0y0,
  coords_to_read
  ))
  fooey();

Since you only want to read a single character, you can make a simple function to do it:

1
2
3
4
5
6
7
8
9
10
11
#include <windows.h>

char get_char_at_xy( int x, int y )
  {
  CHAR_INFO ci;
  COORD xy = { 0, 0 };
  SMALL_RECT rect = { x, y, x, y };
  return ReadConsoleOutput( GetStdHandle( STD_OUTPUT_HANDLE ), &ci, 1, xy, rect )
       ? ci.Char.AsciiChar
       : '\0';
  }

Hope this helps.
My VC++ 2010 compiler throws some errors.

1
2
3
4
1
1>  main.cpp
1>c:\therogue\therogue\use.h(16): error C2664: 'ReadConsoleOutputA' : cannot convert parameter 3 from 'int' to 'COORD'
1>          No constructor could take the source type, or constructor overload resolution was ambiguous
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


There is a USE.H file for my functions(including yours get_char_at_xy, which is now out::read) and the MAIN.CPP for obvious use. They are not written in caps.
There is nothing wrong with your goto function. They are confusing it with the C++ goto keyword which is frowned upon in favor of using functions (like you did :-).

One thing you should realize though is that C++ has absolutely no concept of your computer screen. Cout and Cin are just streams of data. YOU must keep track of where each character is placed in an array if you need to use that info later. There is no C++ function that will tell you what individual character is in 2D space on your screen. That is completely up to the graphics hardware and drivers, not C++.

EDIT: And yes, I realize you're using windows.h functions to handle this, just saying...

BTW, I used to stay at work passed midnight to play Rogue 30 years ago... PARTY ROOM!!
Last edited on
Topic archived. No new replies allowed.