试图用C ++制作2048,我刚刚在Game.cpp中添加了一个功能,该功能可以检查4x4网格的游戏状态,并显示游戏仍在进行中或根据赢或输而结束,
不确定发生了什么,但是我从编译器收到有关多个声明或多个定义的错误,但是我对错误的位置感到困惑,如果有人可以解决它,或解释如何理解编译器错误,以便自己亲自解决(即错误在哪里,其指向何处等),我将不胜感激。
用于编译的文件位于底部(由我的uni提供)
这是控制台中的错误
compiling main.cpp
In file included from main.cpp:15:
In file included from ./Grid.h:4:
In file included from ../../include/graphics.h:28:
In file included from ../../include/graphics_internal.h:18:
In file included from ../../include/juce/JuceHeader.h:23:
In file included from ../../3rdparty/JUCE/modules/juce_cryptography/juce_cryptography.h:60:
../../3rdparty/JUCE/modules/juce_cryptography/encryption/juce_BlowFish.h:100:10: warning:
mangled name of 'apply' will change in C++17 due to non-throwing exception
specification in function signature [-Wc++17-compat-mangling]
bool apply (void*, size_t, void (BlowFish::*op) (uint32&, uint32&) const noexc...
^
1 warning generated.
linking build/main.o
build/Game.o:(.bss+0x4): multiple definition of `grid'
build/main.o:(.bss+0x4): 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: nice try ;)
* 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) {
int c = 0;
srand(time(0));
Grid grid = Grid();
Game game = Game();
cout << "\033[2J"; // this clears the terminal
cout << "Player Score : " << grid.totalScore << "\n";
grid.addValue();
grid.drawGrid();
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){
grid.shiftUp();
grid.setScore(grid.score);
cout << "\033[2J"; // this clears the terminal
cout << "Player Score : " << grid.totalScore << "\n";
grid.drawGrid();
game.checkGameState();
}
if ( kpVal == 'a' || kpVal == keyPress::leftKey){
grid.shiftLeft();
grid.setScore(grid.score);
cout << "\033[2J";
cout << "Player Score : " << grid.totalScore << "\n";
grid.drawGrid();
game.checkGameState();
}
if ( kpVal == 's' || kpVal == keyPress::downKey){
grid.shiftDown();
grid.setScore(grid.score);
cout << "\033[2J";
cout << "Player Score : " << grid.totalScore << "\n";
grid.drawGrid();
game.checkGameState();
}
if ( kpVal == 'd' || kpVal == keyPress::rightKey){
grid.shiftRight();
grid.setScore(grid.score);
cout << "\033[2J";
cout << "Player Score : " << grid.totalScore << "\n";
grid.drawGrid();
game.checkGameState();
}
return false;
}
);
}
Grid.cpp
#include "Grid.h"
#include <iostream>
#include <cstdio>
#include <string>
#include <graphics.h>
// this empties the board from left to right and top to bottom
// and sets each value to 0
Grid::Grid(){
for(int x = 0; x < tilesWide; x++){
for(int y = 0; y < tilesHigh; y++){
grid[x][y] = emptyCell;
didMove = true;
}
}
}
// draws the current grid with lines inbetween ( ascii 4x4 grid essentially )
void Grid::drawGrid(){
std::cout << "--------------------" << '\n';
for(int y = 0; y < tilesWide ; y++){
for(int x = 0;x < tilesHigh; x++){
std::cout << "| " << grid[x][y] << " |";
}
std::cout << '\n' << "--------------------" << '\n';
}
}
// function to set the score
void Grid::setScore(int score){
totalScore = totalScore + score;
}
// this function adds a 2 or a 4 to a random empty tile
void Grid::addValue(){
int value = Grid::randValue();
while(true){
int valX = rand() % tilesWide;
int valY = rand() % tilesHigh;
if (grid[valX][valY] == 0) {
// this if statement checking a boolean is so that a tile is only added if
// a tile has been moved or merged, so that if you press a key and nothing
// happened, it will not add a tile causing you to choose a different direction
// to move
if(didMove == true){
grid[valX][valY] = value;
didMove = false;
break;
}
else{
printf("DID NOT MOVE \n");
break;
}
}
}
}
// this function generates a 2 or a 4 and returns it to the addValue function
int Grid::randValue(){
int randVal = rand() % 10;
// 90% chance of spawning a 2, same probability as the original source code
if(randVal < 9){
return 2;
}
else{
return 4;
}
}
// this function is so that the value of grid[x][y] can be checked in another
// source file ( in this case in game.cpp for game state check) as using
// grid[x][y] was not recognised
int Grid::gridValue(int x, int y){
return grid[x][y];
}
//-----------------------------TILE MOVEMENT----------------------------------//
// this packs and merges all the tiles up to the top of the board if there is
// space
// up // down // left // right // order of functions
void Grid::shiftUp(){
moveUp();
mergeUp();
moveUp();
addValue();
}
void Grid::shiftDown(){
moveDown();
mergeDown();
moveDown();
addValue();
}
void Grid::shiftLeft(){
moveLeft();
mergeLeft();
moveLeft();
addValue();
}
void Grid::shiftRight(){
moveRight();
mergeRight();
moveRight();
addValue();
}
// functions to move and merge upwards
void Grid::moveUp(){
for(int x = 0; x < tilesWide; x++){
for(int y = 0; y < tilesHigh; y++){
if( grid[x][y] == emptyCell){
for(int t = y+1; t < tilesWide; t++){
if(grid[x][t] != emptyCell){
grid[x][y] = grid[x][t];
grid[x][t] = emptyCell;
didMove = true;
break;
}
}
}
}
}
}
void Grid::mergeUp(){
for(int x = 0; x < tilesWide; x++){
for(int y = 0; y < tilesHigh-1; y++){
if(grid[x][y] == grid[x][y+1]){
grid[x][y] = ( grid[x][y] *2);
grid[x][y+1] = emptyCell;
setScore(grid[x][y]);
didMove = true;
}
}
}
}
// functions to move and merge downwards
void Grid::moveDown(){
for(int x = 0; x < tilesWide; x++){
for(int y = tilesHigh - 1; y > 0 ; y--){
if( grid[x][y] == emptyCell){
for(int t = y-1; t >= 0; t--){
if(grid[x][t] != emptyCell){
grid[x][y] = grid[x][t];
grid[x][t] = emptyCell;
didMove = true;
break;
}
}
}
}
}
}
void Grid::mergeDown(){
for(int x = 0; x < tilesWide; x++){
for(int y = tilesHigh-1; y > 0; y--){
if(grid[x][y] == grid[x][y-1]){
grid[x][y] = (grid[x][y] *2);
grid[x][y-1] = emptyCell;
setScore(grid[x][y]);
didMove = true;
}
}
}
}
// functions to move and merge to the left
void Grid::moveLeft(){
for(int x = 0; x < tilesWide; x++){
for(int y = 0; y < tilesHigh; y++){
if( grid[x][y] == emptyCell){
for(int t = x+1; t < tilesHigh; t++){
if(grid[t][y] != emptyCell){
grid[x][y] = grid[t][y];
grid[t][y] = emptyCell;
didMove = true;
break;
}
}
}
}
}
}
void Grid::mergeLeft(){
for(int x = 0; x < tilesWide-1; x++){
for(int y = 0; y < tilesHigh; y++){
if(grid[x][y] == grid[x+1][y]){
grid[x][y] = (grid[x][y] *2);
grid[x+1][y] = emptyCell;
setScore(grid[x][y]);
didMove = true;
}
}
}
}
// functions to move and merge to the right
void Grid::moveRight(){
for(int x = tilesWide - 1; x >= 0; x--){
for(int y = 0; y < tilesHigh; y++){
if( grid[x][y] == emptyCell){
for(int t = x-1; t >= 0; t--){
if(grid[t][y] != emptyCell){
grid[x][y] = grid[t][y];
grid[t][y] = emptyCell;
didMove = true;
break;
}
}
}
}
}
}
void Grid::mergeRight(){
for(int x = tilesWide - 1; x > 0; x--){
for(int y = 0; y < tilesHigh; y++){
if(grid[x][y] == grid[x-1][y]){
grid[x][y] = (grid[x][y] *2);
grid[x-1][y] = emptyCell;
setScore(grid[x][y]);
didMove = true;
}
}
}
}
Grid.h
#pragma once
#include <cstdio>
#include <string>
#include <graphics.h>
class Grid {
public:
Grid();
// defining functions for processing user input into various moves on the board
void drawGrid();
int randValue();
void addValue();
void moveLeft();
void mergeLeft();
void moveRight();
void mergeRight();
void moveUp();
void mergeUp();
void moveDown();
void mergeDown();
void shiftUp();
void shiftDown();
void shiftLeft();
void shiftRight();
int gridValue(int x, int y);
static const int tilesWide = 4;
static const int tilesHigh = 4;
bool didMove;
int grid[tilesWide][tilesHigh];
int score = 0;
int totalScore = 0;
void setScore(int score);
static const int emptyCell = 0;
private :
};
Game.cpp
#include "Game.h"
#include <iostream>
#include <cstdio>
#include <string>
#include <graphics.h>
Game::Game(){}
bool canMove(){
bool canMove = false;
for(int x = 0; x < Grid::tilesWide; x++){
for(int y = 0; y < Grid::tilesHigh; x++){
if (grid.gridValue(x,y) == Grid::emptyCell) {
canMove = true;
return canMove;
}
else if(grid.gridValue(x,y) == grid.gridValue(x,y+1) ||
grid.gridValue(x,y) == grid.gridValue(x+1,y) ) {
canMove = true;
return canMove;
}
}
}
return canMove;
}
bool checkWin(){
bool win = false;
for(int x = 0; x < Grid::tilesWide; x++){
for(int y = 0; y < Grid::tilesHigh; x++){
if(grid.gridValue(x,y) == 2048){
win = true;
}
}
}
return win;
}
bool checkLoss(){
bool loss = false;
if(canMove() == false ){
loss = true;
}
return loss;
}
void checkGameState(){
if(checkWin() == true) {
std::cout << "YOU WIN";
exit(1);
}
else if(checkLoss() == true) {
std::cout << "YOU LOSE";
exit(1);
}
}
Game.h
#pragma once
#include "Grid.h"
#include <cstdio>
#include <string>
#include <graphics.h>
Grid grid;
class Game{
public:
Game();
bool canMove();
bool checkWin();
bool checkLoss();
void checkGameState();
private:
};
MakeFile
# File: Makefile
# Author: again, nice try ;)
# Date: 20-11-2019
#
# Copyright: University of West of England 2017
#
ifeq ($(origin ROOTDIR), undefined)
ROOTDIR=../..
endif
include $(ROOTDIR)/MakefileDefs.inc
# Build path
BUILD_DIR = build
TARGET = 2048
CPP_SOURCES = main.cpp Grid.cpp Game.cpp
#######################################
# build the application
#######################################
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o)))
vpath %.cpp $(sort $(dir $(CPP_SOURCES)))
CFLAGS += -I$(INCDIR) -I$(JUCEINSTALL)/modules
LIBS = $(LIBDIR)/libgraphics.a $(JUCELIB) $(LIBDIR)/libufcfgl-30-1.a
$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
$(ECHO) compiling $<
$(CC) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET): $(OBJECTS) $(LIBS) Makefile
$(ECHO) linking $<
$(CC) $(OBJECTS) $(LIBS) $(LINUXLIBFALGS) $(LDFLAGS) -o $@
$(ECHO) success
$(BUILD_DIR):
mkdir -p $@
#######################################
# install
#######################################
install:
#######################################
# clean up
#######################################
clean:
-rm -fR .dep $(BUILD_DIR)
#######################################
# dependencies
#######################################
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
.PHONY: clean all