一个简单的 Tank C++ 游戏
A simple Tank C++ game
我现在对 c++ 有点陌生,我必须编写一个控制台 Tank 游戏。我自己做了很多部分,大部分部分都没有错。这是我的坦克 class:
class Tank {
protected:
string name;
static int number;
static int row;
static int col;
static char direction;
public:
Tank(int _number, string _name, int _row, int _col, char _direction){
this->name = _name;
this->number = _number;
setRow(_row);
setCol(_col);
setDirection(_direction);
}
///////////////////////////////
///----GETTERS FUNCTIONS----///
///////////////////////////////
char getdirection(){ return direction; }
int getnumber(){ return number; }
int getCol(){ return col; }
int getRow(){ return row; }
void setDirection(char _direction)
{
direction = _direction;
}
void setCol(int _col)
{
col = _col;
}
void setRow(int _row)
{
row = _row;
}
////////////////////////
///To String Function///
////////////////////////
string _toString(){
string r = "";
r = ("Tank No. " + toString(number + 1) + " " + name + " At (" + toString(row) + "," + toString(col) + ") " + direction);
return r;
}
};
int Tank::col = 0;
int Tank::row = 0;
int Tank::number = 0;
char Tank::direction = '[=10=]';
问题是当我创建对象数组时:
Tank *players[4];
因为我需要一个四人游戏和一个坦克对象,所以它只使用最后一个对象。这是我想在每个回合中使用的代码,让每个玩家说出他们将要做什么:
static char action;
static int turn = 1;
static Game game(*players, map);
for (int count = 0; players[count] != NULL; count++)
{
clr_screen();
gotoxy(100, 15); cout << "Turn " << turn;
gotoxy(100, 16); cout << "Player " << players[count]->getnumber() + 1 << " Action: ";
cin >> action;
game.move(action, count);
}
turn++;
如您所见,代码存在问题。
您可能想知道,这是游戏 class:
class Game{
private:
Tank *p_tank[5];
Map map;
public:
Game(Tank *tanks, Map _map)
{
*p_tank = tanks; map = _map;
}
//Tank getTank(){ return p_tank; }
Map getMap(){ return map; }
如果您需要此处的完整代码,它是:
#include <iostream>
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#include <fstream>
#include <sstream>
using namespace std;
void SetWindow(int Width, int Height)
{
_COORD coord;
coord.X = Width;
coord.Y = Height;
_SMALL_RECT Rect;
Rect.Top = 0;
Rect.Left = 0;
Rect.Bottom = Height - 1;
Rect.Right = Width - 1;
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); // Get Handle
SetConsoleScreenBufferSize(Handle, coord); // Set Buffer Size
SetConsoleWindowInfo(Handle, TRUE, &Rect); // Set Window Size
}
void gotoxy(int x, int y)
{
static HANDLE h = NULL;
if (!h)
h = GetStdHandle(STD_OUTPUT_HANDLE);
COORD c = { x, y };
SetConsoleCursorPosition(h, c);
}
string toString(int x) {
stringstream ss;
ss << x;
return ss.str();
}
class Tank {
protected:
string name;
static int number;
static int row;
static int col;
static char direction;
public:
Tank(int _number, string _name, int _row, int _col, char _direction){
this->name = _name;
this->number = _number;
setRow(_row);
setCol(_col);
setDirection(_direction);
}
///////////////////////////////
///----GETTERS FUNCTIONS----///
///////////////////////////////
char getdirection(){ return direction; }
int getnumber(){ return number; }
int getCol(){ return col; }
int getRow(){ return row; }
void setDirection(char _direction)
{
direction = _direction;
}
void setCol(int _col)
{
col = _col;
}
void setRow(int _row)
{
row = _row;
}
////////////////////////
///To String Function///
////////////////////////
string _toString(){
string r = "";
r = ("Tank No. " + toString(number + 1) + " " + name + " At (" + toString(row) + "," + toString(col) + ") " + direction);
return r;
}
};
int Tank::col = 0;
int Tank::row = 0;
int Tank::number = 0;
char Tank::direction = '[=14=]';
class Bullet : public Tank{
private:
Tank tank;
public:
Tank getTank(){ return tank; }
void setRow(int _row){ row = _row; }
void setCol(int _col){ col = _col; }
char getDirection(){ return direction; }
string __toString(){
string r = "";
r = ("Bullet At (" + toString(row) + "," + toString(col) + ") From Tank No " + toString(number));
return r;
}
};
class Block{//Characters: according to legends Lines: 316 - 322
protected:
int row;
int col;
char character;
public:
Block(char block)
{
this->character = block;
}
virtual string _toString(){
string r = "";
r = (character + (" at (" + toString(row) + toString(col) + "). "));
return r;
}
int getRow(){ return row; }
int getCol(){ return col; }
void setRow(int _row){ row = _row; }
void setCol(int _col) { row = _col; }
virtual char getCharacter() { return character; }
};
/*class Ground : public Block{
public:
Ground(){
character = '.';
Block block;
block.getCharacter();
}
};
class Wall : public Block{
public:
Wall(){
character = 'W';
Block block;
block.getCharacter();
}
};
class Box : public Block{
public:
Box(){
character = 'B';
Block block;
block.getCharacter();
}
};
class Ice : public Block{
public:
Ice(){
character = 'I';
Block block;
block.getCharacter();
}
};
class Trap : public Block{
public:
Trap(){
character = 'T';
Block block;
block.getCharacter();
}
};
class Random : public Block{
public:
Random(){
character = '?';
Block block;
block.getCharacter();
}
};
class Tblock : public Block{
public:
Tblock(){
character = 'T';
Block block;
block.getCharacter();
}
};*/
class Map{
private:
int rows;
int cols;
static const int MaxSize = 100;
Block *map[MaxSize][MaxSize];
public:
Map(int row = MaxSize, int col = MaxSize){
this->rows = row;
this->cols = col;
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++)
map[i][j] = new Block(' ');
}
}
void edit(int row, int col, char legend)
{
if (legend == '%')//bullet sign
map[row][col] = new Block('O');
else if (legend == '0')
map[row][col] = new Block('1');
else if (legend == '1')
map[row][col] = new Block('2');
else if (legend == '2')
map[row][col] = new Block('3');
else if (legend == '3')
map[row][col] = new Block('4');
else if (legend == 'G' || legend == 'g')
map[row][col] = new Block(' ');
else if (legend == 'w' || legend == 'W')
map[row][col] = new Block('W');
else if (legend == '?')
map[row][col] = new Block('?');
else if (legend == 'B' || legend == 'b')
map[row][col] = new Block('B');
else if (legend == 'X' || legend == 'x')
map[row][col] = new Block('X');
else if (legend == 'I' || legend == 'i')
map[row][col] = new Block('I');
else
map[row][col] = new Block('B');
_toGUI(row, col);
}
void _toGUI(int x, int y)
{
int X = 7 + 8 * x;
int Y = 6 + 4 * y;
gotoxy(X, Y);
cout << map[x][y]->getCharacter();
}
bool moveOk(int r, int c, char mov)
{
switch (mov)
{
case 'l':
if (r - 1 < 0) return false;
else return true;
break;
case 'r':
if (r > rows - 2) return false;
else return true;
break;
case 'd':
if (c < cols - 1) return true;
else return false;
break;
case 'u':
if (c > 0) return true;
else return false;
break;
}
}
int getRows(){ return cols; }
int getCols(){ return rows; }
};
class Game{
private:
Tank *p_tank[5];
Map map;
public:
Game(Tank *tanks, Map _map)
{
*p_tank = tanks; map = _map;
}
//Tank getTank(){ return p_tank; }
Map getMap(){ return map; }
void move(char move, int whoToPlay)
{
string wtp;
wtp = toString(whoToPlay);
int m_row, m_col;
switch (move)
{
case 'l':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'l')){
map.edit(m_row, m_col, 'G');
map.edit(--m_row, m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
case 'r':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'r')){
map.edit(m_row, m_col, 'G');
map.edit(++m_row, m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
case 'd':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'd')){
map.edit(m_row, m_col, 'G');
map.edit(m_row, ++m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
case 'u':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'u')){
map.edit(m_row, m_col, 'G');
map.edit(m_row, --m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
}
}
};
void draw_field(Map map)
{
////////////////////////
//-------Border-------//
////////////////////////
for (int i = 3; i <= 2 * (4 * map.getRows() + 3); i++)
{
gotoxy(i, 3);
printf("%c", 219);
gotoxy(i, (4 * map.getCols() + 7));
printf("%c", 219);
}
for (int i = 6; i < (4 * map.getCols() + 7); i++){
gotoxy(3, i);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), i);
printf("%c", 219);
}
gotoxy(3, 5);
printf("%c", 219);
gotoxy(3, 4);
printf("%c", 219);
gotoxy(3, 4 * map.getCols() + 7);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), 4);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), 5);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), map.getCols() + 7);
printf("%c", 219);
//end of BORDER
//****************\
//---COORD GUI----\
//****************\
//numbers:
int j = 1;
int z = 1;
for (int i = 8; i < 2 * (4 * map.getRows() + 3); i += 8)
{
gotoxy(i, 2); cout << j;
j++;
}
for (int i = 6; i < (4 * map.getCols() + 6); i += 4)
{
gotoxy(1, i);
cout << z;
z++;
}
//lines:
for (int j = 8; j < (4 * map.getCols() + 6); j += 4)
for (int i = 4; i < 2 * (4 * map.getRows() + 3); i++)
{
gotoxy(i, j);
cout << "-";
}
for (int j = 12, c = 0; c < 4 * map.getRows() / 4 - 1; j += 8, c++)
for (int i = 4, t = 0; t < 4 * map.getCols() + 1; i++, t++)
{
Sleep(10);
gotoxy(j, i);
cout << "|";
}
}
void clr_screen()
{
for (int i = 100; i <= 136; i++){
for (int j = 15; j <= 55; j++){
gotoxy(i, j); cout << " ";
}
}
}
void legend()
{
gotoxy(100, 2); cout << "Legends: ";
gotoxy(100, 4); cout << "Tanks: #\tBullet: *";
gotoxy(100, 5); cout << "Walls: W\tRandom: ?";
gotoxy(100, 6); cout << "Box: B\tIce: I";
gotoxy(100, 7); cout << "Trap: X\t";
gotoxy(100, 9); cout << "Actions:";
gotoxy(100, 10); cout << "U D L R\tFire: F";
gotoxy(100, 11); cout << "----------------------";
}
void action_display(string str, Map &map)
{
Tank *players[5];
char reply = 'n';
if (str == "%edit%" || str == "%Edit%"){
while (reply != 'y'){
char legend; int c; int r;
clr_screen();
gotoxy(100, 14);
cout << "Actions:";
gotoxy(100, 15);
cout << "Edit Section:";
gotoxy(100, 16); cout << "Enter the legend: ";
gotoxy(100, 17); cin >> legend;
if (legend == '1' || legend == '2' || legend == '3' || legend == '4')
legend = '!';
gotoxy(100, 18); cout << "Col: "; cin >> r;
gotoxy(100, 19); cout << "Row: "; cin >> c;
map.edit(r - 1, c - 1, legend);
gotoxy(100, 20); cout << "Done?(Y|N)"; cin >> reply;
}
}
if (str == "%NewGame%")
{
static int P;
string name;
int r, c;
clr_screen();
gotoxy(100, 15);
cout << "How many players?";
cin >> P;
if (P >= 4) P = 4;
for (int i = 0; i < P; i++)
{
clr_screen();
gotoxy(100, 16); cout << "Enter player " << i + 1 << " start: ";
gotoxy(100, 17); cout << "col: "; cin >> r;
gotoxy(100, 18); cout << "row: "; cin >> c;
gotoxy(100, 19); cout << "Name: "; cin >> name;
players[i] = new Tank(i, name, r, c, 'u');
string a;
a = toString(i);
map.edit(r - 1, c - 1, a[0]);
clr_screen();
gotoxy(100, 15); cout << players[i]->_toString();
_getch();
}
}
if (str == "%%MovementDuringGame%%")
{
static char action;
static int turn = 1;
static Game game(*players, map);
for (int count = 0; players[count] != NULL; count++)
{
clr_screen();
gotoxy(100, 15); cout << "Turn " << turn;
gotoxy(100, 16); cout << "Player " << players[count]->getnumber() + 1 << " Action: ";
cin >> action;
game.move(action, count);
}
turn++;
clr_screen();
}
}
void menu()
{
cout << "Welcome to Tank CPP Game.\n";
cout << "At first, Please Enter the field's Size.\n!!Attention!! We Recommend 10x10. Max Row Size: 11 and Max Column Size: 11\n\npress Any Key to continue...";
_getch();
int r; int c;
system("cls");
cout << "Row:"; cin >> r; cout << "Col:"; cin >> c;
if (r >= 11) r = 11;
if (c >= 11) c = 11;
SetWindow(138, 60);
system("cls");
Map map(r, c);
draw_field(map);
_getch();
clr_screen();
legend();
//**********************//
//****** Editing *******//
//**********************//
action_display("%edit%", map);
clr_screen();
/****************************
******GAME START-Players*****
****************************/
action_display("%NewGame%", map);
_getch();
/************************
******* MOVEMENTS *******
*************************/
while (1)
action_display("%%MovementDuringGame%%", map);
_getch();
}
void main()
{
menu();
}
这很危险:
for (int count = 0; players[count] != NULL; count++)
无法保证 players[4]
或原始数组之外的任何其他内存为 null,因为它可能被不同的东西使用或仅保存旧的和未初始化的内存值,导致您的程序意外继续并导致你遇到的问题。
改进:
- 将硬编码的玩家数量存储在常量中。
- 使用
sizeof
或 countof
function or macro 检索数组中的项目数
- 使用
std::vector
或类似的存储它持有的当前项目数的东西
*p_tank = tanks;
是失败的行,您应该告诉我们。
现在我可以告诉您如何解决这个问题,但您真的不应该使用原始指针和数组。当您使用 std::vector<Tank>
.
时,整个问题就消失了
我没有阅读完整的代码示例,但我注意到您正在使用静态成员变量来保存 类 状态。当然这是行不通的,因为如果你有多个对象,它们共享相同的数字、行、列和方向内存。这意味着如果您有一个 Tank 对象数组并且您只更改这些数组对象中的任何一个成员,它们都将被设置为完全相同的值。这意味着你的所有坦克总是在彼此之上,朝同一个方向看。可能有四个,但你只能看到其中一个。
我并不是说这就是问题所在,但这是您可能会考虑的问题。
我现在对 c++ 有点陌生,我必须编写一个控制台 Tank 游戏。我自己做了很多部分,大部分部分都没有错。这是我的坦克 class:
class Tank {
protected:
string name;
static int number;
static int row;
static int col;
static char direction;
public:
Tank(int _number, string _name, int _row, int _col, char _direction){
this->name = _name;
this->number = _number;
setRow(_row);
setCol(_col);
setDirection(_direction);
}
///////////////////////////////
///----GETTERS FUNCTIONS----///
///////////////////////////////
char getdirection(){ return direction; }
int getnumber(){ return number; }
int getCol(){ return col; }
int getRow(){ return row; }
void setDirection(char _direction)
{
direction = _direction;
}
void setCol(int _col)
{
col = _col;
}
void setRow(int _row)
{
row = _row;
}
////////////////////////
///To String Function///
////////////////////////
string _toString(){
string r = "";
r = ("Tank No. " + toString(number + 1) + " " + name + " At (" + toString(row) + "," + toString(col) + ") " + direction);
return r;
}
};
int Tank::col = 0;
int Tank::row = 0;
int Tank::number = 0;
char Tank::direction = '[=10=]';
问题是当我创建对象数组时:
Tank *players[4];
因为我需要一个四人游戏和一个坦克对象,所以它只使用最后一个对象。这是我想在每个回合中使用的代码,让每个玩家说出他们将要做什么:
static char action;
static int turn = 1;
static Game game(*players, map);
for (int count = 0; players[count] != NULL; count++)
{
clr_screen();
gotoxy(100, 15); cout << "Turn " << turn;
gotoxy(100, 16); cout << "Player " << players[count]->getnumber() + 1 << " Action: ";
cin >> action;
game.move(action, count);
}
turn++;
如您所见,代码存在问题。
您可能想知道,这是游戏 class:
class Game{
private:
Tank *p_tank[5];
Map map;
public:
Game(Tank *tanks, Map _map)
{
*p_tank = tanks; map = _map;
}
//Tank getTank(){ return p_tank; }
Map getMap(){ return map; }
如果您需要此处的完整代码,它是:
#include <iostream>
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#include <fstream>
#include <sstream>
using namespace std;
void SetWindow(int Width, int Height)
{
_COORD coord;
coord.X = Width;
coord.Y = Height;
_SMALL_RECT Rect;
Rect.Top = 0;
Rect.Left = 0;
Rect.Bottom = Height - 1;
Rect.Right = Width - 1;
HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE); // Get Handle
SetConsoleScreenBufferSize(Handle, coord); // Set Buffer Size
SetConsoleWindowInfo(Handle, TRUE, &Rect); // Set Window Size
}
void gotoxy(int x, int y)
{
static HANDLE h = NULL;
if (!h)
h = GetStdHandle(STD_OUTPUT_HANDLE);
COORD c = { x, y };
SetConsoleCursorPosition(h, c);
}
string toString(int x) {
stringstream ss;
ss << x;
return ss.str();
}
class Tank {
protected:
string name;
static int number;
static int row;
static int col;
static char direction;
public:
Tank(int _number, string _name, int _row, int _col, char _direction){
this->name = _name;
this->number = _number;
setRow(_row);
setCol(_col);
setDirection(_direction);
}
///////////////////////////////
///----GETTERS FUNCTIONS----///
///////////////////////////////
char getdirection(){ return direction; }
int getnumber(){ return number; }
int getCol(){ return col; }
int getRow(){ return row; }
void setDirection(char _direction)
{
direction = _direction;
}
void setCol(int _col)
{
col = _col;
}
void setRow(int _row)
{
row = _row;
}
////////////////////////
///To String Function///
////////////////////////
string _toString(){
string r = "";
r = ("Tank No. " + toString(number + 1) + " " + name + " At (" + toString(row) + "," + toString(col) + ") " + direction);
return r;
}
};
int Tank::col = 0;
int Tank::row = 0;
int Tank::number = 0;
char Tank::direction = '[=14=]';
class Bullet : public Tank{
private:
Tank tank;
public:
Tank getTank(){ return tank; }
void setRow(int _row){ row = _row; }
void setCol(int _col){ col = _col; }
char getDirection(){ return direction; }
string __toString(){
string r = "";
r = ("Bullet At (" + toString(row) + "," + toString(col) + ") From Tank No " + toString(number));
return r;
}
};
class Block{//Characters: according to legends Lines: 316 - 322
protected:
int row;
int col;
char character;
public:
Block(char block)
{
this->character = block;
}
virtual string _toString(){
string r = "";
r = (character + (" at (" + toString(row) + toString(col) + "). "));
return r;
}
int getRow(){ return row; }
int getCol(){ return col; }
void setRow(int _row){ row = _row; }
void setCol(int _col) { row = _col; }
virtual char getCharacter() { return character; }
};
/*class Ground : public Block{
public:
Ground(){
character = '.';
Block block;
block.getCharacter();
}
};
class Wall : public Block{
public:
Wall(){
character = 'W';
Block block;
block.getCharacter();
}
};
class Box : public Block{
public:
Box(){
character = 'B';
Block block;
block.getCharacter();
}
};
class Ice : public Block{
public:
Ice(){
character = 'I';
Block block;
block.getCharacter();
}
};
class Trap : public Block{
public:
Trap(){
character = 'T';
Block block;
block.getCharacter();
}
};
class Random : public Block{
public:
Random(){
character = '?';
Block block;
block.getCharacter();
}
};
class Tblock : public Block{
public:
Tblock(){
character = 'T';
Block block;
block.getCharacter();
}
};*/
class Map{
private:
int rows;
int cols;
static const int MaxSize = 100;
Block *map[MaxSize][MaxSize];
public:
Map(int row = MaxSize, int col = MaxSize){
this->rows = row;
this->cols = col;
for (int i = 0; i < row; i++){
for (int j = 0; j < col; j++)
map[i][j] = new Block(' ');
}
}
void edit(int row, int col, char legend)
{
if (legend == '%')//bullet sign
map[row][col] = new Block('O');
else if (legend == '0')
map[row][col] = new Block('1');
else if (legend == '1')
map[row][col] = new Block('2');
else if (legend == '2')
map[row][col] = new Block('3');
else if (legend == '3')
map[row][col] = new Block('4');
else if (legend == 'G' || legend == 'g')
map[row][col] = new Block(' ');
else if (legend == 'w' || legend == 'W')
map[row][col] = new Block('W');
else if (legend == '?')
map[row][col] = new Block('?');
else if (legend == 'B' || legend == 'b')
map[row][col] = new Block('B');
else if (legend == 'X' || legend == 'x')
map[row][col] = new Block('X');
else if (legend == 'I' || legend == 'i')
map[row][col] = new Block('I');
else
map[row][col] = new Block('B');
_toGUI(row, col);
}
void _toGUI(int x, int y)
{
int X = 7 + 8 * x;
int Y = 6 + 4 * y;
gotoxy(X, Y);
cout << map[x][y]->getCharacter();
}
bool moveOk(int r, int c, char mov)
{
switch (mov)
{
case 'l':
if (r - 1 < 0) return false;
else return true;
break;
case 'r':
if (r > rows - 2) return false;
else return true;
break;
case 'd':
if (c < cols - 1) return true;
else return false;
break;
case 'u':
if (c > 0) return true;
else return false;
break;
}
}
int getRows(){ return cols; }
int getCols(){ return rows; }
};
class Game{
private:
Tank *p_tank[5];
Map map;
public:
Game(Tank *tanks, Map _map)
{
*p_tank = tanks; map = _map;
}
//Tank getTank(){ return p_tank; }
Map getMap(){ return map; }
void move(char move, int whoToPlay)
{
string wtp;
wtp = toString(whoToPlay);
int m_row, m_col;
switch (move)
{
case 'l':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'l')){
map.edit(m_row, m_col, 'G');
map.edit(--m_row, m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
case 'r':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'r')){
map.edit(m_row, m_col, 'G');
map.edit(++m_row, m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
case 'd':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'd')){
map.edit(m_row, m_col, 'G');
map.edit(m_row, ++m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
case 'u':
m_row = p_tank[whoToPlay]->getRow() - 1;
m_col = p_tank[whoToPlay]->getCol() - 1;
if (map.moveOk(m_row, m_col, 'u')){
map.edit(m_row, m_col, 'G');
map.edit(m_row, --m_col, wtp[0]);
p_tank[whoToPlay]->setRow(m_row + 1);
p_tank[whoToPlay]->setCol(m_col + 1);
}
break;
}
}
};
void draw_field(Map map)
{
////////////////////////
//-------Border-------//
////////////////////////
for (int i = 3; i <= 2 * (4 * map.getRows() + 3); i++)
{
gotoxy(i, 3);
printf("%c", 219);
gotoxy(i, (4 * map.getCols() + 7));
printf("%c", 219);
}
for (int i = 6; i < (4 * map.getCols() + 7); i++){
gotoxy(3, i);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), i);
printf("%c", 219);
}
gotoxy(3, 5);
printf("%c", 219);
gotoxy(3, 4);
printf("%c", 219);
gotoxy(3, 4 * map.getCols() + 7);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), 4);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), 5);
printf("%c", 219);
gotoxy(2 * (4 * map.getRows() + 3), map.getCols() + 7);
printf("%c", 219);
//end of BORDER
//****************\
//---COORD GUI----\
//****************\
//numbers:
int j = 1;
int z = 1;
for (int i = 8; i < 2 * (4 * map.getRows() + 3); i += 8)
{
gotoxy(i, 2); cout << j;
j++;
}
for (int i = 6; i < (4 * map.getCols() + 6); i += 4)
{
gotoxy(1, i);
cout << z;
z++;
}
//lines:
for (int j = 8; j < (4 * map.getCols() + 6); j += 4)
for (int i = 4; i < 2 * (4 * map.getRows() + 3); i++)
{
gotoxy(i, j);
cout << "-";
}
for (int j = 12, c = 0; c < 4 * map.getRows() / 4 - 1; j += 8, c++)
for (int i = 4, t = 0; t < 4 * map.getCols() + 1; i++, t++)
{
Sleep(10);
gotoxy(j, i);
cout << "|";
}
}
void clr_screen()
{
for (int i = 100; i <= 136; i++){
for (int j = 15; j <= 55; j++){
gotoxy(i, j); cout << " ";
}
}
}
void legend()
{
gotoxy(100, 2); cout << "Legends: ";
gotoxy(100, 4); cout << "Tanks: #\tBullet: *";
gotoxy(100, 5); cout << "Walls: W\tRandom: ?";
gotoxy(100, 6); cout << "Box: B\tIce: I";
gotoxy(100, 7); cout << "Trap: X\t";
gotoxy(100, 9); cout << "Actions:";
gotoxy(100, 10); cout << "U D L R\tFire: F";
gotoxy(100, 11); cout << "----------------------";
}
void action_display(string str, Map &map)
{
Tank *players[5];
char reply = 'n';
if (str == "%edit%" || str == "%Edit%"){
while (reply != 'y'){
char legend; int c; int r;
clr_screen();
gotoxy(100, 14);
cout << "Actions:";
gotoxy(100, 15);
cout << "Edit Section:";
gotoxy(100, 16); cout << "Enter the legend: ";
gotoxy(100, 17); cin >> legend;
if (legend == '1' || legend == '2' || legend == '3' || legend == '4')
legend = '!';
gotoxy(100, 18); cout << "Col: "; cin >> r;
gotoxy(100, 19); cout << "Row: "; cin >> c;
map.edit(r - 1, c - 1, legend);
gotoxy(100, 20); cout << "Done?(Y|N)"; cin >> reply;
}
}
if (str == "%NewGame%")
{
static int P;
string name;
int r, c;
clr_screen();
gotoxy(100, 15);
cout << "How many players?";
cin >> P;
if (P >= 4) P = 4;
for (int i = 0; i < P; i++)
{
clr_screen();
gotoxy(100, 16); cout << "Enter player " << i + 1 << " start: ";
gotoxy(100, 17); cout << "col: "; cin >> r;
gotoxy(100, 18); cout << "row: "; cin >> c;
gotoxy(100, 19); cout << "Name: "; cin >> name;
players[i] = new Tank(i, name, r, c, 'u');
string a;
a = toString(i);
map.edit(r - 1, c - 1, a[0]);
clr_screen();
gotoxy(100, 15); cout << players[i]->_toString();
_getch();
}
}
if (str == "%%MovementDuringGame%%")
{
static char action;
static int turn = 1;
static Game game(*players, map);
for (int count = 0; players[count] != NULL; count++)
{
clr_screen();
gotoxy(100, 15); cout << "Turn " << turn;
gotoxy(100, 16); cout << "Player " << players[count]->getnumber() + 1 << " Action: ";
cin >> action;
game.move(action, count);
}
turn++;
clr_screen();
}
}
void menu()
{
cout << "Welcome to Tank CPP Game.\n";
cout << "At first, Please Enter the field's Size.\n!!Attention!! We Recommend 10x10. Max Row Size: 11 and Max Column Size: 11\n\npress Any Key to continue...";
_getch();
int r; int c;
system("cls");
cout << "Row:"; cin >> r; cout << "Col:"; cin >> c;
if (r >= 11) r = 11;
if (c >= 11) c = 11;
SetWindow(138, 60);
system("cls");
Map map(r, c);
draw_field(map);
_getch();
clr_screen();
legend();
//**********************//
//****** Editing *******//
//**********************//
action_display("%edit%", map);
clr_screen();
/****************************
******GAME START-Players*****
****************************/
action_display("%NewGame%", map);
_getch();
/************************
******* MOVEMENTS *******
*************************/
while (1)
action_display("%%MovementDuringGame%%", map);
_getch();
}
void main()
{
menu();
}
这很危险:
for (int count = 0; players[count] != NULL; count++)
无法保证 players[4]
或原始数组之外的任何其他内存为 null,因为它可能被不同的东西使用或仅保存旧的和未初始化的内存值,导致您的程序意外继续并导致你遇到的问题。
改进:
- 将硬编码的玩家数量存储在常量中。
- 使用
sizeof
或countof
function or macro 检索数组中的项目数
- 使用
std::vector
或类似的存储它持有的当前项目数的东西
*p_tank = tanks;
是失败的行,您应该告诉我们。
现在我可以告诉您如何解决这个问题,但您真的不应该使用原始指针和数组。当您使用 std::vector<Tank>
.
我没有阅读完整的代码示例,但我注意到您正在使用静态成员变量来保存 类 状态。当然这是行不通的,因为如果你有多个对象,它们共享相同的数字、行、列和方向内存。这意味着如果您有一个 Tank 对象数组并且您只更改这些数组对象中的任何一个成员,它们都将被设置为完全相同的值。这意味着你的所有坦克总是在彼此之上,朝同一个方向看。可能有四个,但你只能看到其中一个。
我并不是说这就是问题所在,但这是您可能会考虑的问题。