How to make unity not pick the same number twice? - c#

The program is a simple number guessing game however when i randomize the guesses unity tends to pick the same number multiple times is there a way to have it know what numbers it already picked? an also is there a way to make it automatically go to the lose scene if it can't pick another number? any help is appreciated ^_^
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class NumberGuesser : MonoBehaviour {
int min;
int max;
int guess;
int maxGuessesAllowed = 15;
public Text text;
//guess = (max + min) / 2;
// Use this for initialization
void Start () {
min = 1;
max = 1000;
NextGuess();
max = max + 1;
}
// Update is called once per frame
public void guessHigher () {
min = guess;
NextGuess ();
}
public void guessLower() {
max = guess;
NextGuess();
}
void NextGuess(){
guess = (max + min) / 2;
//guess = Random.Range (min,max);//Randomizes Guesses
//print (guess);
text.text = guess.ToString ();
maxGuessesAllowed = maxGuessesAllowed - 1;
if (maxGuessesAllowed <= 0) {
Application.LoadLevel ("Win");
}
}
}//main

Try this:
List<int> alreadyGuessed = new List<int>();
...
int NextGuess()
{
int theGuess = Random.Range(min, max);
while(alreadyGuessed.Contains(theGuess))
theGuess = Random.Range(min, max);
alreadyGuessed.Add(theGuess);
return theGuess;
}
It keeps track of what has been guessed and keeps on guessing until the guess has not been guessed before.

Just add this at top of your code
List<int> used = new List<int>();
you may want to add this using too
using System.Collections.Generic;
and then change your NextGuess function to this
void NextGuess()
{
guess = Random.Range (min,max);
while(used.Contains(guess))
guess = Random.Range (min,max);
used.Add (guess);
text.text = guess.ToString ();
maxGuessesAllowed = maxGuessesAllowed - 1;
if (maxGuessesAllowed <= 0) {
Application.LoadLevel ("Win");
}
}

Related

How do you add a new player life in C# when you get a certain score?

This seems very simple, but I can't seem to figure it out. Here is the code:
if(score >= 3000)
{
FindObjectOfType<GameSession>().AddLife();
}
The problem is that once I've reached and surpassed 3000, the condition is such that my score is always above 3000 and so a new life keeps getting added ad infinitum. If I just use '=' operand, however, my score could just jump above 3000 without equaling it and the life will not be added. How do I just add a single life when the score equals or is greater than 3000?
Any help would be much appreciated.
You need some sort of control for that.
For example :
bool isAdded = false; // add this outside of the method that contains if statement
if(score >= 3000)
{
if(!isAdded){
FindObjectOfType<GameSession>().AddLife();
isAdded = true;
}
}
And reset it anywhere you like. For example when the game resets. isAdded = false
Try adding a class field that is not just a static number, 3000, but that you can increase as the player passes each score to beat.
static int _lives = 1;
static int _increment = 3000;
static void Main(string[] args)
{
int scoreToBeat = 0;
for (int i = 0; i < 5000; i++)
{
var score = i;
if (score >= scoreToBeat)
{
AddLife();
scoreToBeat += _increment;
}
}
}
static void AddLife()
{
_lives += 1;
}

Application freezes just after goin back from desktop to app (on android device)

It tooks a lot of time to unfreeze (but sometimes it just crashes).
I was debugging whole code to find a place where the problem is and I found that there's something wrong while I was saving things to Player Prefs.
My "idea" why it is causing. Multiple times getting and setting prefs with different values.
Test code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class test : MonoBehaviour
{
[SerializeField]
private Image bg;
[SerializeField]
private Text text;
//private void Start()
//{
// PlayerPrefs.SetString("dd", "x");
//}
//Update is called once per frame
//bool was = false;
int counter = 0;
System.DateTime lastUpdate;
bool active = false;
List<string> tmp = new List<string>() { "5", "7" };
private void Start()
{
lastUpdate = System.DateTime.UtcNow;
}
void Update()
{
System.DateTime now = System.DateTime.UtcNow;
System.TimeSpan diff = now - lastUpdate;
text.text = diff.ToString();
if (diff.TotalSeconds > 10)
{
active = !active;
lastUpdate = now;
}
if (active)
{
bg.color = Color.green;
//if ((System.DateTime.UtcNow - xyz).TotalSeconds > 5)
//if (counter > 5)
//{
//if (!was)
//{
// Debug.Log("XX_update");
//}
//was = true;
//string x = PlayerPrefs.GetString("dd");
for (int i = 0; i < 20; i++)
{
string x = PlayerPrefs.GetString("dd");
Set(5, i);
//string x = PlayerPrefs.GetString(CommonMethods.RandomString(5));
}
//}
//else
//{
// was = false;
// counter++;
//}
}
else
{
bg.color = Color.red;
}
}
private System.DateTime xyz = System.DateTime.UtcNow;
public void OnApplicationFocus(bool focus)
{
counter = 0;
Debug.Log("XX_onappfocus");
xyz = System.DateTime.UtcNow;
}
public void Set(double value, int x = 0)
{
//PlayerPrefs.SetString(name, value.ToString("E3"));
//string costam = random.NextDouble().ToString();
//PlayerPrefs.SetString(name, costam);
//UnityEngine.Debug.Log("XX_" + costam);
//List<string> tmp = new List<string>() { "98754.38238715351", "98754.38238415351" };
//string result = tmp.RandomElement();
string result = tmp[x % 2];
//PlayerPrefs.SetString(name, result);
PlayerPrefs.SetString("dd", result);
//PlayerPrefs.SetString(name, "1.054E+003");
}
}
I was thinking that maybe there's a problem with double's precision, but it wasn't. Then I checked if it is caused by parsing inside setstring methods, but it wasn't. Problem isn't connected with a key, so it can be random.
If you want to check this try to build this code with 2 different values in tmp string list (now it's 5 and 7) and there will be bug, then change these values to the same (f.e. 5 and 5). Problem will disappear. Also you can delete get or set from FOR loop and problem will also disappear.
I also made a tricky switch inside Update method to check if it is connected with this get / set pair so you can check it too.
Sorry for my english guys but this problem is so complex that I even don't know how to describe it. I am trying to solve it for 3 days (we need to solve this or make a 'walk around' because we can't use that app without this).
Thanks in advance.

Random Number Generator C#

I'm trying to get my program to start the user with 20 lives and while Lives is greater than 0, flip a coin (random number generator 0(Tails) or 1(Heads)). Every time the user gets Heads it adds 1 to Heads counter and 1 to Flips counter. Every time the user gets Tails it takes 1 from Lives and adds 1 to Flips counter. I think my only problem is my random number generator!? Please be kind, total n00b :)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Coin_Flip_2015
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Random r = new Random(1);
private void cmdFlipCoin_Click(object sender, EventArgs e)
{
int rand = r.Next(1);
int Heads;
int counterFlips;
int Lives;
Lives = 20;
Heads = 0;
counterFlips = 0;
while (Lives > 0)
if (rand == 0)
{
Lives = Lives -= 1;
counterFlips++;
}
else if (rand == 1)
{
Heads = Heads += 1;
counterFlips++;
}
lblFlips.Text = "Flips = " + counterFlips.ToString();
lblHeads.Text = "Heads = " + Heads.ToString();
lblLivesLeft.Text = "Lives Left = " + Lives.ToString();
MessageBox.Show("sorry you are out of lives m8");
}
}
}
The Random.Next(int) method
Returns a non-negative random integer that is less than the specified maximum.
So r.Next(1) is always 0. Use r.Next(2) to get 0 or 1.
You should also move the rand = r.Next(1); inside the while loop. Now it's only assigned once, at the beginning of the method.
I'll take a swing at fixing all the issues:
public partial class Form1 : Form
{
int Heads, counterFlips, Lives;
public Form1()
{
InitializeComponent();
Lives = 20;
Heads = 0;
counterFlips = 0;
}
private Random r = new Random();
private void cmdFlipCoin_Click(object sender, EventArgs e)
{
int rand = r.Next(2);
if (Lives > 0)
{
if (rand == 0)
{
Lives -= 1;
counterFlips++;
}
else
{
Heads += 1;
counterFlips++;
}
}
else
MessageBox.Show("sorry you are out of lives m8");
lblFlips.Text = "Flips = " + counterFlips.ToString();
lblHeads.Text = "Heads = " + Heads.ToString();
lblLivesLeft.Text = "Lives Left = " + Lives.ToString();
}
}
Issues:
The Heads, counterFlips and Lives variables were stored locally, they need to be global
The code was changed so that you flip a coin each time you click the button (changed the while to an if). while loops that have the capability of never exiting should not be used in UI threads.
private Random r = new Random() notice removed the 1, use the default constructor to seed it properly.
Added an "else" to show when the lives were used, it shows your message
Changed the Lives = Lives -= 1 (same with Heads) to proper code
Used r.Next(2) to get either 0 or 1, since the upper bound is exclusive.
Other than that, I'm not sure what you are doing with the Lives and Heads numbers, so I'll leave that up to you to fix.
Here one that is a bit different.. snap beat me by a few seconds!
public partial class Form1 : Form
{
// Leave the seed alone on this line
private readonly Random _r = new Random();
// these need to be outside of your Click event
private int _counterFlips;
private int _heads;
private int _lives = 20;
public Form1()
{
InitializeComponent();
}
private void cmdFlipCoin_Click(object sender, EventArgs e)
{
// x = starting number, y = ending number + 1
// This should be either a zero or one:
int rand = _r.Next(0, 2);
switch (rand)
{
default:
_lives --;
_counterFlips++;
break;
case 1:
_heads ++;
_counterFlips++;
break;
}
if (_lives < 1)
{
MessageBox.Show(#"sorry you are out of lives m8");
button1.Enabled = false;
return;
}
lblFlips.Text = #"Flips = " + _counterFlips;
lblHeads.Text = #"Heads = " + _heads;
lblLivesLeft.Text = #"Lives Left = " + _lives;
}
}

How to add integers in different methods

I'm very new to C# and have a very limited understanding of the "proper code" to use. I had the goal to imitate the old Pokemon battle systems as best I could with what I know and am having a hard time linking a stored int value for HP between two methods (assuming that's the right word), to calculate new Hp when the second method interacts with the main method. Had a hard time finding an answer for that in searches so here is the code:
" static void Main(string[] args)
{
Random Gen = new Random();
int enemyhealth = (150);
int playerhealth = (100); //the line i need to use
int edefense = (20);
int pattack = (30);
int rate = Gen.Next(1,5);
int critical = 0; "
static void enemyattack()
{
Random Gen1 = new Random();
int pdefense = (20);
int eattack = (20);
int erate = Gen1.Next(1, 5);
int ratattack = Gen1.Next(1,3);
int critical1 = 0;
Console.WriteLine("Enemy Ratta gets ready!");
Console.ReadKey();
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("\nEnemy Ratta attacks!\n");
Console.WriteLine("----------------------------------------------------------------------------");
ratattack = Gen1.Next(1,3);
if (ratattack = 1)
{
Console.WriteLine("Enemy Ratta used Tail Whip!");
pdefense = (pdefense - erate);
Console.ReadKey();
Console.WriteLine("----------------------------------------------------------------------------");
erate = Gen1.Next(1, 5);
if (erate <= 3)
{
Console.WriteLine("\nIt wasn't very effective!");
}
else
{
Console.WriteLine("\nIt was super effective!");
}
Console.WriteLine("Squirtle's Defense decreased by " + erate + "");
Console.WriteLine("----------------------------------------------------------------------------");
}
else if (ratattack == 2)
{
Console.WriteLine("\nRatta used Tackle");
erate = Gen1.Next(1, 5);
if (erate >= 5)
{
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("\nCRITICAL HIT!!!!");
Console.WriteLine("----------------------------------------------------------------------------");
Console.WriteLine("----------------------------------------------------------------------------\n");
Console.ReadKey();
Console.WriteLine("It was super effective!");
Console.ReadKey();
eattack = eattack + 10;
}
else
{
critical1 = Gen1.Next(1, 5);
eattack = critical1 + eattack;
}
phealth = Math.Abs((eattack - pdefense) - playerhealth); ***//This Line is where I'm having trouble because phealth is used in my first method as a stored integer and the new calculation for phealth won't interact with the phealth in the origional main, i simply belive I haven't learned that part of c#, I only have 5 hours of youtube tutorials.***
Console.WriteLine("Ratta dealt " + Math.Abs(eattack - pdefense) + " damage!");
eattack = 30;
Console.WriteLine("\n----------------------------------------------------------------------------");
Console.ReadKey();
Console.ReadKey();
}
}
}
}
Make Static method , or simply add your variable in the main Class (where Main method Stored)
Here example
class Program
{
int HP;
int Main()
{
HP=0; //Now you HP is 0;
Method();
}
void Method()
{
HP+=50; //Now you HP is 50
}
}
I would break things down into separate classes. For example you should have a Player class that contains all the information for the player. You can't have methods like that in your main program. You need to keep everything separate. Make a class for each object you need.
public class Player
{
int currentHp = 100;
int maxHp = 100;
int atkPower = 20;
int defense = 20;
string playerName = "Ashe"
public Player() {}
public void TakeDamage(int damage)
{
currentHp = currentHp - damage;
}
}
public class Enemy
{
int currentHp = 100;
int maxHp = 100;
int atkPower = 20;
int defense = 20;
string enemyName= "Rattata"
public Enemy(){}
public int AttackPlayer(Player player)
{
// all of your attack logic, pass in the player here
player.TakeDamage(someAmountofDamage);
}
}
Then in your main program:
static void Main(string[] args)
{
Player myPlayer = new Player();
Enemy myEnemy = new Enemy();
myEnemy.AttackPlayer(player);
}

dice rolling in C# console application giving incorrect totals

I am writing dice roller program in C# console. I am giving two input
Enter the size of the dice and
Enter how times you want to play.
Suppose dice size is 6 and 10 times i have played.
Output is coming:
1 was rolled 2 times
2 was rolled 7 times
3 was rolled 8 times
4 was rolled 7 times
5 was rolled 4 times
6 was rolled 5 times
Total: 33 (its not fixed for every execution this no will be changed)
But my requirement was this total always should be number of playing times. Here I am playing 10 times so the total should be 10 not 33. It should happen for every new numbers... If I play 100 times sum or total should be 100 only not any other number. rest all will be remain same, in my programing not getting the expected sum. Please somebody modify it. Here is my code:
Dice.cs:
public class Dice
{
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
this._DiceSize = dicesize;
}
public string Roll()
{
if (_DiceSize<= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
Random rnd = new Random();
Int32[] roll = new Int32[_DiceSize];
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay=Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
obj.Roll();
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}
It looks to me like you're getting the math backwards... shouldn't it be:
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
Or if you want the actual rolls:
// to capture individual rolls
int[] roll = new int[_NoOfDice];
for (int i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(_DiceSize) + 1; // note upper bound is exclusive, so +1
}
You are creating a new Random instance on each iteration. This is not a good thing as it will affect the uniform distribution of results. Keep the Random instance in a field instead of creating a new one every time.
public class Dice {
private Random rnd = new Random();
// ... don't create a new random in `Roll` method. Use `rnd` directly.
}
First of all, the following for-loop is wrong:
for (Int32 i = 0; i < _DiceSize; i++)
{
roll[i] = rnd.Next(1,_NoOfDice);
}
Obviously you switched _DiceSize and _NoOfDice. The correct loop would look like
for (Int32 i = 0; i < _NoOfDice; i++)
{
roll[i] = rnd.Next(1,_DiceSize);
}
Because of that, the line
Int32[] roll = new Int32[_DiceSize];
has to be changed to
Int32[] roll = new Int32[_NoOfDice];
Maybe you should think about renaming these variables, so it's more clearly, which means what.
If you modify your code that way, you will mention that your analisys won't work that way you implemented it. Actually, what you are showing is the result of each throw, which is not what you want, if I understood you right.
UPDATE:
Sorry, I misunderstood you. You do want to show the result for every roll. So, why don't you just move the StringBuilder.AppendFormat to your "rolling-for-loop"?
UPDATE #2:
For me, the following Die-class works exactly the way you want it:
public class Die
{
private int maxValue;
private int numberOfRolls;
private Random random;
public Die(int maxValue, int numberOfRolls)
{
this.maxValue = maxValue;
this.numberOfRolls = numberOfRolls;
this.random = new Random();
}
public string Roll()
{
StringBuilder resultString = new StringBuilder();
for (int i = 0; i < this.numberOfRolls; i++)
{
resultString.AppendFormat("Roll #{0} - Result: {1}" + Environment.NewLine, i + 1, this.random.Next(1, maxValue + 1));
}
return resultString.ToString();
}
}
Hope I could help you.
This is the full code you have to use, according to Mehrdad and Marc Gravell.
Have fun.
public class Dice
{
private Random rnd = new Random();
Int32 _DiceSize;
public Int32 _NoOfDice;
public Dice(Int32 dicesize)
{
if (dicesize <= 0)
{
throw new ApplicationException("Dice Size cant be less than 0 or 0");
}
this._DiceSize = dicesize;
}
public string Roll()
{
if (_NoOfDice <= 0)
{
throw new ApplicationException("No of dice cant be less than 0 or 0");
}
// to capture just the counts
int[] roll = new int[_DiceSize];
for (int i = 0; i < _NoOfDice; i++)
{
roll[rnd.Next(roll.Length)]++;
}
StringBuilder result = new StringBuilder();
Int32 Total = 0;
Console.WriteLine("Rolling.......");
for (Int32 i = 0; i < roll.Length; i++)
{
Total += roll[i];
result.AppendFormat("{0}:\t was rolled\t{1}\t times\n", i + 1, roll[i]);
}
result.AppendFormat("\t\t\t......\n");
result.AppendFormat("TOTAL: {0}", Total);
return result.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter no of dice size");
int dicesize = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many times want to play");
int noofplay = Convert.ToInt32(Console.ReadLine());
Dice obj = new Dice(dicesize);
obj._NoOfDice = noofplay;
Console.WriteLine(obj.Roll());
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
}

Categories