I'm making a snake game and it's basically done; however sometimes when I run it it works at first then clears (that might be in my code, it has a lot of clears) and returns error code -1073741571.
This is the code:
#include <iostream>
#include <string>
#include <stdio.h>
#include <conio.h>
#include "windows.h"
#include <vector>
#include <random>
#include <ctime>
#include <cmath>
#include <windows.h>
using namespace std;
struct point
{
int x;
int y;
};
bool goTo(point p,vector<point>& snek)
{
bool flag=false;
for (size_t i = 0; i < snek.size(); i++)
{
if (p.x == snek[i].x && p.y == snek[i].y)
{
return true;
}
}
for (int i=snek.size()-1; i >0; i--)
{
snek[i] = snek[i - 1];
}
snek[0] = p;
return false;
}
void makeFood(point& apple, vector<point> snek)
{
bool appleValid = true;
apple.x = (rand() % 19) + 1;
apple.y = (rand() % 19) + 1;
for (int i = 0; i < snek.size() - 1; i++)
{
if (apple.x == snek[i].x && apple.y == snek[i].y)
{
appleValid = false;
break;
}
}
if (!appleValid)
{
srand(time(NULL));
makeFood(apple,snek);
}
}
int main()
{
vector<point> snek;
snek.push_back({ 10,10 });
snek.push_back({ 10,9 });
snek.push_back({ 10,8 });
snek.push_back({ 10,7 });
int highscore= 0, score;
bool tutorial = false;
bool p = false;
char move = 'w';
char sure = 'f';
string board[21][21];
int direction=2;
point apple;
apple.x = rand() % 20;
apple.y = rand() % 20;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
board[i][j] = " ";
}
}
bool loss = false;
while (true)
{
score = snek.size() - 4;
bool appleEaten = false;
srand(time(NULL));
if (snek[0].x == 0 )
loss = true;
if (snek[0].x == 20 )
loss = true;
if (snek[0].y == 0 )
loss = true;
if (snek[0].y == 20 )
loss = true;
if (loss)
{
system("CLS");
if (score > highscore)
{
highscore = score;
}
cout << "You lost with a score of " << snek.size() - 4 << endl;
cout << "Your highscore for this session is " << highscore<<endl;
cout << "Press any key to play again" << endl;
cout << "Press RMB to quit" << endl;
while (true)
{
if (GetAsyncKeyState(VK_RBUTTON))
{
system("CLS");
cout << "Are you sure you want to quit? Your highscore for this session will be reset" << endl;
cout << "Press Q to quit and P to play again" << endl;
sure = _getch();
if (sure == 'q' || sure == 'Q')
{
_Exit(0);
}
if (sure == 'p' || sure == 'P')
{
p = true;
}
}
if (_kbhit() || p)
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
board[i][j] = " ";
}
}
snek.clear();
snek.push_back({ 10,10 });
snek.push_back({ 10,9 });
snek.push_back({ 10,8 });
snek.push_back({ 10,7 });
loss = false;
p = false;
break;
}
}
}
Sleep(100);
if (_kbhit())
{
move = _getch();
}
system("CLS");
switch (move)
{
case 'w':
loss = goTo({ (snek[0].x - 1),snek[0].y }, snek);
Sleep(10);
break;
case 'a':
loss = goTo({ snek[0].x ,(snek[0].y - 1) }, snek);
Sleep(10);
break;
case 's':
loss = goTo({ (snek[0].x + 1),snek[0].y }, snek);
Sleep(10);
break;
case'd':
loss = goTo({ snek[0].x ,(snek[0].y + 1) }, snek);
Sleep(10);
break;
}
board[apple.x][apple.y] = " 0";
for (int k = 0; k < snek.size() - 1; k++)
{
board[snek[k].x][snek[k].y] = " *";
board[snek[snek.size() - 1].x] [snek[snek.size() - 1].y] = " ";
}
if (apple.x == snek[0].x && apple.y == snek[0].y)
{
snek.push_back({snek[snek.size()-1].x+1,snek[snek.size() - 1].y});
appleEaten = true;
}
if (appleEaten)
{
makeFood(apple,snek);
}
for (int i = 0; i < 20; i++)
{
board[0][i] = "--";
board[20][i] = "--";
}
for (int i = 0; i < 20; i++)
{
board[i][0] = '|';
board[i][20] = '|';
}
if (!tutorial)
{
cout << "You are a snake." << endl;
cout << "Your body looks like this" << endl;
cout << "*****" << endl;
cout << "Move with WASD" << endl;
cout << "If you eat the apples, which look like this " << endl << "0" << endl;
cout << "You get bigger. If you try to eat yourself or run into walls, you lose" << endl;
cout << "Click RMB to begin";
while (true)
{
if (GetAsyncKeyState(VK_RBUTTON))
{
system("CLS");
tutorial = true;
break;
}
}
}
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 21; j++)
{
cout << board[i][j];
}
cout << endl;
}
cout << "Score: " << score;
}
}
EDIT: Most of the time it works fine, only sometimes I get the error
EDIT: The stack overflow is in int main()
Let’s take a closer look at your makeFood function:
void makeFood(point& apple, vector<point> snek)
{
bool appleValid = true;
apple.x = (rand() % 19) + 1;
apple.y = (rand() % 19) + 1;
for (int i = 0; i < snek.size() - 1; i++)
{
if (apple.x == snek[i].x && apple.y == snek[i].y)
{
appleValid = false;
break;
}
}
if (!appleValid)
{
srand(time(NULL));
makeFood(apple,snek);
}
}
Your if statement makes it so that makeFood() is called again when the apple is at the snakes position, but using srand(time(NULL)) will put the apple back into the same place, which calls the function again and again for an infinite amount of time. Remove srand(time(NULL)) in the if(!appleValid) and your program shouldn’t have the issue because you only need to seed random.
if you can, try to convert your random functions to the <random> header, but it should work fine with rand as well :)
Related
I am trying to create a c++ unbeatable tic tac toe AI. after watching several videos on the topic i thought I had it all figured out. An error pops up on the screen saying "Expression: vector subscript out of range". I believe the error is coming from the availableMoves() function. however I do not know why.
The game itself works fine. any help would be appreciated.
#include <iostream>
#include <vector>
#include <ctime>
bool in(std::vector<int> v, int element)
{
for (int i = 0; i < v.size(); i++)
{
if (element == v[i])
{
return true;
}
}
return false;
}
class Board
{
private:
char board[3][3] = { {'1', '2', '3'}, {'4', '5', '6'}, {'7', '8', '9'} };
public:
void displayBoard()
{
std::cout << "___________________" << std::endl;
for (int i = 0; i < 3; i++)
{
std::cout << "| ";
for (int j = 0; j < 3; j++)
{
std::cout << board[i][j] << " | ";
}
std::cout << std::endl;
}
std::cout << "___________________" << std::endl;
}
std::vector<int> availableMoves()
{
std::vector<int> moves;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i][j] != 'X' && board[i][j] != 'O')
{
moves.push_back(i * 3 + j);
}
}
}
return moves;
}
void move(int choice, char mark)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = mark;
}
void revert(int choice)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = (char)choice + 48;
}
int checkWin()
{
for (int i = 0; i < 3; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
{
if (board[i][0] == 'X')
{
return 1;
}
else if (board[i][0] == 'O')
{
return -1;
}
}
}
for (int i = 0; i < 3; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
{
if (board[0][i] == 'X')
{
return 1;
}
else if (board[0][i] == 'O')
{
return -1;
}
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2])
{
if (board[0][0] == 'X')
{
return 1;
}
else if (board[0][0] == 'O')
{
return -1;
}
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0])
{
if (board[0][2] == 'X')
{
return 1;
}
else if (board[0][2] == 'O')
{
return -1;
}
}
return 0;
}
int evaluate()
{
return (checkWin() * -1) * (availableMoves().size() + 1);
}
Board& operator=(Board& b)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
board[i][j] = b.board[i][j];
}
}
return (*this);
}
};
class TicTacToe
{
private:
Board board;
int turn;
int searches = 0;
public:
TicTacToe()
{
std::srand(time(0));
turn = std::rand() % 2;
}
int minimax(int depth, Board curBoard, bool is_max)
{
searches++;
if (depth == 0 || curBoard.checkWin() != 0)
{
return board.evaluate();
}
if (is_max)
{
int max_eval = -2147483647;
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'O');
depth -= 1;
int eval = minimax(depth, curBoard, false);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval > max_eval)
{
max_eval = eval;
}
}
return max_eval;
}
if (!is_max)
{
int min_eval = 2147483647;
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'X');
depth -= 1;
int eval = minimax(depth, curBoard, true);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval < min_eval)
{
min_eval = eval;
}
}
return min_eval;
}
}
void game()
{
while (board.checkWin() == 0 && board.availableMoves().size() != 0)
{
board.displayBoard();
if (turn % 2 == 0)
{
std::cout << std::endl;
int choice;
std::cout << "Enter Your Move: ";
std::cin >> choice;
choice -= 1;
while (!in(board.availableMoves(), choice))
{
std::cout << "Enter A Valid Move: ";
std::cin >> choice;
}
board.move(choice, 'X');
std::cout << std::endl;
turn++;
}
board.displayBoard();
if (board.checkWin() != 0)
{
break;
}
if (turn % 2 == 1)
{
int ai = minimax(9 - (turn % 2), board, true);
std::cout << searches;
std::cin.get();
turn++;
}
}
if (board.checkWin() == 1)
{
std::cout << "You Won" << std::endl;
}
else if (board.checkWin() == -1)
{
std::cout << "You Lost" << std::endl;
}
else
{
std::cout << "Tie" << std::endl;
}
std::cout << "Would You Like To Play Again Y/N: ";
char playAgain;
std::cin >> playAgain;
if (playAgain == 'Y')
{
Board newBoard;
board = newBoard;
game();
}
}
};
int main()
{
TicTacToe ticTacToe;
ticTacToe.game();
}
Do you know how to debug? If not, you should definitely learn this, it's pretty helpful. But here's some things I found out.
The problem is not in availableMoves(), but in minimax(), more precisely in line 215, where the program calls curBoard. revert(curBoard. availableMoves()[i]).
void revert(int choice)
{
int y = choice / 3;
int x = choice - y * 3;
board[y][x] = (char)choice + 48;
}
for (int i = 0; i < curBoard.availableMoves().size(); i++)
{
curBoard.move(curBoard.availableMoves()[i], 'X');
depth -= 1;
int eval = minimax(depth, curBoard, true);
curBoard.revert(curBoard.availableMoves()[i]);
if (eval < min_eval)
{
min_eval = eval;
}
}
The error happens in the function revert, but I am not sure why. Maybe availableMoves also returns something wrong. Variable i is permanently 0 in the for-loop. So it is possible that there is something wrong at position 0 of the vector moves, which revert cannot handle. Try debugging yourself, maybe you'll find the problem.
My program is exiting without iterating. It automatically goes to "YOU WON". Without the champion function the program runs fine. Its probably some obvious error Im missing. If anyone could please I would greatly appreciate it.
#include <iostream>
#include <string>
#define GRID_SIZE 3
class TicTacToe {
private:
char map[GRID_SIZE][GRID_SIZE];
public:
void champion() {
const char *possiblities[8]{
"123"
"456"
"789"
"147"
"159"
"258"
"369"
"753"
};
for (int i = 0; i < 8; i++) {
bool winner = true;
char previous_pos = '0';
const char *possible_moves = possiblities[i];
for (int index = 0; index < GRID_SIZE; index++) {
char character = possible_moves[i];
int entered_num = character - '0';
int grid_space = entered_num - 1;
int row = index / GRID_SIZE;
int col = index % GRID_SIZE;
char grid_coordinate = map[row][col];
if (previous_pos == '0') {
previous_pos = grid_coordinate;
} else if
(previous_pos == grid_coordinate) {
continue;
} else {
winner = false;
break;
}
}
if (winner = true) {
std::cout << "YOU WON" << std::endl;
exit(0);
break;
}
}
}
void playgame() {
std::string input;
while (true) {
std::cout << "Go player one" << std::endl;
getline(std::cin, input);
if (input != " ") {
char entered = input.c_str()[0];
if (entered >= '1' && entered <= '9') {
int entered_num = entered - '0';
int index = entered_num - 1;
int row = index / 3;
int col = index % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char) 'X';
break;
}
} else {
std::cout << "Only numbers 1 - 9" << std::endl;
}
} else {
std::cout << "Have to enter something, try again" << std::endl;
}
}
}
void generateGrid() {
int number = 1;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
map[x][y] = std::to_string(number).c_str()[0];
number += 1;
}
}
}
void tictacToeMap() {
std::cout << std::endl;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
std::printf(" %c ", map[x][y]);
}
std::cout << std::endl;
}
}
TicTacToe() {
generateGrid();
while (true) {
tictacToeMap();
playgame();
champion();
}
}
};
int main() {
TicTacToe tic;
tic.playgame();
return 0;
}
The problem is here:
if (winner = true) {
std::cout << "YOU WON" << std::endl;
exit(0);
break;
}
You probably meant:
if (winner == true) {
std::cout << "YOU WON" << std::endl;
exit(0);
break;
}
First, do what Max Meijer said, by replacing if(winner = true) with if(winner == true). But the program is still broken. The problem is that in your string array, you are not separating each string with a comma, so when my debugger hits const char *possible_moves, it ends up just assigning the entire array concatenated together. So just separate each string in the possibilities array with a comma, like so:
const char *possiblities[8]{
"123",
"456",
"789",
"147",
"159",
"258",
"369",
"753"
};
I want the program to print "You win" when any of the instances in the champion() function are given. It only shows a winner when "123" is inputted. Whenever three X's are displayed anywhere else the program continues. For instance if three X's are given diagonally the program will still continue. Novice programmer so any criticism is greatly appreciated.
class TicTacToe {
private:
char map[GRID_SIZE][GRID_SIZE];
public:
void computers_turn() {
while (true) {
int choice = (rand() % 9) + 1;
int row = choice / 3;
int col = choice % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'O';
break;
}
}
}
void champion() {
const char* possiblities[8] = {"123", "456", "789", "147",
"258", "369", "159", "753"};
for (int i = 0; i < 8; i++) {
char previous_pos = '0';
bool winner = true;
const char* possible_moves = possiblities[i];
for (int index = 0; index < GRID_SIZE; index++) {
char character = possible_moves[i];
int entered_num = character - '0';
int grid_space = entered_num - '1';
int row = index / GRID_SIZE;
int col = index % GRID_SIZE;
char grid_coordinate = map[row][col];
if (previous_pos == '0') {
previous_pos = grid_coordinate;
} else if (previous_pos == grid_coordinate) {
continue;
} else {
winner = false;
break;
}
}
if (winner) {
puts("You win");
exit(0);
break;
}
}
}
void playgame() {
std::string input;
while (true) {
std::cout << "Go player one" << std::endl;
getline(std::cin, input);
if (input != " ") {
char entered = input.c_str()[0];
if (entered >= '1' && entered <= '9') {
int entered_num = entered - '0';
int index = entered_num - 1;
int row = index / 3;
int col = index % 3;
char grid_position = map[row][col];
if (grid_position == 'X' || grid_position == 'O') {
std::cout << "Space taken. Try again" << std::endl;
} else {
map[row][col] = (char)'X';
break;
}
} else {
std::cout << "Only numbers 1 - 9" << std::endl;
}
} else {
std::cout << "Have to enter something, try again" << std::endl;
}
}
}
void generateGrid() {
int number = 1;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
map[x][y] = std::to_string(number).c_str()[0];
number += 1;
}
}
}
void tictacToeMap() {
std::cout << std::endl;
for (int x = 0; x < GRID_SIZE; x++) {
for (int y = 0; y < GRID_SIZE; y++) {
std::printf(" %c ", map[x][y]);
}
std::cout << std::endl;
}
}
TicTacToe() {
generateGrid();
while (true) {
champion();
tictacToeMap();
playgame();
computers_turn();
}
}
};
int main() {
TicTacToe ticTacToe;
return 0;
}
As the title states i'm having trouble finding the error with the way in which my queue is being populated. It should be holding every visited state node until they have been processed. but the queue is not being populated as it should be. Can anyone help me find the bug? Below is my implementation file for the PuzzleStateNode class and source.cpp
EDIT: After more debugging it would seem that the problem lies with the following chunk of code from the solvePuzzle function. The items are never pushed to my queue, and I don't understand why. Could it be an issue with my unordered_set?
void solvePuzzle(string stateArray[3][3]) {
ofstream oFile("output.txt");
PuzzleStateNode pState(stateArray);
queue<PuzzleStateNode> puzzleQueue;
unordered_set<string> visitedPuzzleStateSet;
if (pState.parityCheck() == true) {
puzzleQueue.push(pState);
for(int i = 0; i < 31; i++){
PuzzleStateNode myTempState(puzzleQueue.front());
//puzzleQueue.pop();
if (visitedPuzzleStateSet.find(myTempState.getPuzzleID()) == visitedPuzzleStateSet.end()) { // is our value in the set? if not then do the following
visitedPuzzleStateSet.emplace(myTempState.getPuzzleID()); // add to the list of visited states.
if (myTempState.getEmptyXArrayPos() == 0 || myTempState.getEmptyXArrayPos() == 1) { // if a move to the right is available
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareRight(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl << endl << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have visited this already" << endl;
system("pause");
}
}
END EDIT:
PuzzleStateNode.h
#pragma once
#include<queue>
#include<iostream>
#include<fstream>
#include<cstdlib>
#include<string>
using namespace std;
class PuzzleStateNode
{
public:
PuzzleStateNode();
PuzzleStateNode(string tempArray[3][3]);
PuzzleStateNode(const PuzzleStateNode &other);
int getEmptyXArrayPos();
int getEmptyYArrayPos();
int getMoveCounter();
string getPuzzleID();
bool parityCheck();
bool checkForSolve();
void setPuzzleID();
void setEmptyXArrayPos(int x);
void setEmptyYArrayPos(int y);
void incrimentMoveCounter();
void pushToMoveQueue(string move);
void moveEmptySquareDown(int xEmptyPos, int yEmptyPos);
void moveEmptySquareUp(int xEmptyPos, int yEmptyPos);
void moveEmptySquareRight(int xEmptyPos, int yEmptyPos);
void moveEmptySquareLeft(int xEmptyPos, int yEmptyPos);
void printState(ofstream &oFile);
void printMoves(ofstream &oFile);
~PuzzleStateNode();
private:
string puzzleStateArray[3][3];
int moveCounter;
queue<string> moveQueue;
int emptyXArrayPos;
int emptyYArrayPos;
string puzzleID;
};
PuzzleStateNode.cpp
#include "PuzzleStateNode.h"
using namespace std;
PuzzleStateNode::PuzzleStateNode()
{
}
PuzzleStateNode::PuzzleStateNode(string tempArray[3][3])
{
puzzleID = "";
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzleStateArray[i][j] = tempArray[i][j];
puzzleID += tempArray[i][j];
if (puzzleStateArray[i][j] == "E") {
emptyXArrayPos = j;
emptyYArrayPos = i;
}
}
}
moveCounter = 0;
moveQueue.push("The following lists the movement of the Empty or 'E' square until the puzzle is solved: ");
}
PuzzleStateNode::PuzzleStateNode(const PuzzleStateNode &other) {
{ puzzleID = "";
moveCounter = other.moveCounter;
moveQueue = other.moveQueue;
emptyXArrayPos = other.emptyXArrayPos;
emptyYArrayPos = other.emptyYArrayPos;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzleStateArray[i][j] = other.puzzleStateArray[i][j];
puzzleID += other.puzzleStateArray[i][j];
}
}
}
}
int PuzzleStateNode::getEmptyXArrayPos() {
return emptyXArrayPos;
}
int PuzzleStateNode::getEmptyYArrayPos() {
return emptyYArrayPos;
}
int PuzzleStateNode::getMoveCounter() {
return moveCounter;
}
string PuzzleStateNode::getPuzzleID() {
return puzzleID;
}
bool PuzzleStateNode::checkForSolve() {
if (puzzleStateArray[0][0] == "1" && puzzleStateArray[0][1] == "2" && puzzleStateArray[0][2] == "3" && puzzleStateArray[1][0] == "4" && puzzleStateArray[1][1] == "5" && puzzleStateArray[1][2] == "6" && puzzleStateArray[2][0] == "7" && puzzleStateArray[2][1] == "8" && puzzleStateArray[2][2] == "E") {
return true;
}
return false;
}
void PuzzleStateNode::setPuzzleID() {
puzzleID = "";
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzleID += puzzleStateArray[i][j];
}
}
}
void PuzzleStateNode::setEmptyXArrayPos(int x) {
emptyXArrayPos = x;
}
void PuzzleStateNode::setEmptyYArrayPos(int y) {
emptyXArrayPos = y;
}
void PuzzleStateNode::incrimentMoveCounter() {
moveCounter++;
}
void PuzzleStateNode::pushToMoveQueue(string move) {
moveQueue.push(move);
}
void PuzzleStateNode::printMoves(ofstream &oFile) {
string tempString;
for (int i = 0; i < moveQueue.size(); i++) {
cout << moveQueue.front() << endl;
moveQueue.push(moveQueue.front());
moveQueue.pop();
}
cout << endl << endl;
}
void PuzzleStateNode::printState(ofstream &oFile) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
cout << puzzleStateArray[i][j];
}
cout << endl;
}
cout << endl;
}
void PuzzleStateNode::moveEmptySquareDown(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos + 1][xEmptyPos];
puzzleStateArray[yEmptyPos + 1][xEmptyPos] = "E";
moveQueue.push("Down");
moveCounter++;
cout << "Moving Down" << endl;
emptyYArrayPos = yEmptyPos + 1;
}
void PuzzleStateNode::moveEmptySquareUp(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos - 1][xEmptyPos];
puzzleStateArray[yEmptyPos - 1][xEmptyPos] = "E";
moveQueue.push("Up");
moveCounter++;
cout << "Moving Up" << endl;
emptyYArrayPos = yEmptyPos - 1;
}
void PuzzleStateNode::moveEmptySquareLeft(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos][xEmptyPos - 1];
puzzleStateArray[yEmptyPos][xEmptyPos - 1] = "E";
moveQueue.push("Left");
moveCounter++;
cout << "Moving Left" << endl;
emptyXArrayPos = xEmptyPos - 1;
}
void PuzzleStateNode::moveEmptySquareRight(int xEmptyPos, int yEmptyPos) {
puzzleStateArray[yEmptyPos][xEmptyPos] = puzzleStateArray[yEmptyPos][xEmptyPos + 1];
puzzleStateArray[yEmptyPos][xEmptyPos + 1] = "E";
moveQueue.push("Right");
moveCounter++;
cout << "Moving Right" << endl;
emptyXArrayPos = xEmptyPos + 1;
}
bool PuzzleStateNode::parityCheck() // counts number of swaps for a bubble sort excluding swaps involving the empty space
{
enter code here
// Puzzles with odd swaps have odd parity and are unsolvable.
string parityCheckString = "";
char tempChar;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
parityCheckString += puzzleStateArray[i][j];
}
}
int counter = 0;
for (int j = 0; j < 8; j++) {
for (int i = 0; i < 8; i++) {
if (parityCheckString[i] > parityCheckString[i + 1]) {
if (parityCheckString[i] == 'E') {
tempChar = parityCheckString[i];
parityCheckString[i] = parityCheckString[i + 1];
parityCheckString[i + 1] = tempChar;
}
else {
tempChar = parityCheckString[i];
parityCheckString[i] = parityCheckString[i + 1];
parityCheckString[i + 1] = tempChar;
counter += 1;
}
}
}
}
if (counter % 2 == 0) {
cout << "Even Parity, solving the 8 puzzle!" << endl;
return true;
}
else {
cout << "Parity is odd and puzzle is unsolvable. Skipping to next Puzzle." << endl;
return false;
}
}
PuzzleStateNode::~PuzzleStateNode()
{
}
source.cpp
#include"PuzzleStateNode.h"
#include<string>
#include<fstream>
#include<iostream>
#include<unordered_set>
using namespace std;
int main() {
void solvePuzzle(string stateArray[3][3]);
ifstream inFile("input.txt");
ofstream outFile("output.txt");
string puzNum;
int numberOfPuzzles;
string junk;
getline(inFile, puzNum); // read number of puzzles
numberOfPuzzles = stoi(puzNum); // convert value to int.
for (int i = 0; i < numberOfPuzzles; i++) {
string stateArray[3][3]; // populates a temporary puzzle state.
string temp;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
while (temp != "1" && temp != "2" && temp != "3" && temp != "4" && temp != "5" && temp != "6" && temp != "7" && temp != "8" && temp != "E") {
temp = inFile.get();
}
stateArray[i][j] = temp;
temp = inFile.get();
}
}
solvePuzzle(stateArray);
}
system("pause");
return 0;
}
void solvePuzzle(string stateArray[3][3]) {
ofstream oFile("output.txt");
PuzzleStateNode pState(stateArray);
queue<PuzzleStateNode> puzzleQueue;
unordered_set<string> visitedPuzzleStateSet;
if (pState.parityCheck() == true) {
puzzleQueue.push(pState);
for(int i = 0; i < 31; i++){
PuzzleStateNode myTempState(puzzleQueue.front());
//puzzleQueue.pop();
if (visitedPuzzleStateSet.find(myTempState.getPuzzleID()) == visitedPuzzleStateSet.end()) { // is our value in the set? if not then do the following
visitedPuzzleStateSet.emplace(myTempState.getPuzzleID()); // add to the list of visited states.
if (myTempState.getEmptyXArrayPos() == 0 || myTempState.getEmptyXArrayPos() == 1) { // if a move to the right is available
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareRight(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl << endl << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have visited this already" << endl;
system("pause");
}
}
if (myTempState.getEmptyXArrayPos() == 1 || myTempState.getEmptyXArrayPos() == 2) {
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareLeft(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
tempState.incrimentMoveCounter();
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have visited this state" << endl;
system("pause");
}
}
if (myTempState.getEmptyYArrayPos() == 0 || myTempState.getEmptyYArrayPos() == 1) {
PuzzleStateNode tempState;
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareDown(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "you have this state already" << endl;
system("pause");
}
}
if (myTempState.getEmptyYArrayPos() == 1 || myTempState.getEmptyYArrayPos() == 2) {
PuzzleStateNode tempState(myTempState);
tempState = PuzzleStateNode(myTempState);
tempState.moveEmptySquareUp(tempState.getEmptyXArrayPos(), tempState.getEmptyYArrayPos());
if (tempState.checkForSolve() == true) {
tempState.printState(oFile);
oFile << "Puzzle Solved in " << tempState.getMoveCounter() << " movements of the emtpy tile which are listed below." << endl;
tempState.printMoves(oFile);
cout << "Puzzle Solved!" << endl;
oFile.close();
return;
}
else if (tempState.checkForSolve() != true && visitedPuzzleStateSet.find(tempState.getPuzzleID()) == visitedPuzzleStateSet.end()) {
puzzleQueue.push(tempState);
}
else {
cout << "have visited this state already" << endl;
system("pause");
}
}
}
}
}
else
oFile.close();
return;
}
I found the problem! I was never resetting puzzle id's after copying so all puzzle states had the same ID for my set.
I'm beginner to C++. i'm making a snake game in c++ simple game console based. without using any graphics. i had done almost 60% of work the only thing which makes me confuse is the movement of snake after eating "fruit". Below is my code if someone can help me please it'll be very helpful or i want you to give me any hint so that i can continue my code
Here is my header file
snake.h:
#ifndef SNAKE_H
#define SNAKE_H
class snake
{
private:
char key;
int x1, y1, x2, y2, n;
char keyp;
public:
snake()
{
x1=28; y1=12; x2=0; y2=0; n=1;
}
void gotoxy(int x, int y);
void frame();
char movement(char keyp);
char rmove();
char lmove();
char umove();
char dmove();
void rstar();
void rcstar();
void options();
};
#endif // SNAKE_H
Here is my snake.cpp File
Snake.cpp
#include "snake.h"
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
//gotoxy function
COORD coord={0,0};
void snake::gotoxy(int x,int y)
{
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
void snake::frame()
{
for(int i=0;i<=78;i++)
cout << char(45);
for(int i=1;i<22;i++)
{
gotoxy(0,i);
cout << char(124);
gotoxy(63,i);
cout << char(124);
gotoxy(78,i);
cout << char(124);
}
cout << endl;
for(int i=0;i<=78;i++)
cout << char(45);
}
char snake::rmove()
{
for(;x1<=63;x1++)
{
Sleep(200);
if(x1==62)
{
x1=1;
gotoxy(61,y1);
cout << " ";
}
if(x1!=1)
{
gotoxy(x1-1,y1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='a' || keyp=='A' || keyp=='d' || keyp=='D')
continue;
else
break;
}
}
return keyp;
}
char snake::lmove()
{
for(x1;x1>=0;x1--)
{
Sleep(200);
if(x1==0)
{
x1=62;
gotoxy(1,y1);
cout << " ";
}
if(x1!=62)
{
gotoxy(x1+1,y1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='d' || keyp=='D' || keyp=='a' || keyp=='A')
continue;
else
break;
}
}
return keyp;
}
char snake::umove()
{
for(;y1>=0;y1--)
{
Sleep(200);
if(y1==0)
{
y1=21;
gotoxy(x1,1);
cout << " ";
}
if(y1!=21)
{
gotoxy(x1,y1+1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='s' || keyp=='S' || keyp=='w' || keyp=='W')
continue;
else
break;
}
}
return keyp;
}
char snake::dmove()
{
for(;y1<=22;y1++)
{
Sleep(200);
if(y1==22)
{
y1=1;
gotoxy(x1,21);
cout << " ";
}
if(y1!=1)
{
gotoxy(x1,y1-1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='w' || keyp=='W' || keyp=='s' || keyp=='S')
continue;
else
break;
}
}
return keyp;
}
char snake::movement(char keyp)
{
switch(keyp)
{
case 'w':
keyp=umove();
break;
case 's':
keyp=dmove();
break;
case 'd':
keyp=rmove();
break;
case 'a':
keyp=lmove();
break;
}
return keyp;
}
void snake::rcstar()
{
if(x1==x2 && y1==y2)
{
rstar();
n++;
}
gotoxy(65,8);
cout << "Score : " << n-1;
}
void snake::rstar()
{
x2 = rand()%61+1;
y2 = rand()%21+1;
gotoxy(x2, y2);
cout << "*";
}
void snake::options()
{
gotoxy(64,4);
cout << "[P] Pause";
gotoxy(64,5);
cout << "[K] Difficulty";
gotoxy(64,6);
cout << "[Q] Quit";
gotoxy(66,9);
cout << "High Score";
gotoxy(70,10);
cout << "0";
gotoxy(66,13);
cout << "SNAKE 2K ";
gotoxy(65,15);
cout << "Created By";
gotoxy(66,17);
cout << "Khurram";
}
And Here is main main.cpp file
main.cpp
#include <iostream>
#include <conio.h>
#include <windows.h>
#include "snake.h"
using namespace std;
int main()
{
snake a1;
char kph;
a1.load();
system("cls");
a1.frame();
a1.gotoxy(28,12);
cout << "*";
a1.rstar();
a1.options();
kph=getch();
do
{
if(kph=='w' || kph=='s' || kph=='a' || kph=='d')
kph=a1.movement(kph);
else if(kph=='q')
break;
else if(kph=='p' || kph=='P')
kph=getch();
else if(kph=='k' || kph=='K')
{ kph=a1.difficulty(); }
else
continue;
}
while(kph!='q');
a1.gotoxy(0,24);
return 0;
}
First of all i want to say that i know this code is really messed up but i'm beginner and still learning how to make a good program.
Please help me to complete this program.
You are going to need to save the coordinates (positions) of each segment of the snake. You will need to prepend a head and erase a tail segment. You will save the coordinates in a container.
There are many containers such as std::vector, std::list, std::stack and std::deque. I recommend std::deque. This allows you to push new segment coordinates into the back and pop the oldest segment from the top.
The std::deque structure allows growth too. You can push more items than you pop and also pop more than push (until the container is empty).
You can also do this the more difficult method and use an array or std::vector. You would erase the tail (using the coordinates at the end of the array), then move all the coordinates down (to make room for a new head coordinate), then set the first slot to the new coordinate.
Also, please invest some time with your debugger. Debugging your program is a lot faster than using StackOverflow to debug it. Most of us don't have the time to take your program, use a debugger, to find out where the issues are. If the issue is not obvious to most people in the first minute, your question is less likely to be answered (thus more downvotes).
Why are you making 3 programs. Here is how you do it. Make good use of OOP man !
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
bool gameOver;
const int width = 40;
const int height = 20;
int x, y, fruitX, fruitY, score;
int tailX[100], tailY[100];
int ntail;
enum edirecton { STOP = 0, LEFT, RIGHT, UP, DOWN };
edirecton 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 + 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 << endl;
cout << "Score= " << score << endl;
}
void 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;
}
}
}
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<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 == fruitX && y == fruitY)
{
score += 10;
fruitX = rand() % width;
fruitY = rand() % height;
ntail++;
}
}
int main()
{
Setup();
while (!gameOver)
{
Draw();
Input();
Logic();
Sleep(80);
}
return 0;
}