问题
In the following code, I have the game board stay the same. I have the program looping so that the user can recycle the cards through as many times as they want. I would like it so that the character typed by the user will show in the exact same spot each time, instead of creating a new line. I would like for it to show so they can see what they typed before they hit enter. I am still pretty new to coding and I am in my 2nd C++ class, and I wish to learn and impress. To start off, I am using Microsoft Visual Studio 2013. Through research I got this code built:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <Windows.h>
#include <string>
using namespace std;
const TCHAR SUITS[] = { 'H', 'C', 'D', 'S' };
const TCHAR FACES[] = { 'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K' };
const TCHAR SPACE = ' ';
const int number_of_cards = 5;
int main() {
char * line_of_stars = "*****************************************************\n";
char * line_of_spaces = "* *\n";
char * top_of_cards = "* ******* ******* ******* ******* ******* *\n";
char * card_sides = "* * * * * * * * * * * *\n";
char quit = 'q';
//Display Screen
cout << line_of_spaces << top_of_cards << card_sides << card_sides << card_sides
<< card_sides << card_sides << top_of_cards << line_of_spaces << line_of_stars;
cout << "\nPress 'q' to quit or any other key to get new cards: ";
DWORD dw;
COORD suitCoord;
COORD faceCoord;
COORD nextMove;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut == INVALID_HANDLE_VALUE){
printf("Invalid handle");
}
nextMove.X = 53;
nextMove.Y = 11;
do {
for (int i = 0; i < number_of_cards; i++){
int startX = 6 + (i * 10);
int startY = 3;
//Set coords for the i-nth card
suitCoord.X = (startX);
suitCoord.Y = (startY);
faceCoord.X = (startX);
faceCoord.Y = (startY + 2);
//suit random num
int rand1 = rand() % 4;
TCHAR suit_char = SUITS[rand1];
int rand2 = rand() % 13;
TCHAR face_char = FACES[rand2];
//Print to screen
WriteConsoleOutputCharacter(hStdOut, &suit_char, 1, suitCoord, &dw);
WriteConsoleOutputCharacter(hStdOut, &face_char, 1, faceCoord, &dw);
}
// Cover Last input with a space
WriteConsoleOutputCharacter(hStdOut, &SPACE, 1, nextMove, &dw);
cin.clear();
cin >> quit;
cout << "\b\b";
} while (!(quit == 'q' || quit == 'Q'));
return 0;
}
I have it so that the the program puts a space in the spot where the initial that the user will type the first input. After the first input the cin character shows on the next line until the user types 'q' or 'Q'. I would like for it to show in the same spot each time. The X coord should be: 51 and the Y coord should be: 12. I am trying not to use the clear screen technique because I used that for my final last semester and it flashed a lot reprinting the lines.
回答1:
One way to achieve this would be to move the cursor position each time they enter a number
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), { 0, 0 });
This code should work:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <Windows.h>
#include <string>
using namespace std;
const TCHAR SUITS[] = { 'H', 'C', 'D', 'S' };
const TCHAR FACES[] = { 'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K' };
const TCHAR SPACE = ' ';
const int number_of_cards = 5;
int main() {
char * line_of_stars = "*****************************************************\n";
char * line_of_spaces = "* *\n";
char * top_of_cards = "* ******* ******* ******* ******* ******* *\n";
char * card_sides = "* * * * * * * * * * * *\n";
char quit = 'q';
//Display Screen
cout << line_of_spaces << top_of_cards << card_sides << card_sides << card_sides
<< card_sides << card_sides << top_of_cards << line_of_spaces << line_of_stars;
cout << "\nPress 'q' to quit or any other key to get new cards: ";
DWORD dw;
COORD suitCoord;
COORD faceCoord;
COORD nextMove;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut == INVALID_HANDLE_VALUE){
printf("Invalid handle");
}
nextMove.X = 53;
nextMove.Y = 11;
do {
for (int i = 0; i < number_of_cards; i++){
int startX = 6 + (i * 10);
int startY = 3;
//Set coords for the i-nth card
suitCoord.X = (startX);
suitCoord.Y = (startY);
faceCoord.X = (startX);
faceCoord.Y = (startY + 2);
//suit random num
int rand1 = rand() % 4;
TCHAR suit_char = SUITS[rand1];
int rand2 = rand() % 13;
TCHAR face_char = FACES[rand2];
//Print to screen
WriteConsoleOutputCharacter(hStdOut, &suit_char, 1, suitCoord, &dw);
WriteConsoleOutputCharacter(hStdOut, &face_char, 1, faceCoord, &dw);
}
// Cover Last input with a space
WriteConsoleOutputCharacter(hStdOut, &SPACE, 1, nextMove, &dw);
cin.clear();
cin >> quit;
cout << "\b\b";
SetConsoleCursorPosition(hStdOut, { 53, 11 });
} while (!(quit == 'q' || quit == 'Q'));
return 0;
}
Also, there is nothing wrong with clearing the screen as long as you don't use system("cls");
You can use a function like this, to fill the console buffer with spaces.
void clearScreen(){
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD count, cellCount;
if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) return;
cellCount = csbi.dwSize.X *csbi.dwSize.Y;
if (!FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), (TCHAR) ' ', cellCount, { 0, 0 }, &count))return;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), { 0, 0 });
}
回答2:
You can use system("CLS")
to clear the screen and then print everything again. You will just have to store your information somehow so that it is really easy to print, then just clear the screen and reprint. I don't think there is a way to modify on screen characters in a console program.
回答3:
void setPos(int x, int y)
{
COORD coord;
coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
return;
}
Use a method such as this to continually set the cursor to the same location by passing in the same coordinates every time. It may be beneficial to set the position and then write some spaces/newlines to the console to "erase" the previous input then set the cursor back again.
来源:https://stackoverflow.com/questions/27339936/how-to-make-the-cin-show-in-the-same-spot-each-time-for-c-console