|
 GameBoard.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleBattle
{
public class GameBoard
{
public enum Square
{
Water,
Miss,
Ship,
Hit,
}
private Square[,] TheBoard = new Square[10, 10];
public Square[,] CheckGuess(int x, int y)
{
if (TheBoard[x, y] == Square.Ship)
{
Console.WriteLine(TheBoard[x, y] = Square.Hit);
}
else if (TheBoard[x, y] == Square.Water)
{
Console.WriteLine(TheBoard[x, y] = Square.Miss);
}
else if (TheBoard[x, y] == Square.Miss)
{
string message1 = "you already missed here";
Console.WriteLine(message1);
}
else
{
string message2 = "this spot was hit already";
Console.WriteLine(message2);
}
return TheBoard;
}
public Ship PlaceShip(Ship ship, Point loc, Orientation wayUp)
{
Console.WriteLine(ship.Name);
Console.WriteLine(wayUp);
Console.WriteLine(loc);
return ship;
}
}
public enum Orientation
{
Up = 1,
Down = 2,
Left = 4,
Right = 8,
}
public struct Point
{
public int x;
public int y;
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
public abstract class Ship
{
public abstract string Name { get; }
public abstract int Length { get; }
}
public class Destroyer : Ship
{
public override string Name { get => "Destroyer"; }
public override int Length { get => 2; }
}
public class Submarine : Ship
{
public override string Name { get => "Submarine"; }
public override int Length { get => 3; }
}
public class Cruiser : Ship
{
public override string Name { get => "Cruiser"; }
public override int Length { get => 3; }
}
public class Battleship : Ship
{
public override string Name { get => "Battleship"; }
public override int Length { get => 4; }
}
public class Carrier : Ship
{
public override string Name { get => "Carrier"; }
public override int Length { get => 5; }
}
}
It has gotten pretty messy and I am feeling a little frustrated
Any suggestions on what I can do to clean it up?
This must be one of the longest threads ever
|
|
|
|
|
Hi Griff,
Hope you are doing well
I am up to speed with everything you mentioned on this post
I figured out I needed the using directive System.Drawing in order
to access the built in .NET Point struct
With that said I successfully implemented the randomization of
Point loc, and the Orienation orient (represented as Enums)
I am able to call the PlaceShip method on the object playerA
and create the 1 ship, 2 location, and 3 orientation as follows:
playerA.PlaceShip(new Submarine(), loc, orient);
...
public Ship PlaceShip(Ship ship, Point loc, Orientation wayUp)
{
loc = (x, y);
string direction;
int x;
int y;
if (wayUp == Orientation.Right)
{
direction = "right";
}
else if (wayUp == Orientation.Left)
{
direction = "left";
}
else
{
direction = "left,right";
}
if (wayUp == Orientation.Down)
{
direction += "down";
}
else if (wayUp == Orientation.Up)
{
direction += "up";
}
else
{
direction += "up,down";
}
if (direction == "up")
{
for (int i = y; i < y - 4; i--)
{
TheBoard[i, y] = Square.Ship;
}
}
else if (direction == "down")
{
for (int i = y; i < y + 4; i++)
{
TheBoard[i, y] = Square.Ship;
}
}
else if (direction == "left")
{
for (int i = x; i < x - 4; i--)
{
TheBoard[x, i] = Square.Ship;
}
}
else
{
for (int i = x; i < x + 4; i++)
{
TheBoard[x, i] = Square.Ship;
}
}
Console.WriteLine(ship.Name);
Console.WriteLine(wayUp);
Console.WriteLine(loc);
return ship;
}
In the console when I run the program with PlaceShip() above I get back the following:
Submarine
Left
{X=7, Y=1}
What I am working on now is placement of the Ship(s)
inside the PlaceShip Method:
I am trying to acces the x, y coordinates that come from Point loc
within the PlaceShip Method, and them use them in the assignment
logic with the looping and if/else statements in order to populate
the board with the Enum Ship
I know that I need to take the location and orientation and loop
over them to populate TheBoard with the Enum Ship, but having
a hard implementing that functionality.
|
|
|
|
|
Hi! I haven't forgotten you - I've just been really, really busy for the last week, and it doesn't look like it'll improve till the weekend at least.
I will get back to you, but I don't want to hurry what I say and either send you off on a wrong tangent or confuse you - and that takes time to review the whole conversation we've had and plan out how best to help you next!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Okay no worries at all I completely understand and appreciate the valuable time you spend while helping me.
I'll continue to try and move forward, and watch/code C# tutorials since there is what seems like a plethora of concepts to cover in .NET
|
|
|
|
|
Hope all is well
So I am able to pass in all three arguments to the PlaceShip method
And I am copying the Point loc inside of of the method and assigning them values of loc.X, loc.Y,
so I can use them in my loops in my conditional statements (not sure if that's the best way)
I am trying to place and populate the ship with the Enum Ship
Sometimes the values get filled, but other times I am off the board or the logic won't execute. I can see
the values get populated on TheBoard when I step through it while debugging.
This is what it looks like currently:
public Ship PlaceShip(Ship ship, Point loc, Orientation direction)
{
loc = new Point(loc.X, loc.Y);
Console.WriteLine(loc);
if (direction == Orientation.Up)
{
for (int i = loc.Y; i < loc.Y - 5; i--)
{
TheBoard[loc.X, i] = Square.Ship;
}
}
else if (direction == Orientation.Down)
{
for (int i = loc.Y; i < loc.Y + 5; i++)
{
TheBoard[loc.X, i] = Square.Ship;
}
}
else if (direction == Orientation.Left)
{
for (int i = loc.X; i < loc.X - 5; i--)
{
TheBoard[i, loc.Y] = Square.Ship;
}
}
else
{
for (int i = loc.X; i < loc.X + 5; i++)
{
TheBoard[i, loc.Y] = Square.Ship;
}
}
Console.WriteLine(ship.Name);
Console.WriteLine(direction);
return ship;
}
}
|
|
|
|
|
In terms of randomly populating, you'd have to tally the rows and columns that are available "before" each "chance" throw; whose range would depends on the # of available "slots".
A "5 cell" ship on a 10 x 10 grid would obviously only fit in a row or column that had 5 "contiguous" empty cells; something that could be figured out by iterating over the array before each throw. Use the "id #" of the ship to populate the grid cells and identify what got hit. Another throw could determine the offset within the column / row if more than 5 cells are available for "slotting".
"Before entering on an understanding, I have meditated for a long time, and have foreseen what might happen. It is not genius which reveals to me suddenly, secretly, what I have to say or to do in a circumstance unexpected by other people; it is reflection, it is meditation." - Napoleon I
|
|
|
|
|
Hi. I'm working with Visual Studio on a application that changes a windows registry. There is a small forms that requests an address in a text box. The contents of the text box wil be writen is the registry. I need the key to be LocalMachine and here is a snippet of this code:
private void button1_Click(object sender, EventArgs e)
{
RegistryKey chaveBase, chave;
chaveBase = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
chave = chaveBase.CreateSubKey("Software\\Antares", true);
chave.SetValue("Endereço", textBox1.Text);
}
The problem is that I receive the message: "System.UnauthorizedAccessException: 'Access to the registry key 'HKEY_LOCAL_MACHINE\Software\Antares' is denied".
If I change LocalMachine for CurrentUser, it works fine. What should I do to access LocalMachine?
|
|
|
|
|
This is because you have to be running the code as an administrator to make any changes to anything under HKEY_LOCAL_MACHINE.
Hold down a Shift key, right-click your executable and click "Run as administrator". You'll, of course, have to supply admin credentials, or if you're already using an admin account, you'll have to OK using the admin part of your account to run the app. Then it'll work.
|
|
|
|
|
Thank you Dave, but code should run without user intervention.
|
|
|
|
|
Yeah, ... and?
You said you created a WINDOWS FORMS APP, which is an app that requires user interaction.
If this is a test app for what you're really writing, like a Windows Service app, then you can run that code under the Local System account, which will have admin permissions.
|
|
|
|
|
To add to what Dave has - rightly - said ...
The problem is due to a layer of security added after the registry became too bloated and vulnerable: it was filled with rubbish, and fully available to code to view or modify.
In more modern OSes (think Vista and later) it became much harder to access the registry, and Admin access was required for most of the content. This included the entire LocalMachine branch. Do not expect it to get easier to access, if anything it will get harder as storing app settings there is now discouraged to reduce the bloat.
So unless you have a very, very good reason to use the registry you shouldn't do it: use an app config file, or store data in a User data folder instead. It's easier to do, and a lot more future proof!
This may help: SWhere should I store my data?[^]
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Hi, OriginalGriff.
I read your article which you suggested and I'll probably change my storage place. On question: your article is 10 years old. Are those information still valid?
Thank you.
|
|
|
|
|
Yes - the locations are still the same!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Hi, OriginalGriff.
I used the code you wrote in your article, but I received an error message. First see a snipet of my code:
public static Guid AppGuid
{
get
{
Assembly asm = Assembly.GetEntryAssembly();
object[] attr = (asm.GetCustomAttributes(typeof(GuidAttribute), true));
return new Guid((attr[0] as GuidAttribute).Value);
}
}
This is in fact your code. The error is on the line of the return:
"System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'"
Do you know what causes this error?
Thanks.
|
|
|
|
|
That's because your app doesn't have a GuidAttribute.
Go into your project Properties, click on the Application tab, then Assembly Information button. You'll find a GUID box in the dialog that pops up. That box is empty. That's where you have to put your GUID.
|
|
|
|
|
Normally, that is filled in by VS when it creates the project template. Dunno what he used to do that ...
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Under the .NET Framework projects (4.8 at least), it's filled in by the Windows Forms template, but not the WPF template. I haven't tried any of the others.
On .NET Core projects, the "Assembly Information" option doesn't even exist. The assembly info is automatically generated at compile time, but is controllable in the .csproj file.
I haven't spent very much time looking at this because I don't expose much to COM, so YMMV.
|
|
|
|
|
Hi, Dave.
I tried here, but didn't get it. I use VS Community 2022 in portuguese.
In my superior menu there is "Tools" and then "Create GUID". Next appears a small form with many options (1 - IMPLEMENT_OLECREATE(...) 2 - DEFINE_GUID(...) and others). Menu says I must copy and paste the chosen option in my source code. But I don't understand what I should do. Have you seen this? Can you help me? Thanks again.
|
|
|
|
|
Pick Registry format, click the Copy button, then you go back into the Project Properties, ..., and paste that value into the GUID box and click OK.
|
|
|
|
|
Dave. For me there is no GUID box. But I'll tell yu my original problem, and maybe you can give another tip. I'll install a desktop application for a client and need to store the instalation folder somewhere. Inicially I thougt of using windows registry, but the local available was CURRENTUSER, and I didn't like it. Then I read OriginalGriff's article and thougt of a text file anywhere I can find and the ALLUSERS folder appeared to be good for me. Then these problems arouse.
Do you have any suggestion? Thanks a lot.
|
|
|
|
|
What type of app are you writing, which version of .NET or the .NET Framework are you writing this code against, and are you exposing any components in your app to COM?
|
|
|
|
|
I'm writing a program to control incomes and expenses of a small company. .NET Framework version 4.8.04084. Microsoft Visual Studio Community 2022 Version 17.2.6
Is this what you wanted?
|
|
|
|
|
OK, so you're writing either a Windows Forms app, or WPF, for some accounting function.
You have no reason at all to be saving anything to HKEY_LOCAL_MACHINE. Follow the advice of Griff.
As for the Guid of the app, you really have no use for it so why are you interested in it?
|
|
|
|
|
Hi, Dave.
I changed my approach. Now I get a special folder path and will use it to store a text file containing the installation folder of my app. The command is:
string caminho = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData).ToString();
I think it will solve my problem.
Thanks for your help and interest!
|
|
|
|
|
GetFolderPath always returns a string, so why are you calling .ToString() on a string?
|
|
|
|
|