Reputation: 1
I have a problem with my game battleship, more precisely with the entry treatment. If I selecting coordinates in my array for shooting(X = first coordinate, Y = second coordinate) so I can select the same coordinates in array more times and I wanna repair it. I mean I want to select specific coordinates(array index) just one time and not more times.
Thank you for help.
There is a code: Sorry if I wrongly entered code on forum.
namespace Battleship
{
class Program
{
static void Main(string[] args)
{
string continue = "yes";
while (continue == "yes")
{
Console.WriteLine();
Console.WriteLine("----Battleship-----");
Console.WriteLine();
Console.WriteLine("Your name");
string jmeno = Console.ReadLine();
Console.WriteLine();
Console.WriteLine("Hit left 7x");
Console.WriteLine();
Hodnoty h = new Hodnoty();
while (h.Trefa < 7)
{
h.Zadej();
}
Console.Clear();
Console.WriteLine(name + " won!!!");
Console.WriteLine();
Console.WriteLine(name + " se trefil/a " + h.Trefa + "x");
Console.WriteLine(name + " miss " + h.Vedle + "x");
Console.WriteLine("Do you wanna play again? [yes/no]");
pokracovat = Console.ReadLine();
}
Console.Clear();
Console.WriteLine("Click on Enter");
Console.ReadLine();
}
class Hodnoty
{
public int Hit = 0;
public int left = 0;
int left = 0;
int x = 0;
int y = 0;
string cislo;
int hodnota;
//MAIN PROBLEM (I Guess)
//------------------------------------------------------------------------------
public void Zadej() /
{
var mapa = new char[5, 5];
using (var reader = new StreamReader("Lode.txt"))
{
Console.WriteLine(" ¦ 01234");
Console.WriteLine(" ¦----------");
for (var i = 0; i < 5; i++)
{
Console.Write((i).ToString() + " ¦ ");
var pole = reader.ReadLine();
for (var j = 0; j < 5; j++)
{
mapa[i, j] = char.Parse(pole[j].ToString());
}
Console.WriteLine();
}
}
Console.WriteLine();
Console.Write("Enter coordinates X = ");
cislo = Console.ReadLine();
if (int.TryParse(cislo, out hodnota))
{
x = hodnota;
}
else
{
Console.WriteLine("Enter number");
}
Console.Write("Enter bumber Y = ");
cislo = Console.ReadLine();
if (int.TryParse(cislo, out hodnota))
{
y = hodnota;
}
else
{
Console.WriteLine("Enter number");
}
if (mapa[x, y].Equals('X'))
{
Console.Clear();
Console.WriteLine("-----Battleship-----");
Console.WriteLine();
Trefa += 1;
Zbyva = 7 - Trefa;
Console.WriteLine("Hit " + Hit + "x ");
Console.WriteLine();
Console.WriteLine("hits left " + left + "x");
Console.WriteLine();
}
else
{
Console.Clear();
Console.WriteLine("-----Battleship-----");
Console.WriteLine();
Vedle += 1;
Console.WriteLine("Miss " + Miss + "x ");
Console.WriteLine();
Console.WriteLine("hits left " + left + "x");
Console.WriteLine();
}
}
}
}
}
Problem:
I mean.. I can enter the same coordinate just one time and not more times.
Upvotes: 0
Views: 89
Reputation: 29244
You are either asking how to prevent the user from playing the same coordinates twice, or you are asking how to enter the coordinates using one ReadLine()
statement instead of two.
I will answer the second first:
Here is a simple loop where the user inputs two values and the system parses the string into two integers x
and y
. This continues until the user presses enter. The trick is to split the input at the comma ,
generating an array of strings. "5,3" => ["5","3"]
.
do
{
int x, y;
Console.WriteLine("Enter Hit Coordinates (x,y):");
var input = Console.ReadLine();
var parts = input.Split(',');
if (parts.Length!=2)
{
Console.WriteLine("Please enter two values separated by a comma.");
break;
}
if (int.TryParse(parts[0].Trim(), out x) && int.TryParse(parts[1].Trim(), out y))
{
// use the x, y values below
Console.WriteLine($"User input was: ({x},{y})");
}
else
{
Console.WriteLine("Please enter numeric values.");
}
}
while (true);
The first question is handled easier if you keep track of the previous input coordinates and compare the current input to previous ones. One way of doing this is to keep a list of (x,y)
values as a Tuple
.
var history = new List<(int x,int y)>();
and populate it for every input after checking for existing values with .Contains()
var history = new List<(int x, int y)>();
do
{
Console.WriteLine("Enter Hit Coordinates (x,y):");
var input = Console.ReadLine();
var parts = input.Split(',');
if (parts.Length!=2)
{
Console.WriteLine("Please enter two values separated by a comma.");
break;
}
if (int.TryParse(parts[0].Trim(), out int x) && int.TryParse(parts[1].Trim(), out int y))
{
var coords = (x, y);
if (history.Contains(coords))
{
Console.WriteLine($"Coordinates ({x},{y}) Previously Played.");
}
else
{
// use the x, y values below
Console.WriteLine($"User input was: ({x},{y})");
history.Add(coords);
}
}
else
{
Console.WriteLine("Please enter numeric values.");
}
}
while (true);
Upvotes: 1
Reputation: 3455
if you don't want to shoot twice on the same map-tile, you have to remember, what happended there. You're using char
a status-marker. I'd suggest to use a enum:
public enum MapStatus
{
Empty = 0,
Ship = 1,
HitShip = 2,
HitWater = 3
}
Your map will be something like this:
MapStatus[,] mapTiles;
But we have set int-values to the enum-values. because of this we can convert them:
map[0,0] = (MapStatus)1; // This will set a ship to 1/1
Now you've to check every time you shoot if there is water etc.
In addition you should move your logic to a class "map" or something.
Well.. this escalated quickly: Here a complete example:
public enum MapStatus
{
Empty = 0,
Ship = 1,
HitShip = 2,
HitWater = 3
}
public class Map
{
MapStatus[,] mapTiles;
public Map(int[,] mapInt = null)
{
if (mapInt == null) // if there's no map in parameters we'll set a default map..
{
mapInt = new int[,]
{
{ 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 1 }, // in this row there's a ship
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
};
}
// Initialize empty map
mapTiles = new MapStatus[mapInt.GetLength(0), mapInt.GetLength(1)];
// copy numbers into our map
for (int i = 0; i < mapTiles.GetLength(0); i++)
{
for (int j = 0; j < mapTiles.GetLength(1); j++)
{
mapTiles[i, j] = (MapStatus)mapInt[i, j];
}
}
}
/// <summary>
/// "Graphics-Engine" which enables us to print our map.
/// </summary>
public void PrintMap()
{
Console.Clear();
Console.Write(" ");
for (int j = 0; j < mapTiles.GetLength(1); j++)
{
Console.Write(j.ToString().PadLeft(8));
}
Console.WriteLine();
for (int i = 0; i < mapTiles.GetLength(0); i++)
{
Console.Write(i.ToString().PadLeft(8));
for (int j = 0; j < mapTiles.GetLength(1); j++)
{
Console.Write(mapTiles[i, j].ToString().PadLeft(8) + " ");
}
Console.WriteLine();
}
}
/// <summary>
/// Check if there are ships left. Have a look at Linq ;)
/// </summary>
public bool StillAlive()
{
return mapTiles.Cast<MapStatus>().Any(a => a == MapStatus.Ship);
}
public bool Shoot(int x, int y)
{
// Error-Checking if the values are valid..
if (x < 0 || x >= mapTiles.GetLength(0))
throw new ArgumentOutOfRangeException(string.Format("X-coordinate ({0}) is wrong (min: {1}, max: {2})!", x, 0, mapTiles.GetLength(0)));
if (y < 0 || y >= mapTiles.GetLength(1))
throw new ArgumentOutOfRangeException(string.Format("Y-coordinate ({0}) is wrong (min: {1}, max: {2})!", y, 0, mapTiles.GetLength(1)));
// Check if we shot here before..
if (mapTiles[x, y] == MapStatus.HitShip || mapTiles[x, y] == MapStatus.HitWater)
throw new ArgumentException(string.Format("You did already shoot the coordinates {0}/{1}", x, y));
// Shoot
if (mapTiles[x, y] == MapStatus.Empty)
{
mapTiles[x, y] = MapStatus.HitWater; // Change value
return false; // return the info that we didn't hit anything
}
else
{
mapTiles[x, y] = MapStatus.HitShip;
return true;
}
}
}
public static void Main(string[] args)
{
Map m = new Map(); // Initialize without map.
int x;
int y;
while (m.StillAlive()) // Loop untill all ships are sunk
{
m.PrintMap();
Console.Write("Enter X: ");
x = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter Y: ");
y = Convert.ToInt32(Console.ReadLine());
try
{
bool hit = m.Shoot(x, y);
m.PrintMap();
if (hit)
Console.WriteLine("We hit a ship!");
else
Console.WriteLine("We hit only water!");
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
}
Console.WriteLine("(Press Enter to continue)");
Console.ReadLine();
}
Console.WriteLine("We won!");
Console.ReadLine();
}
Upvotes: 1