Variable Values are not getting Updated - c#

I have 3 class files. First is the Main class, second is the Ship class, and the third is the Skill class. All values are added to my Main class file. I have a method where the parameters should be the value in my Main class. Please see below:
public class Skill
{
public double _capInc;
public int bscEng, advEng, expEng;
// engineering
public double capInc(int bsc, int adv, int exp)
{
if(bsc == 5 && adv == 5 && exp == 4)
{
_capInc = 0.48;
}
return _capInc;
}
The values of int bsc, int adv, and int exp should be the value of bscEng, advEng, & expEng which was set in my Main class
skill.bscEng = 5;
skill.advEng = 5;
skill.expEng = 4;
But when I try to run the method in my Ship class, values are different
public class Ship
{
Skill skill = new Skill();
public double capacitor;
public double totalCap()
{
double _totalCap = capacitor * skill.capInc(skill.bscEng, skill.advEng, skill.expEng);
Console.WriteLine(skill.bscEng + " bscEng inside totalCap");
return _totalCap;
}
This is the result when I run my Main class
class MainClass
{
public static void Main (string[] args)
{
Ship ship = new Ship();
Skill skill = new Skill();
skill.bscEng = 5;
skill.advEng = 5;
skill.expEng = 4;
Console.WriteLine(skill.bscEng + " bscEng in Main");
Console.WriteLine(ship.totalCap());
}
}
Result:
5 bscEng in Main
0 bscEg inside totalCap
0

You should assign the values to skill in your ship object.
Example:
ship.skill.bscEng = <yourValue>;
ship.skill.advEng = <yourValue>;
ship.skill.expEng = <yourValue>;

As I said in the comments you need to pass the skill object to the ship object. I've also added an constructor to both classes. I don't know what you really want to do and the code is weird but here's a working solution:
class MainClass
{
public static void Main (string[] args)
{
Skill skill = new Skill(5, 5, 4);
Ship ship = new Ship(skill);
Console.WriteLine(skill.bscEng + " bscEng in Main");
Console.WriteLine(ship.totalCap());
}
}
public class Skill
{
public Skill(int bscEnd, int advEng, int expEng)
{
this.bscEng = bscEnd;
this.advEng = advEng;
this.expEng = expEng;
}
public double _capInc;
public int bscEng, advEng, expEng;
// engineering
public double capInc()
{
if(bscEng == 5 && advEng == 5 && expEng == 4)
{
_capInc = 0.48;
}
return _capInc;
}
}
public class Ship
{
public Ship(Skill skill)
{
Skill = skill;
capacitor = 1.0; // TODO
}
private Skill Skill;
public double capacitor;
public double totalCap()
{
double _totalCap = capacitor * Skill.capInc();
Console.WriteLine(Skill.bscEng + " bscEng inside totalCap");
return _totalCap;
}
}
Output should be:
5 bscEng in Main
5 bscEng inside totalCap
0,48

Related

How to add a second argument(Number) to a calculator program?

I'm working on a small calculator program in Unity.
I only need the calculator to work with two numbers.
The feature I'm trying to implement:
After inputting the math operator, It should display the second number in the third index.
The issue:
Instead of Adding a second number, the first number is being overwritten if a different number is pressed on the keyboard.
Here's the script I've created:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Functions : MonoBehaviour
{
// Global Variable to display text on top panel
public Text panelText;
// Create a number variable
string num;
string num1;
string num2;
string mOpr;
string calNum;
string cbutton;
string opr;
bool isFirstNum;
// Start is called before the first frame update
void Start()
{
}
// A function with an int argument
public void NumberInputOne(string num)
{
num1 = num;
num2 = num;
if (panelText.text.Length < 1)
{
Debug.Log(num1);
panelText.text = num1;
isFirstNum = false;
}
else if (panelText.text.Length > 1 && panelText.text.Length < 3)
{
num2 = num;
Debug.Log(num2);
panelText.text = num1 + mOpr + num2;
}
}
public void OperatorInput(string opr)
{
mOpr = opr;
if (panelText.text.Length > 0 && panelText.text.Length < 2)
{
panelText.text = num1 + mOpr;
}
}
// public void NumberInputTwo(int num)
//{
// ResNum2 = num;
// Debug.Log(ResNum2);
// if (panelText.text.Length > 1 && panelText.text.Length < 3)
// {
// panelText.text = ResNum1 + opr + ResNum2;
// }
// }
public void RestartCal(string cButton)
{
panelText.text = "";
}
}
I've also added a screen recording to capture the issue:
First number being overwritten
Do you have any suggestions?
Thank you
use the NumberInputOne func like below;
public void NumberInputOne(string num)
{
if (num1 is null)
{
Debug.Log(num1);
panelText.text = num1;
num1 = num
}
else
{
num2 = num;
Debug.Log(num2);
panelText.text = num1 + mOpr + num2;
}
}
btw i recommend that you review the sample calculation application codes. because apart from what you're asking, there are places you need to improve in general.
This feels like a beginner programming exercise. But the right way to build a calculator involves programming concepts that you probably haven't been taught yet. Which makes this a poor choice as an assignment.
Personally I would build a calculator by defining a simple syntax tree to represent the formula being input. Including methods to display the formula and calculate the answer. For example;
public interface IValue
{
int Calculate();
string PrintValue();
}
public class Number : IValue
{
public int? Value;
public void AddDigit(int digit) => Value = (Value ?? 0) * 10 + digit;
public int Calculate() => Value ?? 0;
public string PrintValue() => Value?.ToString();
}
public abstract class BinaryOperator : IValue
{
public IValue Left;
public IValue Right;
public abstract int Operation(int left, int right);
public abstract char Operator { get; }
public int Calculate()
{
var left = Left.Calculate();
var right = Right.Calculate();
return Operation(left, right);
}
public string PrintValue() => $"{Left?.PrintValue()} {Operator} {Right?.PrintValue()}";
}
public class Addition : BinaryOperator
{
public override char Operator => '+';
public override int Operation(int left, int right) => left + right;
}
// TODO define other operators
Then think about how each button should change the syntax tree.
// the entire formula
public IValue Root;
// the number currently being typed
public Number Input;
public void Display() {
panelText.text = Root.PrintValue();
}
// start / clear
public void Start(){
Root = Input = new Number(){
Value = 0
};
Display();
}
public void Plus(){
// left as an exercise for the reader
Display();
}
public void Digit(int digit) {
Input.AddDigit(digit);
Display();
}
public void Calculate() {
// left as an exercise for the reader
Display();
}

Assigning objects to an array C#

Struggling to assign objects to an array in C#.
The output of the code is unexpected because I get the nameOfProject.ClassName(?) x3 rather than name and life points of 3 monsters i added using my for loop.
Debug suggests monsters aren't being assigned. Is there a logical flaw that people like me should be looking out for?
class Monsters
{
public Monsters(string name, int points)
{
var monsterName = name;
var monsterLifePoints = points;
}
}
class Program
{
static void Main(string[] args)
{
Monsters[] monster = new Monsters[3];
for (int i = 0; i < monster.Length; i++)
{
Console.WriteLine("Please enter a name");
string name = Console.ReadLine();
Console.WriteLine("Please enter life points");
int points = Convert.ToInt32(Console.ReadLine());
monster[i] = new Monsters(name,points);
Console.Clear();
}
foreach (var element in monster)
{
Console.WriteLine(element);
}
Console.ReadKey();
}
Assignment works just fine. The problem is that you never asign the monster's name and points to a field or property:
class Monsters
{
public Monsters(string name, int points)
{
var monsterName = name;
var monsterLifePoints = points;
}
}
This code just assigns the input to local values and then discards them.
Your class should look like this:
class Monsters
{
public string Name {get;set;}
public int Points {get;set;}
public Monsters(string name, int points)
{
Name = name;
Points = points;
}
}
This line still won't print the details :
Console.WriteLine(element);
You need to either create a string from the properties :
Console.WriteLine($"{element.Name} {element.Points}");
Or override the ToString() method of your class :
public override string ToString()
{
return $"{element.Name} {element.Points}";
}
How should WriteLine know that you want to print those two properties and not e.g. the type-name (which it does per default) or any other wierd string? You have to tell your program how to do this. This is done by overriding ToString
class Monster
{
public override string ToString() {
return this.name + " " + this.lifePoints;
}
}
Furthermore your variables need to be fields:
class Monster
{
private readonly string name;
private readonly int lifePoints;
Monster(string name, int points)
{
this.name = name;
this.lifePoints = points;
}
}

How to use polymorphism instead of generic in C#

I have a generic base Interface IGameble (for the example move is generic) and Classes: Chess and Tic-Tac-Toe (and more board games) which derived from the generic Interface IGmable but are no longer generic.
I want to design class Agent (there might be several kind of these) that will play any kind of game (not in the same time), but the problem is that I cant
for example:
interface IGame<T_move,T_matrix>
{
T_matrix[,] game_state { get; }
void MakeMove(Move mov);
List<Move> ListAllMoves();
...// some more irrelevant code
}
class Tic_Tac_Toe : IGameble<Tuple<int,int>,int>
{
public int turn;
public int[,] game_state;
public List<Tuple<int,int>> ListAllMoves() {...}
public void MakeMove(Tuple<int,int> mov) {...}
}
public Chess : IGameble <some other kind> //...
// so on more classes which uses other kind in the generic.
interface IAgent<Move>
{
Move MakeMove();
}
public RandomAgent<T_Move,T_Matrix> : IAgent
{
public IGameble<T_move> game;
public D(IGameble game_) {game = game_}
public T_Move MakeMove() {//randomly select a move}
}
public UserAgent<T_Move,T_Matrix> : IAgent {get the move from the user}
The problems is that I want 1 instance of the random agent (or any other agent) to play all the games (1 game at a time) and using the generic enforce me to specifically choose the types of T_Move and T_Matrix that I want to use.
I might have it all wrong and used the generic poorly.
There was a suggestion to use IMovable and IBoardable instead of the generic. Is it the correct design? Would it solve all the problems?
I'm still a noobie in design pattern in C# :(
Also I will be appreciate it very much if some one can get a link to some design pattern that can help me here (if there is one..).
I think you can just use the is keyword:
public D(IA<T> a_)
{
if (a_ is B)
{
//do something
}
else if (a_ is C)
{
//do something else
}
}
Generics in C# aren't nearly as flexible as C++, so as some commenters pointed out, you may not want to do things this way. You may want to design an intermediate interface, say IMove, that your algorithm can use to enumerate the moves in a generic way.
I don't know is that what you want, but you can do it without generics.
Sample code:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main (string[] args)
{
var game = new TicTacToe (
(x) => new UserAgent (x, "John"),
(x) => new RandomAgent (x));
game.Play ();
Console.ReadKey ();
}
}
public interface IGame
{
IMove[] GetAvailableMoves ();
}
public interface IMove
{
void MakeMove ();
string Description { get; }
}
public interface IAgent
{
string Name { get; }
IMove SelectMove ();
}
public delegate IAgent AgentCreator (IGame game);
public class RandomAgent : IAgent
{
private readonly IGame game;
private readonly Random random = new Random ();
public RandomAgent (IGame game)
{
this.game = game;
}
public string Name => "Computer (random moves)";
public IMove SelectMove ()
{
var availableMoves = game.GetAvailableMoves ();
int moveIndex = random.Next (availableMoves.Length);
return availableMoves[moveIndex];
}
}
public class UserAgent : IAgent
{
private readonly IGame game;
public UserAgent (IGame game, string playerName)
{
this.game = game;
Name = playerName;
}
public string Name { get; }
public IMove SelectMove ()
{
var availableMoves = game.GetAvailableMoves ();
Console.WriteLine ("Choose your move:");
for (int i = 0; i < availableMoves.Length; i++)
{
Console.WriteLine (i + " " + availableMoves[i].Description);
}
int selectedIndex = int.Parse (Console.ReadLine ());
return availableMoves[selectedIndex];
}
}
public class TicTacToe : IGame
{
enum CellState { Empty = 0, Circle, Cross }
CellState[] board = new CellState[9]; // 3x3 board
int currentPlayer = 0;
private IAgent player1, player2;
public TicTacToe (AgentCreator createPlayer1, AgentCreator createPlayer2)
{
player1 = createPlayer1 (this);
player2 = createPlayer2 (this);
}
public void Play ()
{
PrintBoard ();
while (GetAvailableMoves ().Length > 0)
{
IAgent agent = currentPlayer == 0 ? player1 : player2;
Console.WriteLine ($"{agent.Name} is doing a move...");
var move = agent.SelectMove ();
Console.WriteLine ("Selected move: " + move.Description);
move.MakeMove (); // apply move
PrintBoard ();
if (IsGameOver ()) break;
currentPlayer = currentPlayer == 0 ? 1 : 0;
}
Console.Write ("Game over. Winner is = ..."); // some logic to determine winner
}
public bool IsGameOver ()
{
return false;
}
public IMove[] GetAvailableMoves ()
{
var result = new List<IMove> ();
for (int i = 0; i < 9; i++)
{
var cell = board[i];
if (cell != CellState.Empty) continue;
int index = i;
int xpos = (i % 3) + 1;
int ypos = (i / 3) + 1;
var move = new Move ($"Set {CurrentPlayerSign} on ({xpos},{ypos})", () =>
{
board[index] = currentPlayer == 0 ? CellState.Cross : CellState.Circle;
});
result.Add (move);
}
return result.ToArray ();
}
private char CurrentPlayerSign => currentPlayer == 0 ? 'X' : 'O';
public void PrintBoard ()
{
Console.WriteLine ("Current board state:");
var b = board.Select (x => x == CellState.Empty ? "." : x == CellState.Cross ? "X" : "O").ToArray ();
Console.WriteLine ($"{b[0]}{b[1]}{b[2]}\r\n{b[3]}{b[4]}{b[5]}\r\n{b[6]}{b[7]}{b[8]}");
}
}
public class Move : IMove // Generic move, you can also create more specified moves like ChessMove, TicTacToeMove etc. if required
{
private readonly Action moveLogic;
public Move (string moveDescription, Action moveLogic)
{
this.moveLogic = moveLogic;
Description = moveDescription;
}
public string Description { get; }
public void MakeMove () => moveLogic.Invoke ();
}
}

C# Poker: how to keep track of players and make game engine (classes) preflop, flop, turn, river?

Im recently studying c# and want to create a 'simple' console app poker game.
Ive created classes: player, hand, deck, dealer. Dealer gets cards out of the deck and assigns it to player instances. What I'm struggling with now is how to progress further? I need to make some gameplay possible.
This is what i have coded thusfar:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication10
{
class Program
{
static void Main(string[] args)
{
//Deck d = new Deck();
Player[] players = new Player[2];
Dealer dealer = new Dealer();
players[0] = new Player("M");
players[1] = new Player("T");
foreach (var player in players)
{
Console.WriteLine(player.name);
}
Console.WriteLine();
foreach (var player in players)
{
player.AddCardsToHand(dealer);
}
Console.WriteLine("View hand van player 1");
foreach (string card in players[0].ViewHandCards())
{
Console.WriteLine(card);
}
Console.WriteLine();
Console.WriteLine("View hand van player 2");
foreach (string card in players[1].ViewHandCards())
{
Console.WriteLine(card);
}
Console.WriteLine();
Console.WriteLine("Number of players instantiated:");
Console.WriteLine(Player.playerCount);
Console.WriteLine();
Console.WriteLine("Number of hands instantiated:");
Console.WriteLine(Hand.handCount);
Console.WriteLine();
dealer.SetMoneyAmount(players[0]);
dealer.SetMoneyAmount(players[1], 150);
Console.WriteLine("Money player 1:");
Console.WriteLine(players[0].MoneyAmount);
Console.WriteLine();
Console.WriteLine("Money player 2:");
Console.WriteLine(players[1].MoneyAmount);
Console.WriteLine();
int index = 0;
dealer.SetDealer(players[index]);
Console.WriteLine("Dealer: " + dealer.GetDealer());
// how to know in a class how many players there are and there values?
// create a class containing the players array?
}
}
class Settings
{
// static string dealer;
public static int dealerIndex;
public static string dealerName;
public
}
class User
{
public string name;
}
class Player : User
{
Hand h = new Hand();
public static int playerCount;
private double moneyAmount;
public bool dealerButton;
public double MoneyAmount
{
get
{
return moneyAmount;
}
set
{
moneyAmount = value;
}
}
public int NumOfCardsInHand()
{
return h.cardsInHand;
}
public string[] ViewHandCards()
{
return h.handCards;
}
public void AddCardsToHand(Dealer d)
{
d.DealCard(h);
d.DealCard(h);
}
public Player(string n)
{
this.name = n;
playerCount++;
}
}
class Hand
{
public static int handCount;
public int cardsInHand = 0;
public string[] handCards = new string[2];
public Hand()
{
handCount++;
}
}
class Dealer
{
Deck d = new Deck();
//public void StartGame()
//{
//}
public void DealCard(Hand h)
{
if (h.cardsInHand < 2)
{
if (h.cardsInHand == 0)
h.handCards[0] = d.NextCard();
if (h.cardsInHand == 1)
h.handCards[1] = d.NextCard();
h.cardsInHand++;
}
else
{
Console.WriteLine("Meer dan 2 kaarten per hand is niet toegestaan");
}
}
public void SetMoneyAmount(Player p, double amount = 100)
{
p.MoneyAmount = amount;
}
public void SetDealer(Player p)
{
p.dealerButton = true;
Settings.dealerName = p.name;
}
public string GetDealer()
{
return Settings.dealerName;
}
}
class Deck
{
public int numOfCards = 52;
public string[] cards = new string[13];
public string[] playingCards = new string[52];
public string[] cardsDealt = new string[52];
Random r = new Random();
int y = 0;
public string NextCard()
{
string nextCard = "-";
int x = 0;
while (x < 1)
{
nextCard = playingCards[r.Next(0, playingCards.Length)];
if (!cardsDealt.Contains(nextCard))
{
cardsDealt[y] = nextCard;
y++;
x++;
}
else
{
Console.WriteLine("Reeds gedeelde kaart bijna opnieuw gedeeld!");
x = 0;
}
}
return nextCard;
}
public void ConstructDeck()
{
// spade club heart diamond
this.cards[0] = "A";
this.cards[1] = "K";
this.cards[2] = "Q";
this.cards[3] = "J";
this.cards[4] = "10";
this.cards[5] = "9";
this.cards[6] = "8";
this.cards[7] = "7";
this.cards[8] = "6";
this.cards[9] = "5";
this.cards[10] = "4";
this.cards[11] = "3";
this.cards[12] = "2";
int x = 0;
foreach (string card in this.cards)
{
this.playingCards[x] = card + "s";
x++;
this.playingCards[x] = card + "c";
x++;
this.playingCards[x] = card + "h";
x++;
this.playingCards[x] = card + "d";
x++;
}
}
public Deck()
{
ConstructDeck();
}
}
class Bet
{
public double betAmount;
public Bet(Player p, double betInput)
{
betAmount = betInput;
}
}
}
I have put the player instances in an array and can call them like this players[0] (player 1).
I would like to know if im on the right track here and more specifically how do I keep track of the players I instantiated so that other classes can access the player instance variables? Im assigning one player the dealer status and would need to know where to start asking for other players initiative in the game like needing to bet call check or fold at some given point. I dont know what kind of classes I would need to create for a preflop game, a flop game, a turn game and the river game. Classes for each game name? How would I check if a player finished his action?
I think I should create a class like: preflopgame and identify the dealer than ask initiative (bet fold etc (make classes of betting folding checking etc) of the player thats not the dealer and keep track via a variable that player finished its initiative in the preflopgame class? And if preflopgame is played out: some kind of static boolean field in the class indicating its finished. Than move on to the next game: flopgame. Is this the right way of thinking about this game?
Any suggestions would certainly be much apreciated.
Excuse my English im Dutch from origin.

Knights Tour recursive C# Im getting something wrong in my way of doing the stuff

class Knight
{
public static readonly double LegalDistance = Math.Sqrt(5);
public Stack<Field> Steps { get; set; }
private static readonly List<Field> board = Board.GameBoard;
private static List<Field> fields;
private static readonly Random random = new Random();
private static readonly object synLock = new object();
public Knight(Field initial)
{
Steps = new Stack<Field>();
Steps.Push(initial);
}
public void Move()
{
Field destination = Choose();
if (destination == null)
{
return;
}
Console.WriteLine("Moving from " + GetPosition().GetFieldName() + " to " + destination.GetFieldName());
Steps.Push(destination);
}
public Field Back()
{
Field from = Steps.Pop();
Console.WriteLine("Moving back from " + from.GetFieldName() + " to " + GetPosition().GetFieldName());
return from;
}
public Field Choose()
{
List<Field> legalMoves = Behaviour();
legalMoves.RemoveAll(field => Steps.Contains(field, new FieldValueComparer()));
if (legalMoves.Count == 0)
{
return null;
}
Field theChoosenOne;
int index;
lock (synLock)
{
index = random.Next(0, legalMoves.Count);
}
theChoosenOne = legalMoves.ElementAt(index);
return theChoosenOne;
}
private List<Field> Behaviour()
{
fields = new List<Field>();
fields.AddRange(board);
for (int i = fields.Count - 1; i >= 0; i--)
{
double actualDistance = fields[i].GetDistance(GetPosition());
if (!actualDistance.Equals(LegalDistance))
{
fields.Remove(fields[i]);
}
}
return fields;
}
public List<Field> GetSteps()
{
return Steps.ToList();
}
public Field GetPosition()
{
return Steps.Peek();
}
}
So this is how I'd do the stuff. The problem is, I am missing some key functionality, because on low given stepcount it backtracks to the start, on high stepcount, it causes StackOverFlow.
Here are some other functions to let you understand what I want to do:
Calculating distance:
public double GetDistance(Field other)
{
return Math.Sqrt(Math.Pow(other.X - X, 2) + Math.Pow(other.Y - Y, 2));
}
Finding the path:
class PathFinder
{
public static void FindPath(Knight knight)
{
if (knight.Steps.Count != 20)
{
knight.Move();
FindPath(knight);
knight.Back();
}
}
}
Your path search is essentially random walk. On large board, this may take a while anyway.
Now about StackOverflow: notice that you don't push anything on Move() when there are no places to go. So, on recursive call to FindPath() there still will be the same knight.Steps.Count, the same position, the same null return on Choose()... and so on, until you're out of stack space.
Obvious fix would be to add bool return value to Move() indicating if there was any move. Unless there is actual reason behind using random moves, more deterministic search algorithm is recommended.

Categories

Resources