so, im making small unity game and have some classes for working with big nubmer's
here is the code for class CurrLevel
public class CurrLevel {
public CurrLevel (int levelNum, string id) {
valuesLevel = "pow" + levelNum.ToString();
if(levelNum != 0){
numberFormatSci = "10^" + levelNum.ToString();
} else {
numberFormatSci = "";
}
identificator = id;
}
public string valuesLevel;
public string numberFormatSci;
public string identificator;
public int getValue(){
return PlayerPrefs.GetInt(identificator+"-"+valuesLevel);
}
public void setValue(int value){
PlayerPrefs.SetInt(identificator+"-"+valuesLevel, value);
}
public void add(int value){
PlayerPrefs.SetInt(identificator+"-"+valuesLevel, PlayerPrefs.GetInt(identificator+"-"+valuesLevel) + value);
}
public void substract(int value){
PlayerPrefs.SetInt(identificator+"-"+valuesLevel, PlayerPrefs.GetInt(identificator+"-"+valuesLevel) - value);
}
}
here is the code for class SomeCurrency
public class SomeCurrency {
public string identificator;
public CurrLevel[] levels = new CurrLevel[10];
public SomeCurrency(string id){
identificator = id;
for(int i = 0; i < 30; i=i+3){
levels[i/3] = new CurrLevel(i, identificator);
}
}
public void add(int power, double value){
int full = (int) value;
int leftover = (int) (value*1000 - full*1000);
if(power >= 3){
levels[power/3-1].add(leftover);
}
levels[power/3].add(full);
updateValues();
}
public SomeCurrency copy(SomeCurrency CurrToCopy){
SomeCurrency copy = new SomeCurrency(CurrToCopy.identificator);
for(int i = 0; i < 30; i++){
copy.levels[i/3] = CurrToCopy.levels[i/3];
}
return copy;
}
public void addAnotherCurrency(SomeCurrency anotherCurr){
for(int i = 0; i < 30; i=i+3){
this.add(i, anotherCurr.levels[i/3].getValue());
}
updateValues();
}
public bool substractAnotherCurrency(SomeCurrency anotherCurr){
SomeCurrency buffer = copy(anotherCurr);
Debug.Log(anotherCurr.levels[1].getValue());
if(canSubstract(buffer)){
Debug.Log(anotherCurr.levels[1].getValue());
// for(int i = 27; i >= 0; i-=3){
// levels[i/3].substract(anotherCurr.levels[i/3].getValue());
// }
return true;
} else {
return false;
}
}
public bool canSubstract(SomeCurrency fromWhereSubstract){
bool possible = false;
for(int i = 0; i < 30; i+=3){
fromWhereSubstract.levels[i/3].substract(levels[i/3].getValue());
if(i != 27){
if(fromWhereSubstract.levels[i/3].getValue() < 0){
fromWhereSubstract.levels[i/3+1].substract(1);
fromWhereSubstract.levels[i/3].add(1000);
}
}
}
if(fromWhereSubstract.levels[9].getValue() < 0){
possible = true;
}
return possible;
}
public void setValue(int power, double value){
int full = (int) value;
int leftover = (int) (value*1000 - full*1000);
if(power >= 3){
string beforeid = identificator+"-"+levels[power/3-1].valuesLevel;
PlayerPrefs.SetInt(beforeid,leftover);
}
string thisid = identificator+"-"+levels[power/3].valuesLevel;
PlayerPrefs.SetInt(thisid,full);
updateValues();
}
public string getStringValue(){
int maxlvl = 0;
for(int i = 27; i >= 0; i=i-3){
if(levels[i/3].getValue() > 0){
maxlvl = i/3;
break;
}
}
string result = levels[maxlvl].getValue().ToString();
if(maxlvl > 0){
string leftover = levels[maxlvl-1].getValue().ToString();
while(leftover.Length != 3){
leftover = "0"+leftover;
}
result += "." + leftover + "*" + levels[maxlvl].numberFormatSci;
}
return result;
}
public void resetValues(){
for(int i = 0; i < 30; i+=3){
levels[i/3].setValue(0);
}
}
private void updateValues(){
for(int i = 0; i < 27; i=i+3){
levels[i/3] = new CurrLevel(i, identificator);
if(levels[i/3].getValue() >= 1000){
levels[i/3].setValue(levels[i/3].getValue()-1000);
levels[i/3+1].setValue(levels[i/3+1].getValue()+1);
}
}
}
}
So basicly, in the code i create to new variables type of SomeCurrency
public NumberFormatting.SomeCurrency playerScore = new NumberFormatting.SomeCurrency("playerScore");
public NumberFormatting.SomeCurrency playerClickValue = new NumberFormatting.SomeCurrency("playerClickValue");
playerScore.resetValues();
playerScore.add(6, 1.32);
playerClickValue.resetValues();
playerClickValue.add(3, 103.831);
And later, when player clicks the button i try to substract one from another
Debug.Log(playerClickValue.levels[1].getValue());
Debug.Log(playerScore.substractAnotherCurrency(playerClickValue));
Debugger firstly print 103 (original value of playerClickValue.levels[1].getValue() from click function), then it prints 103 again (from the function substractAnotherCurrency before if(canSubstract(buffer)), but printing the same variable after this canSubstract shows the value of 783. So, my functions somehow change original value of playerClickValue every time i call substractAnotherCurrency.
What should i change to keep the playerClickValue same, but still checking can i suubstract it from another SomeCurrency, and after checking if i can - do so.
In C#, objects are passed by reference, meaning that if you modify an object in a fonction, it will be modified everywhere. You can read more about it, it will be important when coding. It seems you tried to do something like a copy somewhere, but you don't use the copy at all.
Also, are you sure you want to edit a variable in canSubstact?
The name suggest if will just return a bool and not change anything but you actually call substact in it
fromWhereSubstract.levels[i/3+1].substract(1);
Related
using System;
namespace ConsoleApp12
{
class Cake
{
private string cakeType;
private int weight;
private bool baked;
public Cake(string cakeType, int weight)
{
this.cakeType = cakeType;
this.weight = weight;
this.baked = true;
}
public Cake(string cakeType, int weight, bool baked)
{
this.cakeType = cakeType;
this.weight = weight;
this.baked = baked;
}
public Cake(int weight)
{
this.cakeType = "chocolate";
this.weight = weight;
this.baked = true;
}
public string IsBaked()
{
int count = 0;
Cake[] CakeArr = new Cake[3];
for (int i = 0; i < CakeArr.Length; i++)
{
if (/* if cake is baked */)
{
return "The Cake is indeed baked...";
}
else
{
count++;
}
}
return "There are: " + count + " not baked cakes...";
}
public string GetCakeType() { return this.cakeType; }
public int GetWeight() { return this.weight; }
public bool GetBaked() { return this.baked; }
public void SetBaked(bool baked) { this.baked = baked; }
public void Sold(int weight) { this.weight -= weight; }
}
class Program
{
static void Main(string[] args)
{
Cake c1 = new Cake(1800);
Cake c2 = new Cake("cheese", 1200, false);
Cake c3 = new Cake("chocolate", 2100, true);
c1.Sold(400);
if (c1 == c3)
Console.WriteLine("aaa");
else
Console.WriteLine("bbb");
c3.Sold(700);
if (c1 == c2 || c2 == c3)
Console.WriteLine("ccc");
else
if (c1 == c3)
Console.WriteLine("ddd");
c1.Sold(1400);
c2.SetBaked(c1.GetBaked());
if (c2.GetBaked())
Console.WriteLine("eee");
Console.WriteLine(c2.IsBaked());
}
}
}
I did everything I need but I do not know how to make the system check if the cake is baked in an if statement...
It doesnt matter what everything else do like the other methods because they all supposed to work anyways I just need to find a solution to the method IsBaked in the class Cake.
Please help, thank you.
Assuming you want to check how many of c1, c2, c3 are baked, you might want to create an extension method:
public static class MyCakeExtensionMethods{
public static string HowManyAreNotBaked(this Cake[] cakeArr ){
int count = 0;
for (int i = 0; i < cakeArr.Length; i++)
{
if (!cakeArr[i].GetBaked())
{
count++;
}
}
if( count == 0){
return "all cakes are baked";
return "There are: " + count + " not baked cakes...";
}
}
Note that the body could be mostly simplified to CakeArr.Count(c => c.GetBaked());
But there are other issues with your code:
You should probably be using properties instead of get/set methods
You should probably not allow the cake type to be changed after creation. Unless you found some way to transform a cheese-cake into a chocolatecake in the real world.
You should probably change SetBaked(bool baked) into Bake(), since you cannot un-bake a cake.
You should probably add a check to Sold to ensure you cannot sell more cake than there is.
I am a new to OOP and C#. Here is a small experiment I made:
Using System;
class A
{
public int X { get; set; }
public static A[] a = new A[10];
public static int i = 0;
public A()
{
this.X = -2;
}
public A(int x)
{
this.X = x;
}
public static void Add(A b)
{
if (i < 10) a[i] = b;
i++;
return;
}
public void Reveal()
{
Console.WriteLine(X);
}
public static void Show()
{
for (int j=0; j<=10; ++j)
{
a[j].Reveal();
}
}
}
I tried creating a class that has its instances stored inside, up to 10 objects. When invoke the A.Show() a NullReferenceException is thrown: "Object reference not set to an instance of an object." As I guess, it must be the object a[j] is created, then destroyed immediately. So it give a[j] a null value, hence the result?
*This is my main method:
int val = 0;
while (val != -1)
{
Console.Write("create a new object. new value: ");
val = Console.ReadLine();
A a = new A(val);
A.Add(a);
};
A.Show();
Console.ReadKey();
return;
Please pay attention to the upper bound condition of the loop:
for (int j=0; j<=10; ++j)
{
a[j].Reveal();
}
array a has 10 items assigned,but this code shows you have 11 items beginning from 0 to 10, so change it to just lower than 10.And also try to compare
So the correct code can be as follows :
public static void Show()
{
for (int j = 0; j < 10; ++j)
{
a[j]?.Reveal();//Or if(a[j] != null)
}
}
and also make amendment to line that reads the input of client,that must be as follow:
val = int.Parse(Console.ReadLine());//If you are sure that the input
is truly convertible to int,or
int.TryParse(Console.ReadLine() , out int value);
if(value != 0)
{
val = value;
A a = new A(val);
A.Add(a);
}
else
{
throw new Exception();
}
You're incrementing i before assigning a[i], so a[0] is null because it will always start initializing a at 1.
Try changing the add method to this:
public static void Add(A b)
{
if (i < 10)
{ //braces are important for readability
a[i] = b;
}
i++;
return;
}
I`m trying to find the first fib number to contain 1000 digits. Because i have no data-type capeable of holding such a number, i created a class called hugeNumber which holds the digits in a list, with a decimal base. I get a stack overflow at the generation of the list for the "hugenum" class - I am not sure why (is it really not the right way to do it? Is there a better way?)
Here's my code:
class hugeNum
{
List<int> digits = new List<int>();
public hugeNum(int basic)
{
digits.Add(basic);
}
public hugeNum()
{
}
public static hugeNum operator +(hugeNum first, hugeNum second)
{
hugeNum generated = new hugeNum();
hugeNum finalIter = null;
int carry = 0;
int i = 0;
for (i = 0; i<second.digits.Count && i<first.digits.Count; i++)
{
generated.digits.Add(first.digits[i] + second.digits[i] + carry);
if (generated.digits[i] >= 10)
{
carry = 1;
generated.digits[i] -= 10;
}
else
carry = 0;
}
finalIter = first;
if (i==first.digits.Count)
{
finalIter = second;
}
while (i<finalIter.digits.Count)
{
generated.digits.Add(finalIter.digits[i]);
i++;
}
return generated;
}
public int amountOfDigits()
{
return this.digits.Count;
}
}
class Program
{
public static int fibHugesUntilIter(hugeNum huge1, hugeNum huge2, int reqDigits, int iter)
{
if (huge2.amountOfDigits() == reqDigits)
return iter;
return fibHugesUntilIter(huge2, huge1 + huge2, reqDigits, iter + 1);
}
static void Main(string[] args)
{
Console.WriteLine(fibHugesUntilIter(new hugeNum(1), new hugeNum(1), 1000, 1));
}
}
You can use BigInteger without recursion:
public static int FibHugesUntil(BigInteger huge1, BigInteger huge2, int reqDigits)
{
int number = 1;
while (huge2.ToString().Length < reqDigits)
{
var huge3 = huge1 + huge2;
huge1 = huge2;
huge2 = huge3;
number++;
}
return number;
}
static void Main(string[] args)
{
Console.WriteLine(FibHugesUntil(BigInteger.Zero, BigInteger.One, 1000));
}
Answer: 4782
I'm trying to find the "Median","Maximum","Minimum","Average","Sum of numbers" and if there is any duplicates in the array. I ran into issues in the beginning when I made my methods and tried calling them in the main method. This produced "An object reference is required to access non-static member" so to combat this I made all the variables public static. Wasn't the best option but it worked. So I tackled the rest and when tried to display that I have duplicates I get "not all code paths return a value" So any help on how to fix this and any way to clean up the code will very helpful.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
public class Test
{
public static int maxNum;
public static int minNum;
public static double avgNum;
public static long sumNum;
public static double median;
public static int MaxNum(int[] randArray)
{
maxNum = randArray.Max();
Console.WriteLine("This is the maximum value: " + maxNum);
return maxNum;
}
public static int MinNum(int[] randArray)
{
minNum = randArray.Min();
Console.WriteLine("This is the minimum value: " + minNum);
return minNum;
}
public static long SumNum(int[] randArray)
{
for(int x =0; x < randArray.Length;x++)
sumNum = sumNum +randArray[x];
Console.WriteLine("This is the sum of values: " + sumNum);
return sumNum;
}
public static double Average(int[] randArray)
{
avgNum = randArray.Average();
Console.WriteLine("This is the average of the values: " + avgNum);
return avgNum;
}
public static int GetMedian(int[] randArray)
{
int size = randArray.Length;
int mid = size / 2;
double median = (size % 2 != 0) ? (double)randArray[mid] : ((double)randArray[mid] + (double)randArray[mid - 1]) / 2;
Console.WriteLine("This is the median value:" + median);
return Convert.ToInt32((median));
}
public static bool ContainDups(int[] randArray)
{
for (int i = 0; i < randArray.Length; i++)
{
for (int j = i + 1; j < randArray.Length; j++)
{
if (randArray [i] == randArray [j])
return true;
}
}
return false;
}
public static int ShowDups(int[] randArray)
{
if(ContainDups(randArray) == true)
{
Console.WriteLine("Contains duplicate numbers");
}
else
{
Console.WriteLine("No duplicate numbers");
}
}
public static void Main()
{
int[] randArray = new int[1000];
Random r = new Random();
for(int i = 0; i < randArray.Length; i++)
{
randArray[i] = r.Next();
}
Array.Sort(randArray);
for (int i = 0; i < 1000; i++)
{
// Console.WriteLine(","+randArray[i]);
}
MaxNum(randArray);
MinNum(randArray);
SumNum(randArray);
Average(randArray);
GetMedian(randArray);
ContainDups(randArray);
ShowDups(randArray);
}
}
This method public static int ShowDups(int[] randArray) doesn't return anything. You just write to te console a message and you don't return an int as it is expected by the signature of your method.
First if all the class members are static, just make the class to be static instead .
Secondly, if you have no intention to return value in your function and just write to console, then use void instead of int
If many threads are calling GetNextNumber simultaneously with the following code, GetNextNumber will return 1 more times than any other numbers.
private class RoundRobbinNumber
{
private int _maxNumbers = 10;
private int _lastNumber;
private RoundRobbinNumber(int maxNumbers)
{
_maxNumbers = maxNumbers;
}
public int GetNextNumber()
{
int nextNumber = Interlocked.Increment(ref _lastNumber);
if (_lastNumber > _maxNumbers)
{
Interlocked.CompareExchange(ref _lastNumber, 1, _maxNumbers);
nextNumber = 1;
}
return nextNumber;
}
}
Is there a way to reset the _lastNumber back to one, and reliably return an incremented number for each thread calling GetNextNumber(), without having to use a lock?
Andrey's answer without conditional statements:
using System;
namespace Utils
{
public class RoundRobinCounter
{
private int _max;
private int _currentNumber = 0;
public RoundRobinCounter(int max)
{
_max = max;
}
public int GetNext()
{
uint nextNumber = unchecked((uint)System.Threading.Interlocked.Increment(ref _currentNumber));
int result = (int)(nextNumber % _max);
return result;
}
}
}
And here is a .net fiddle running this code.
The trick is to do the operation in a loop until it is successful. I provide a general template for this approach in my answer here.
public int GetNextNumber()
{
int initial, computed;
do
{
initial = _lastNumber;
computed = initial + 1;
computed = computed > _maxNumbers ? computed = 1 : computed;
}
while (Interlocked.CompareExchange(ref _lastNumber, computed, initial) != initial);
return computed;
}
Not sure if if helps anyone but this could be even simpler:
class RoundRobinNumber
{
private int _maxNumbers = 10;
private int _lastNumber = 0;
public RoundRobinNumber(int maxNumbers)
{
_maxNumbers = maxNumbers;
}
public int GetNextNumber()
{
int nextNumber = Interlocked.Increment(ref _lastNumber);
int result = nextNumber % _maxNumbers;
return result >= 0 ? result : -result;
}
}
Usually round-robin is used to select an item from a collection. Based on Alex's answer I made a RoundRobinCollection variant.
public class RoundRobinCollection<T>
{
private readonly ReadOnlyCollection<T> _collection;
private int _currentNumber = -1;
public RoundRobinCollection(IEnumerable<T> enumerable)
{
_collection = new List<T>(enumerable).AsReadOnly();
if (!_collection.Any())
{
throw new InvalidOperationException("Cannot use empty collection for RoundRobinCollection.");
}
}
public T GetNext()
{
var index = GetNextIndex();
return _collection[index];
}
private int GetNextIndex()
{
// This increments the currentNumber in a Thread-safe way, and deals with exceeding int.MaxValue properly
var nextNumber = unchecked((uint)Interlocked.Increment(ref _currentNumber));
return (int)(nextNumber % _collection.Count);
}
}
Usage example:
public class SomeClient
{
private readonly RoundRobinCollection<ServerConfig> _serverConfigs;
public SomeClient(List<ServerConfig> serverConfigs)
{
_serverConfigs = new RoundRobinCollection<ServerConfig>(serverConfigs);
}
public void DoSomething(){
var serverConfig = _serverConfigs.GetNext();
// Do something with current serverConfig
}
}