создал структуру, скомпилировал мою программу, работал отлично, ничего не изменил, закрыл vm, перезапустил vm и vs c, а затем снова сделал make в консоли и обнаружил эту ошибку
1 warning generated.
linking build/main.o
build/Game.o:(.bss+0x60): multiple definition of `scoreArray'
build/main.o:(.bss+0x10): first defined here
clang-5.0: error: linker command failed with exit code 1 (use -v to see
invocation)
Makefile:33: recipe for target 'build/2048' failed
make: *** [build/2048] Error 1
Вот мой код, я не вижу ничего, что переопределяет его, пожалуйста, кто-нибудь определит его для меня, вот файл заголовка и исходный файл, который использовался в
main. cpp
/**
* File: main.cpp
* Author: not lettin u know :)
* Date: 20-11-2019
* Desc:
* Copyright: University of West of England 2017
*/
#include <stdio.h>
#include <cstdio>
#include <stdlib.h>
// include the UFCFGL301's standard library
#include <ufcfgl-30-1.h>
#include <iostream>
#include <time.h>
#include "Grid.h"
#include "Game.h"
// uncomment if you want to use the graphics library
#include <graphics.h>
using namespace std;
using namespace uwe;
/**
* main routine, implements ...
* @return success
*/
int main(void) {
srand(time(0));
Game game;
// -------Initialising Game-------
while(1){
game.chooseFunction();
grid.totalScore = 0;
grid.initGrid();
grid.addValue();
cout << "\033[2J"; // this clears the terminal
cout << "\nPlayer Score : " << grid.totalScore << "\n";
std::cout << "\nMoves = " << grid.moves << "\n\nlast input = N/A \n";
grid.setScore(grid.score);
grid.drawGrid();
// This launches graphics window where all keypresses are inputted
// this is also where we start the lambda functions in a loop
initialiseGraphics(600,400);
loop (
[&](){
},
[&](keyPress keyPress){
// w a s d are also inputted into an integer as their respective ascii value
// so this allows the use of w a s d and also the arrow keys in controlling
// the moves of the player
int kpVal = keyPress.getKeyCode();
if ( kpVal == 'q' ){
return true;
}
if ( kpVal == 'w' || kpVal == keyPress::upKey ){
cout << "\033[2J"; // this clears the terminal
grid.shiftUp();
cout << "Player Score : " << grid.totalScore << "\n";
std::cout << "\nMoves = " << grid.moves
<< "\n\nlast input = UP \n";
grid.setScore(grid.score);
grid.drawGrid();
game.checkGameState();
if(game.gameFinished == true){
return true;
}
}
if ( kpVal == 'a' || kpVal == keyPress::leftKey ){
cout << "\033[2J"; // this clears the terminal
grid.shiftLeft();
cout << "Player Score : " << grid.totalScore << "\n";
std::cout << "\nMoves = " << grid.moves
<< "\n\nlast input = LEFT \n";
grid.setScore(grid.score);
grid.drawGrid();
game.checkGameState();
if(game.gameFinished == true){
return true;
}
}
if ( kpVal == 's' || kpVal == keyPress::downKey ){
cout << "\033[2J"; // this clears the terminal
grid.shiftDown();
cout << "Player Score : " << grid.totalScore << "\n";
std::cout << "\nMoves = " << grid.moves
<< "\n\nlast input = DOWN \n";
grid.setScore(grid.score);
grid.drawGrid();
game.checkGameState();
if(game.gameFinished == true){
return true;
}
}
if ( kpVal == 'd' || kpVal == keyPress::rightKey ){
cout << "\033[2J"; // this clears the terminal
grid.shiftRight();
cout << "Player Score : " << grid.totalScore << "\n";
std::cout << "\nMoves = " << grid.moves
<< "\n\nlast input = RIGHT \n";
grid.setScore(grid.score);
grid.drawGrid();
game.checkGameState();
if(game.gameFinished == true){
return true;
}
}
return false;
}
);
}
}
Game.h
#pragma once
#include <cstdio>
#include <string>
#include <graphics.h>
#include "Grid.h"
class Game{
public:
bool canMove();
bool checkWin();
bool checkLoss();
void checkGameState();
void chooseFunction();
void printHighScores();
void writeHighScore();
bool gameFinished = false;
private:
};
extern Game game;
struct highScore {
int score;
std::string name;
};
Игра. cpp
#include "Grid.h"
#include "Game.h"
#include <sstream>
#include <unistd.h>
#include <iostream>
#include <cstdio>
#include <graphics.h>
#include <fstream>
#include <string>
#include <algorithm> //std::sort for array of structs sorting based on struct
// integer
Grid grid;
highScore scoreArray[100];
// functions to check game state for win or loss or can make moves
bool Game::canMove(){
bool canMove = false;
for(int x = 0; x < Grid::tilesWide; x++){
for(int y = 0; y < Grid::tilesHigh; y++){
if (grid.grid[x][y] == Grid::emptyCell) {
canMove = true;
return canMove;
}
// multiple if statements due to if grid[3][1] was being checked with
// grid[3+1][1] then it would loop around and check against grid[1][2]
// for an unknown reason, so to combat this i had to check specifically against
// the edge of the board
else if(y == 3 && x < 3){
if( grid.grid[x][y] == grid.grid[x+1][y] ){
canMove = true;
return canMove;
}
}
else if(x == 3 && y < 3){
if( grid.grid[x][y] == grid.grid[x][y+1] ){
canMove = true;
return canMove;
}
}
else if( ( x < 3 && y < 3 ) &&
(grid.grid[x][y] == grid.grid[x][y+1] ||
grid.grid[x][y] == grid.grid[x+1][y]) ) {
canMove = true;
return canMove;
}
}
}
return canMove;
}
bool Game::checkWin(){
bool win = false;
for(int x = 0; x < Grid::tilesWide; x++){
for(int y = 0; y < Grid::tilesHigh; y++){
if(grid.grid[x][y] == 2048){
win = true;
return win;
}
}
}
return win;
}
bool Game::checkLoss(){
bool loss = false;
if(canMove() == false ){
loss = true;
return loss;
}
return loss;
}
void Game::checkGameState(){
if(checkWin() == true) {
std::cout << "\n\n--------YOU WIN--------\n\n";
gameFinished = true;
writeHighScore();
}
else if(checkLoss() == true) {
std::cout << "\n\n--------YOU LOSE--------\n\n";
gameFinished = true;
}
}
// functions for initializing game/options
void Game::chooseFunction(){
while(1){
int function = 0;
std::cout << "\nPlease Choose A Function\n1) Play Game\n2) High Scores"
<< "\n3) Exit Program";
std::cout << "\nFunction : ";
std::cin >> function;
if (std::cin.fail() || function < 1 || function > 3) {
std::cin.clear();
std::cin.ignore(1000,'\n'); // this is to stop the validation from
// looping for each wrong character entered
std::cout << "Not a valid option, Please re-enter \n\n" ;
sleep(1);
}
else if (function == 1) {
std::cout << "------Launching Game------\n\n";
std::cout << "---------LOADING---------\n";
for(int x=0;x < 5;x++){
std::cout << "|||||" << std::flush;
sleep(1);
}
return ;
}
else if (function == 2) {
std::cout << "---Printing High Scores---\n";
std::cout << "---------LOADING---------\n";
for(int x=0;x < 5;x++){
std::cout << "|||||" << std::flush;
sleep(1);
}
printHighScores();
sleep(10);
}
else if (function == 3) {
std::cout << "-------Now Exiting------- \n\n" << std::flush ;
std::cout << "---------LOADING---------\n";
for(int x=0;x < 5;x++){
std::cout << "|||||" << std::flush;
sleep(1);
}
exit(0);
}
}
}
// This function is called upon a win, and writes the high score ,of those who
// win the game, into a text file under the format of SCORE - NAME
void Game::writeHighScore(){
std::string name;
std::cout << "\nEnter Name To Store High Score ( Max 16 Characters )\n"
<< "Name : ";
std::getline(std::cin,name);
// this is to stop the string being over 16 characters
if(std::cin.fail() || name.length() > 16){
std::cout << "\n\nPlease Enter A Max of 16 Characters\n\n";
writeHighScore();
return;
}
else{
// This opens the output stream to the high scores text file
// and immediately points to the next free line in the file
std::ofstream HighScore;
HighScore.open ("HighScores.txt", std::ios::app);
HighScore << grid.totalScore << " "<< name << std::endl;
HighScore.close();
return;
}
}
// simple comparator function to be used with std::sort in order to sort
// the array of structs containing scores and their respective player names
bool sortScore(highScore a,highScore b){
return a.score > b.score;
}
// this function prints the high scores from the text file, however
// im not sure how to sort a text file each time its appended, so instead
// when this function is called, it seperates the lines of the files into
// the score and their respective player name, these are stored in a struct
// object for each line, and then the array of structs is sorted using
// std::sort and the comparator function and then the first 10 scores and names
// in the struct array are printed, TLDR, prints Top 10 scores :)
//
// not on the spec for the assignment but i enjoyed learning about how
// i would go about making something like this :)
void Game::printHighScores() { // function to choose and print ascii art
std::ifstream highScores;
highScores.open("HighScores.txt");
std::string line;
int i=0;
if(!highScores){
std::cout << "\nCould Not Open HighScores.txt";
sleep(2);
return;
}
else{
while(getline(highScores, line)){
std::istringstream iss(line);
int score;
std::string name;
// this seperates out the score and the name string from each line in the file
if(!(iss >> score && iss.ignore() && std::getline(iss,name))){
break;
}
// this adds to the array of structs defined in the header file
scoreArray[i].score = score;
scoreArray[i].name = name;
i++;
}
std::sort(&scoreArray[0],&scoreArray[100],sortScore);
}
// and finally... this prints the top 10 scores
std::cout << "\n\n-------HIGH SCORES-------\n\n";
for(int i=0; i<10; i++){
std::cout <<i+1<<") "<<scoreArray[i].score<<" - "<<scoreArray[i].name
<<"\n";
}
}