I am trying to make a simple game. The basic concept is that the player (P) is moving around on a map. Eventually the player will have to avoid enemies and complete the level. Currently I have the player able to move around grab ammo and fire forward. I am clearing the entire screen and rewriting the map every so often so the user can input and play the game in real time. Here is my current code:
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
bool gameOver;
const int width = 20;
const int height = 20;
int x, y, ammoX, ammoY, score;
bool shot;
enum eDirecton { STOP = 0, LEFT, RIGHT, UP, DOWN, ALL};
eDirecton dir,shoot;
void Setup()
{
gameOver = false;
dir = STOP;
x = width / 2;
y = height / 2;
ammoX = rand() % width;
ammoY = rand() % height;
score = 0;
}
void Draw()
{
system("cls"); //system("clear");
for (int i = 0; i < width+2; i++)
cout << "-";
cout << endl;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (j == 0)
cout << "|";
if(shoot == UP){
if(i < y && j == x && score > 0){
cout << ":";
shot = true;
}
}
/*if(shoot == LEFT || shoot == ALL){
if(i == y && j < x && score > 0){
cout << "~";
shot = true;
}
}
if(shoot == RIGHT || shoot == ALL){
if(i == y && j > x && score > 0){
cout << "~";
shot = true;
}
}
if(shoot == DOWN){
if(i > y && j == x && score > 0){
cout << ":";
shot = true;
}
}*/
else if (i == y && j == x)
cout << "P";
else if (i == ammoY && j == ammoX && score < 50)
cout << "A";
else
{
bool print = false;
/*for (int k = 0; k < nTail; k++)
{
if (tailX[k] == j && tailY[k] == i)
{
cout << "o";
print = true;
}
}*/
if (!print)
cout << " ";
}
if (j == width - 1)
cout << "|";
}
cout << endl;
}
for (int i = 0; i < width+2; i++)
cout << "-";
cout << endl;
cout << "Score:" << score << endl;
cout << "x: " << x << endl;
cout << "y: " << y << endl;
/*
if(_kbhit()){
cout << _getch() << endl;
}//*/
}
void Input()
{
if (_kbhit())
{
switch (_getch())
{
case 75:
dir = LEFT;
break;
case 77:
dir = RIGHT;
break;
case 72:
dir = UP;
break;
case 80:
dir = DOWN;
break;
case 'w':
shoot = UP;
break;
case 'a':
shoot = LEFT;
break;
case 's':
shoot = DOWN;
break;
case 'd':
shoot = RIGHT;
break;
case 32:
shoot = ALL;
break;
case 27:
gameOver = true;
break;
}
}
}
void Logic()
{
/*int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for (int i = 1; i < nTail; i++)
{
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}*/
switch (dir)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
if(x>=width){
x--;
}
else if(x < 0){
x++;
}
if(y>=height){
y--;
}
else if(y < 0){
y++;
}
//if (x > width || x < 0 || y > height || y < 0)
// gameOver = true;
//if (x >= width) x = 0; else if (x < 0) x = width - 1;
//if (y >= height) y = 0; else if (y < 0) y = height - 1;
/* for (int i = 0; i < nTail; i++)
if (tailX[i] == x && tailY[i] == y)
gameOver = true;*/
if (x == ammoX && y == ammoY)
{
score += 10;
ammoX = rand() % width;
ammoY = rand() % height;
//nTail++;
}
if(shot == true){
score -= 10;
}
}
int main()
{
Setup();
while (!gameOver)
{
Draw();
shoot = STOP;
Input();
Logic();
shot = false;
dir = STOP;
Sleep(30); //sleep(10);
}
return 0;
}
Is there a way to rewrite a certain line (such as the line the player is on and the one the player is moving to) so that I only have to rewrite a portion of the map instead of the entire map. It currently flashes and is hard to see since it flashes so often. If I could rewrite certain lines when the user inputs a key. I have tried \r and the setCursorPos() function, but I don't think I understand them entirely. I am using Windows 10 and Windows 7 and am using Microsoft Visual 2010. Please Help!
Thanks
"I have tried \r and the setCursorPos() function, but I don't think I understand them entirely. "
This should work:
void setcp( int x, int y )
{
HANDLE hStdout = GetStdHandle( STD_OUTPUT_HANDLE );
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
csbiInfo.dwCursorPosition = COORD{ x, y };
SetConsoleCursorPosition( hStdout, csbiInfo.dwCursorPosition );
}
See this for more Windows console functions.
Related
I'm a beginner in c++ so I started making a snake game in c++. But just as I complete the program i run into a problem and i just cant find the fix. When the snake picks up the fruit, it generates a segment, but the first segment doesn't follow the snake. The next segments do follow the snake. Any help to the solution is really appreciated.
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
bool gameOver;
const int width = 40;
const int height = 40;
int x, y, fruitX, fruitY, score;
int tailX[100], tailY[100]; // snail coordinates
int nTail;
enum eDirection {STOP = 0, LEFT,RIGHT,UP,DOWN}; //controls for snake
eDirection dir;
//set fruit position and snake position
void setup(){
gameOver = false;
dir = STOP;
x = width / 2;
y = width / 2;
fruitX = rand() % width;
fruitY = rand() % height;
}
//draw the map
void draw(){
system("cls");
for(int i = 0; i < width+2; i++)
cout << "#";
std::cout << endl;
for(int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
if (j == 0){
std::cout << "|";
}
if(i == y && j == x){
std::cout << "O";
} else if (i == fruitY && j == fruitX) {
std::cout << "F";
} else {
bool segment = false;
for(int l = 0; l < nTail; l++){
if (tailX[l] == j && tailY[l] == i){
std::cout << "o";
segment = true;
};
}
if(!segment){
std::cout << " ";
}
}
if(j == width-1) {
std::cout << "|";
}
}
std::cout << endl;
}
for(int i = 0; i < width+2; i++)
cout << "#";
std::cout << endl;
//display score
std::cout << " Score: " << score << endl;
}
//set snake direction
void movement(){
if(_kbhit()){
switch(_getch()){
case 'a':
dir = LEFT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'd':
dir = RIGHT;
break;
case 'x':
gameOver = true;
break;
}
}
}
//update snake direction
void movementUpdate(){
// make tail and coordinate tail
int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for(int i = 0; i < nTail; i++){
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
switch(dir){
case STOP:
break;
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
//allow player to move through left and right walls
if(x >= width){
x = 0;
} else if ( x < 0) {
x = width -1;
}
if(y >= height){
y = 0;
} else if ( y < 0) {
y = height -1;
}
// check for game over
// if(x > width || x < 0 || y > height || y < 0){
// gameOver = true;
// }
//check if snake hit itself
for(int i = 0; i < nTail; i++){
if(tailX[i] == x && tailY[i] == y){
gameOver = true;
}
}
//check if snake takes fruit
if(x == fruitX && y == fruitY){
nTail++;
score += 10;
fruitX = rand() % width;
fruitY = rand() % height;
}
}
// initialize game
int main(){
setup();
while(!gameOver){
draw();
movement();
movementUpdate();
//sleep(10);
}
return 0;
}
In the first for loop in movement update where you update the tail. If you think about in the case of nTail = 1 you are basically only setting tailX[0] = tailX[0] and tailY[0] = tailY[0].
Simplified for loop when nTail = 1:
// make tail and coordinate tail
int prevX = tailX[0];
int prev2X;
tailX[0] = x;
{
prev2X = tailX[0];
tailX[0] = prevX; // prevX = tailX[0]
prevX = prev2X;
}
This is a working for loop:
// make tail and coordinate tail
int nextX = x;
int nextY = y;
int tX, tY;
for(int i = 0; i < nTail; i++){
tX = tailX[i];
tY = tailY[i];
tailX[i] = nextX;
tailY[i] = nextY;
nextX = tX;
nextY = tY;
}
i'm trying to make a unbeatable tic tac toe for a side project and i can't make it right (i can actually beat it ironically).
It's actually a implementation of the MiniMax algorithm; i came with this code
#include <iostream>
#include <string>
using namespace std;
struct Move
{
int line, columns;
};
//Return the number of remainings turn based on the number of lest boxes
int remainingsTurns(char grid[3][3])
{
int remainingTurn = 0;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
remainingTurn++;
}
}
}
return remainingTurn;
}
//Print the grid on screen
void printGrid(char grid[3][3])
{
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
cout << "| " << grid[k][i] << " ";
}
cout << "|" << endl;
}
}
//Give a value to the board
int evaluateBoard(char grid[3][3])
{
//Check the board for lines
for (int k = 0; k < 3; k++)
{
if (grid[k][0] == grid[k][1] && grid[k][1] == grid[k][2])
{
if (grid[k][0] == 'x')
{
return +10;
}
else if (grid[k][0] == 'o')
{
return -10;
}
}
}
//Check the board for columns
for (int k = 0; k < 3; k++)
{
if (grid[0][k] == grid[1][k] && grid[1][k] == grid[2][k])
{
if (grid[0][k] == 'x')
{
return +10;
}
else if (grid[0][k] == 'o')
{
return -10;
}
}
}
//Check the board for diagonals
if (grid[0][0] == grid[1][1] && grid[0][0] == grid[2][2])
{
if (grid[0][0] == 'x')
{
return +10;
}
else if (grid[0][0] == 'o')
{
return -10;
}
}
if (grid[0][2] == grid[1][1] && grid[0][2] == grid[2][0])
{
if (grid[0][0] == 'x')
{
return +10;
}
else if (grid[0][0] == 'o')
{
return -10;
}
}
//if no ictory return 0
return 0;
}
// MiniMax algorithm
int miniMax(char grid[3][3], int turn, bool maxMove)
{
int score = evaluateBoard(grid);
if (score == 10)
{
return score;
}
if (score == -10)
{
return score;
}
//Check if the game is a tie
if (remainingsTurns(grid) == 0)
{
return 0;
}
if (maxMove)
{
int best = -1000;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
grid[k][i] = 'x';
best = max(best, miniMax(grid, turn + 1, !maxMove));
grid[k][i] = ' ';
}
}
}
return best;
}
else
{
int best = 1000;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
grid[k][i] = 'o';
best = min(best, miniMax(grid, turn + 1, !maxMove));
grid[k][i] = ' ';
}
}
}
return best;
}
}
Move playerMov(char grid[3][3])
{
Move playerMove;
int input = -1;
cout << "Enter the column you want to play (1, 2 or 3)" << endl;
cin >> input;
if (input == 1 || input == 2 || input == 3)
{
playerMove.columns = input-1;
input = -1;
}
else
{
cout << "Error, enter a valid number!" << endl;
playerMov(grid);
}
cout << "Enter the line you want to play (1, 2 or 3)" << endl;
cin >> input;
if (input == 1 || input == 2 || input == 3)
{
playerMove.line = input-1;
input = -1;
}
else
{
cout << "Error, enter a valid number!" << endl;
playerMov(grid);
}
return playerMove;
}
//return the best move using the MiniMax
Move findMove(char grid[3][3])
{
int best = -1000;
Move move;
move.line = -1;
move.columns = -1;
//Check all move to find if this move is the best possible move
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
if (grid[k][i] == ' ')
{
grid[k][i] = 'x';
int moveValue = miniMax(grid, 0, false);
grid[k][i] = ' ';
if (moveValue > best)
{
move.line = k;
move.columns = i;
}
}
}
}
return move;
}
int main()
{
char grid[3][3];
int turn = 0;
Move playerMove, algoMove;
for (int k = 0; k < 3; k++)
{
for (int i = 0; i < 3; i++)
{
grid[k][i] = ' ';
}
}
cout << "Welcome to the unbeatable Tic Tac Toe !" << endl;
do
{
printGrid(grid);
playerMove = playerMov(grid);
grid[playerMove.line][playerMove.columns] = 'o';
Move computerMove = findMove(grid);
grid[computerMove.line][computerMove.columns] = 'x';
} while (remainingsTurns(grid) > 0);
cout << endl;
}
but the movements of the algorithm doesn't seems right, it always choose the bottom right corner and i don't understand why...
This implementation is largely inspired by this article from Geek for Geek where i tried to steal the algorithm but i can't get it right to make it fit for single player.
What do i miss?
There are multiple bugs in your code:
You are checking the value of grid[0][0] in grid[0][2] == grid[1][1] && grid[0][2] == grid[2][0] case of the function evaluateBoard. It should be grid[0][2].
playerMov(grid); in the function playerMov should be return playerMov(grid);. Otherwise, the re-entered "correct" values will be dropped and (partly) uninitalized playerMov will be returned.
You should update best to moveValue when moveValue > best in the function findMove. (this should be the cause of the issue on your question)
I am a beginner in c++ and i made my first game, a snake game. I made it without any graphics library.
So far the things were good, my snake was just running fine and eating the fruit and score is also increasing.
At the moment my snake just runs while the key is pressed, but now I want to run my snake continuously and just change its direction with keys as we have seen in old snake games.
So far I have tried many things from my side, like a loop and all, but the things just didn't work in the way I wanted it to be.
There is my code-
#include<iostream>
#include<conio.h>
#include<Windows.h>
using namespace std;
bool gameOver;
const int width = 20;
const int height = 20;
int x, y, fruitX, fruitY, score;
int tailX[100], tailY[100];
int n_Tail;
enum eDirection {STOP = 0, LEFT , RIGHT ,UP , DOWN};
eDirection dir;
void setup()
{
gameOver = false;
dir = STOP;
x = width / 2;
y = height / 2;
fruitX = rand() % width;
fruitY = rand() % height;
score = 0;
}
void draw()
{
system("cls");
for(int i = 0 ;i < width+1; i++)
{
cout << "#"; //for Upper wall
}
cout << "\n";
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width ; j++)
{
if (j==0)
{
cout <<"#";
}
if (i == y && j == x)
{
cout <<"0";
}
else if (i == fruitY && j == fruitX)
{
cout <<"f";
width - 1;
}
else if (j== width -1)
{
cout << "#";
}
else
{
bool print = false;
for (int k = 0; k <n_Tail; k++)
{
if (tailX[k] == j && tailY[k] == i )
{
cout << "o";
print = true;
}
}
if (!print)
{
cout <<" ";
}
}
}
cout << "\n";
}
for (int i = 0; i < width+1; i++)
{
cout << "#"; //for lower wall
}
cout <<"\n";
cout << "Score = " << score;
}
void input()
{
switch (_getch())
{
case 'a': dir = LEFT;
break;
case 'w': dir = UP;
break;
case 's': dir = DOWN;
break;
case 'd': dir = RIGHT;
break;
}
}
void logics()
{
int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for (int i = 1; i < n_Tail; i++)
{
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
switch (dir)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
y--;
}
for (int i = 0; i < n_Tail; i++)
{
if (tailX[i] == x && tailY[i] == y)
{
gameOver = true;
}
}
//if (x> width||x<0||y>height||y<0)
//{
//gameOver = true;
//}
if (x > width-2)x = 0; else if (x < 0)x = width - 2;
if (y > height-1)y = 0; else if (y < 0)y = height - 1;
{
}
if (x == fruitX && y == fruitY)
{
score = score + 10;
fruitX = rand() % width;
fruitY = rand() % height;
n_Tail++;
}
}
int main()
{
setup();
while (!gameOver)
{
draw();
input();
logics();
Sleep(10);
}
}
someone please help me with this so i can continue learning c++ peacefully.
As I'm sure you noticed when you used your debugger.
No? No debugger? This is your essential read!
You're using _getch to read the input.
getch is blocking - meaning it will wait until you press a key. It's not really what you want.
This post explains how to make a non-blocking version.
I am writing a snake game, and I have been able to produce a complete result that works as planned.
However, the game seems to randomly crash. I hit another command and the game closes even with the GameOver conditions are not met.
I have attached the code:
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
bool GameOver;
const int width = 20;
const int height = 20;
int x, y, fruitX, fruitY, score;
int tailX[100], tailY[100];
int nTail;
enum Direction { STOP = 0, LEFT, RIGHT, UP, DOWN};
Direction dir;
int Setup()
{
GameOver = false;
dir = STOP;
x = width / 2;
y = height / 2;
fruitX = rand() % width;
fruitY = rand() % height;
score = 0;
return 0;
}
int Draw()
{
system("cls"); //system("clear");
for (int i = 0; i < width+2; i++)
cout << "#";
cout << endl;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (j == 0)
cout << "#";
if (i == y && j == x)
cout << "O";
else if (i == fruitY && j == fruitX)
cout << "F";
else
{
bool print = false;
for (int k = 0; k < nTail; k++)
{
if (tailX[k] == j && tailY[k] == i)
{
cout << "o";
print = true;
}
}
if (!print)
cout << " ";
}
if (j == width - 1)
cout << "#";
}
cout << endl;
}
for (int i = 0; i < width+2; i++)
cout << "#";
cout << "\n";
cout << "Score:" << score << "\n";
return 0;
}
int Input()
{
if (_kbhit())
{
switch (_getch())
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'x':
gameOver = true;
break;
}
}
return 0;
}
int Logic()
{
int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for (int i = 1; i < nTail; i++)
{
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
switch (dir)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
for (int i = 0; i < nTail; i++)
if (tailX[i] == x && tailY[i] == y)
GameOver = true;
if (x == fruitX && y == fruitY)
{
score += 10;
fruitX = rand() % width;
fruitY = rand() % height;
nTail++;
}
return 0;
}
int main()
{
Setup();
while (!GameOver)
{
Draw();
Input();
Logic();
Sleep(50);
}
return 0;
}
Your tailX/tailY arrays have a capacity of 100, but you don't enforce a limit on how large nTail gets. So when nTail becomes larger than 100, the behaviour of your program becomes undefined and may randomly crash.
But really, you should 1) learn how to use a debugger, and 2) get a more modern C++ compiler. Very few here would be able to compile or test this.
So I'm currently working on a small project named dungeon crawl, where the user controls a char, player, and tries to reach another char, treasure. So far I have been able to program this but every time I print the board, it prints another game board right below the previous one! I want the board to constantly update the position of the player, not move the player and then print out a whole new board! I know this is a logic error but I cannot seem to find an answer, thanks in advance guys:
class Player
{
public:
int posX = 5;
int posY = 10;
char avatar = 'G';
};
class Treasure
{
public:
int posX = 2;
int posY = 10;
char avatar = 'X';
};
char board[10][20];
char player_move = 0;
bool player_win = 0;
Player p;
Treasure t;
void fill_board()
{
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 20; ++j)
board[i][j] = '.';
}
}
void print_board()
{
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 20; ++j)
{
cout << board[i][j];
}
cout << endl;
}
}
void set_player()
{
board[p.posX][p.posY] = p.avatar;
}
void erase_board(char b[][20])
{
for (int i = 0; i < 20; ++i)
{
for (int j = 0; j < 40; ++j)
board[i][j] = 0;
}
}
int main()
{
// Make board
fill_board();
// Set initial player position
board[p.posX][p.posY] = p.avatar;
// Set treasure position
board[t.posX][t.posY] = t.avatar;
// Start of game
player_win = false;
cout << "Welcome to dungeon crawl! To move press 'w', 'a', 's' , 'd' " << endl;
cout << endl;
//Prints board
print_board();
//Player movement
while (player_win == false)
{
cin >> player_move;
switch (player_move)
{
case 'w':
board[p.posX][p.posY] = '.';
p.posX -= 1;
break;
case 's':
board[p.posX][p.posY] = '.';
p.posX += 1;
break;
case 'a':
board[p.posX][p.posY] = '.';
p.posY -= 1;
break;
case 'd':
board[p.posX][p.posY] = '.';
p.posY += 1;
break;
}
set_player();
print_board();
// Check if player has won
if (p.posX == t.posX && p.posY == t.posY)
player_win = true;
}
cout << "\nCongratulations you win!!" << endl;
return 0;
}