Yahtzee question
BlitzMax Forums/BlitzMax Beginners Area/Yahtzee question
| ||
I've been trying to make a yahtzee port and am having trouble with rolling the die. I can roll the first one just fine, but when I try to change the numberofrolls variable in the roll() function, I can't keep the first roll and then roll my second time. Any suggestions?Strict AppTitle="Yahtzee Port by ZaChO" Graphics 600,600 SeedRnd MilliSecs() AutoMidHandle False Const NUMBEROFDICE = 6 Const MAXROLLS = 3 Global ROLLSLEFT = 3 Type Dice1 Field number:Int Field number2:Int Field number3:Int End Type Type Dice2 Field number:Int Field number2:Int Field number3:Int End Type Type Dice3 Field number:Int Field number2:Int Field number3:Int End Type Type Dice4 Field number:Int Field number2:Int Field number3:Int End Type Type Dice5 Field number:Int Field number2:Int Field number3:Int End Type Type Dice6 Field number:Int Field number2:Int Field number3:Int End Type Global diceuno:Dice1 = New Dice1 Global dicedos:Dice2 = New Dice2 Global dicetres:Dice3 = New Dice3 Global dicequatro:Dice4 = New Dice4 Global dicecinco:Dice5 = New Dice5 Global diceseis:Dice6 = New Dice6 While Not KeyDown(KEY_ESCAPE) Cls DrawText"---------------------------YAHTZEE PORT BY ZACHO-----------------------------",0,0 If KeyHit(KEY_SPACE) And ROLLSLEFT <> 2 And ROLLSLEFT <> 1 roll() ROLLSLEFT = 2 EndIf If KeyHit(KEY_SPACE) And ROLLSLEFT = 2 roll2() ROLLSLEFT = 1 EndIf If KeyHit(KEY_SPACE) And ROLLSLEFT = 1 roll3() ROLLSLEFT = 0 EndIf ' 'YAHTZEE CHECK ' If diceuno.number = 1 And dicedos.number = 1 And dicetres.number = 1 And dicequatro.number = 1 And dicecinco.number = 1 And diceseis.number = 1 DrawText "YAHTZEE!!!!",400,400 EndIf If diceuno.number = 2 And dicedos.number = 2 And dicetres.number = 2 And dicequatro.number = 2 And dicecinco.number = 2 And diceseis.number = 2 DrawText "YAHTZEE!!!!",400,400 EndIf If diceuno.number = 3 And dicedos.number = 3 And dicetres.number = 3 And dicequatro.number = 3 And dicecinco.number = 3 And diceseis.number = 3 DrawText "YAHTZEE!!!!",400,400 EndIf If diceuno.number = 4 And dicedos.number = 4 And dicetres.number = 4 And dicequatro.number = 4 And dicecinco.number = 4 And diceseis.number = 4 DrawText "YAHTZEE!!!!",400,400 EndIf If diceuno.number = 5 And dicedos.number = 5 And dicetres.number = 5 And dicequatro.number = 5 And dicecinco.number = 5 And diceseis.number = 5 DrawText "YAHTZEE!!!!",400,400 EndIf If diceuno.number = 6 And dicedos.number = 6 And dicetres.number = 6 And dicequatro.number = 6 And dicecinco.number = 6 And diceseis.number = 6 DrawText "YAHTZEE!!!!",400,400 EndIf drawHUD() drawROLLS() Flip Wend Function drawHUD() SetColor Rand(0,255),Rand(0,255),Rand(0,255) DrawText"Click <SpaceBar> to roll",300,300 SetColor 255,255,255 End Function Function drawROLLS() SetColor 255,0,0 DrawText"*****Roll #1*****",0,90 DrawText diceuno.number,0,110 DrawText dicedos.number,10,110 DrawText dicetres.number,20,110 DrawText dicequatro.number,30,110 DrawText dicecinco.number,40,110 DrawText diceseis.number,50,110 ' SetColor 0,255,0 DrawText"*****Roll #2*****",0,130 ' DrawText diceuno.number2,0,150 DrawText dicedos.number2,10,150 DrawText dicetres.number2,20,150 DrawText dicequatro.number2,30,150 DrawText dicecinco.number2,40,150 DrawText diceseis.number2,50,150 ' SetColor 0,0,255 DrawText"*****Roll #3*****",0,170 DrawText diceuno.number3,0,190 DrawText dicedos.number3,10,190 DrawText dicetres.number3,20,190 DrawText dicequatro.number3,30,190 DrawText dicecinco.number3,40,190 DrawText diceseis.number3,50,190 SetColor 255,255,255 End Function Function roll() diceuno.number = Rand(1,6) dicedos.number = Rand(1,6) dicetres.number = Rand(1,6) dicequatro.number = Rand(1,6) dicecinco.number = Rand(1,6) diceseis.number = Rand(1,6) ROLLSLEFT=2 End Function Function roll2() diceuno.number2 = Rand(1,6) dicedos.number2 = Rand(1,6) dicetres.number2 = Rand(1,6) dicequatro.number2 = Rand(1,6) dicecinco.number2 = Rand(1,6) diceseis.number2 = Rand(1,6) ROLLSLEFT=1 End Function Function roll3() diceuno.number3 = Rand(1,6) dicedos.number3 = Rand(1,6) dicetres.number3 = Rand(1,6) dicequatro.number3 = Rand(1,6) dicecinco.number3 = Rand(1,6) diceseis.number3 = Rand(1,6) ROLLSLEFT=0 End Function |
| ||
I took just the quickest of glances and noticed that you have six different types, all of them identical. I really wish you'd stick to one program and fixing everything that's wrong with it instead of just going from one broken program to the next without stopping to fix all the errors with the last one. |
| ||
I agree with Gabriel, you should stick to one project until you master it. You only need one Dice type. EDIT: The reason none of your other rolls are going through is because calling KeyHit nulls the state for the given key when it polls it. |
| ||
@Gabriel-I'm trying to get some accomplishment by trying to make simpler (text-based) programs. If I managed to fix my errors (by the way making 200+ help posts), I would be in my late-fifties. It takes me that long...seriously... |
| ||
@Plash-Do I create an array? Dice[number:Int,number2:Int,number3:Int] EDIT: The reason none of your other rolls are going through is because calling KeyHit nulls the state for the given key when it polls it. My program isn't affected by the state of the spacebar. Im only trying to get at is I want a variable to change when the func is called so I can go to roll #2, instead of repeating roll #1. |
| ||
@Gabriel-I'm trying to get some accomplishment by trying to make simpler (text-based) programs. So we can safely assume that this is the program you're going to be working on until it's fixed, can we? And there won't be a completely new one in two days time while this one carries on unanswered? My program isn't affected by the state of the spacebar. How do you figure? There are three if..endif sections all of which are only executed if the spacebar has been hit. They all contain the call to the roll functions. Unless you happen to press the space button on the minute fraction of a second between the first and third if statements, the second and third ones will never be true. Which is exactly what Plash told you. |
| ||
why do you keep on doing this? Type Dice1 Field number:Int Field number2:Int Field number3:Int End Type Type Dice2 Field number:Int Field number2:Int Field number3:Int End Type Type Dice3 Field number:Int Field number2:Int Field number3:Int End Type Type Dice4 Field number:Int Field number2:Int Field number3:Int End Type Type Dice5 Field number:Int Field number2:Int Field number3:Int End Type Type Dice6 Field number:Int Field number2:Int Field number3:Int End Type [edited] another thing the keyhit should be like this: If KeyHit(KEY_SPACE) If ROLLSLEFT = 3 roll() ElseIf ROLLSLEFT = 2 roll2() ElseIf ROLLSLEFT = 1 roll3() EndIf EndIf |
| ||
why do you keep on doing this? Heh :-) Aren't there only 5 dice in Yahtzee? But anyway... you may want to sit down and think a bit more before you start banging away at the keyboard. So, you get (up to) three rolls of (let's say) 5 dice. How might you represent this? If we break that down further to a single roll of 5 dice, you can see that you could, in theory, have one thing to store 5 numbers. Our one thing could be a Type.. Type TDice End Type Our 5 numbers may well be an array of Ints of size 5. We could store this our Type... Type TDice Field numbers:Int[5] End Type One nice thing about Types, is that you can add Methods to them. So perhaps we want a Roll() method, to indicate we want to roll some dice.. Type TDice Field numbers:Int[5] Method Roll() End Method End Type But what are we rolling? 5 Dice? Well... sometimes... On the first roll, yes. On the second, according to the rules, you might only want to roll the 2nd and 4th dice. How might you solve that problem? One way might be to define which dice are actually rolled during Roll(). To keep things simple, why don't we add some parameters to indicate which dice is being rolled this time... Type TDice Field numbers:Int[5] Method Roll(d1:int, d2:int, d3:Int, d4:int, d5:int) End Method End Type We could use 1 to indicate a roll is required, and 0 to indicate that no roll is required... So, for our first roll, we could call our Roll() method like this : dice.Roll(1, 1, 1, 1, 1) (this assumes that "dice" is an object) Now, how might we actually roll the dice? Keeping things simple, we'll just check each parameter and roll if required: Type TDice Field numbers:Int[5] Method Roll(d1:Int, d2:Int, d3:Int, d4:Int, d5:Int) If d1 Then numbers[0] = Rand(1, 6) End If If d2 Then numbers[1] = Rand(1, 6) End If If d3 Then numbers[2] = Rand(1, 6) End If If d4 Then numbers[3] = Rand(1, 6) End If If d5 Then numbers[4] = Rand(1, 6) End If End Method End Type There are of course more efficient ways to do this, but this should keep things clear. What about the second roll? Well, if the player decided to roll the 2nd and 4th dice again, you could call Roll() with the following parameters : dice.Roll(0, 1, 0, 1, 0) Much of writing code is deciding what needs to be done. Then you need to think about how you might implement it. Write some code, see if it does what you want... if not, tweak it a little - or even go back to the drawing board and start over with your ideas. But thinking about the problem is quite important :-) |
| ||
Heh :-) he knows what I am talking about: http://www.blitzmax.com/Community/posts.php?topic=84372#953894 @Brucey Good luck getting through. ;) he is too inpatient. doesn't take the time to learn one thing when he is already jumping to 10 others and that is what is slowing him down. @Zacho, Dont take it personal it's just what I think based on my experiences. |
| ||
@Jesse-@Brucey- Its true, very true. I am sorta impatient. Lol @Gabriel- So we can safely assume that this is the program you're going to be working on until it's fixed, can we? And there won't be a completely new one in two days time while this one carries on unanswered? You can never be sure of that :) How do you figure? There are three if..endif sections all of which are only executed if the spacebar has been hit. They all contain the call to the roll functions. Unless you happen to press the space button on the minute fraction of a second between the first and third if statements, the second and third ones will never be true. Which is exactly what Plash told you. I was just a little unsure of his wording. @Brucey- Aren't there only 5 dice in Yahtzee? Typo Your explanation of my code is awesome! And I'd listen to Jesse. Giving me the code isn't ganna solve my questions, its only going to give me answers. But I really truly appreciate your time on my Yahtzee port. Really do, honestly. I'm actually still happy that everyone hasn't left me yet....Lol Btw: Im still reading the noob guide. |
| ||
Here is the work-in-progress. Please don't comment as I will try to figure this game out myself (for once, lol) :) |
| ||
Looking good Zacho! :) You're using very "static" code right now, you should try to think more dynamiclly :) For example: Function roll() dice.Roll(1, 1, 1, 1, 1) ROLLSLEFT=2 End Function Function roll2() dice.Roll(1,1,1,1,1) ROLLSLEFT=1 End Function Function roll3() dice.Roll(1,1,1,1,1) ROLLSLEFT=0 End Function Could be replaced by 1 function, like this: Function roll() dice.Roll(1, 1, 1, 1, 1) ROLLSLEFT = ROLLSLEFT - 1 'ROLLSLEFT:-1 'Works aswell, but the other way is easier to see :) End Function Which just substracts 1 from ROLLSLEFT each time you call it, instead of declaring ROLLSLEFT to something static each time :) (I hope you get what I mean :P) |
| ||
Function drawROLLS() ... ... End Function could be replaced with Function drawROLLS() local y:int = 0 If ROLLSLEFT = 3 SetColor 255,0,0 y = 90 else If ROLLSLEFT = 2 SetColor 0,0,255 y = 110 else If ROLLSLEFT = 1 SetColor 0,255,0 y = 130 endif DrawText "*****Roll #"+(4-ROLLSLEFT)+"*****",0,y DrawText dice.numbers[0],0,y+20 DrawText dice.numbers[1],10,y+20 DrawText dice.numbers[2],20,y+20 DrawText dice.numbers[3],30,y+20 DrawText dice.numbers[4],40,y+20 SetColor 255,255,255 End Function What should my code-replacement show off? You see that certain parts of your code are similar or nearly the same, cutting down repeated elements to one call will make it easier to make bugfixes or changes because eg. only one line has to be changed instead of 3. Going further would change: DrawText dice.numbers[0],0,y+20 DrawText dice.numbers[1],10,y+20 DrawText dice.numbers[2],20,y+20 DrawText dice.numbers[3],30,y+20 DrawText dice.numbers[4],40,y+20 into For local i:int = 0 to 4 DrawText dice.numbers[i],i*10,y+20 Next But like obvious this all is rather cosmetic than functional in its changes. bye MB EDIT: @thareh Could be replaced by 1 function, like this: Function roll() dice.Roll(1, 1, 1, 1, 1) ROLLSLEFT = ROLLSLEFT - 1 'ROLLSLEFT:-1 'Works aswell, but the other way is easier to see :) End Function isn't exactly the same thing, consider using Function roll() dice.Roll(1, 1, 1, 1, 1) ROLLSLEFT = Max(0, ROLLSLEFT - 1) End Function The Max-function takes care of variable ROLLSLEFT decreasing to negative values. |
| ||
I personally don't think that ROLLSLEFT should be global or inside the function. the "max" or "if" statement should be kept in the main loop. |
| ||
@Thareh- Could be replaced by 1 function, like this: Function roll() dice.Roll(1, 1, 1, 1, 1) ROLLSLEFT = ROLLSLEFT - 1 'ROLLSLEFT:-1 'Works aswell, but the other way is easier to see :) End Function Ok, but what if the player wants to hold a certain die? Eh? That is why I have it like this for the moment: Function roll() dice.Roll(1, 1, 1, 1, 1) ROLLSLEFT=2 End Function Function roll2() dice.Roll(1,1,1,1,1) ROLLSLEFT=1 End Function Function roll3() dice.Roll(1,1,1,1,1) ROLLSLEFT=0 End Function Which just substracts 1 from ROLLSLEFT each time you call it, instead of declaring ROLLSLEFT to something static each time :) (I hope you get what I mean :P) Ya, your saying its easier to type ROLLSLEFT:-1 @MichaelB Wow, you are a very clever person. I would have never thought of this: Function drawROLLS() local y:int = 0 If ROLLSLEFT = 3 SetColor 255,0,0 y = 90 else If ROLLSLEFT = 2 SetColor 0,0,255 y = 110 else If ROLLSLEFT = 1 SetColor 0,255,0 y = 130 endif DrawText "*****Roll #"+(4-ROLLSLEFT)+"*****",0,y DrawText dice.numbers[0],0,y+20 DrawText dice.numbers[1],10,y+20 DrawText dice.numbers[2],20,y+20 DrawText dice.numbers[3],30,y+20 DrawText dice.numbers[4],40,y+20 SetColor 255,255,255 End Function Very well done. Thanks for the tip! :) As well as this snippet of code: For local i:int = 0 to 4 DrawText dice.numbers[i],i*10,y+20 Next [b][u]Here is one question to ask before I procede; what method should I use to allow the user to keep the die he/she wants. I want to say with a mouseclick or something but I'm not sure what is best. What do you guys think? |
| ||
As you want it textbased you could wait for userinputGlobal DiesHold:int[5] 'inside mainloop 'the formula value = 1 - value is used to switch between 1 and 0 as result if KeyHit(KEY_1) then DiesHold[0] = 1 - DiesHold[0] .. if KeyHit(KEY_5) then DiesHold[4] = 1 - DiesHold[4] '---- 'draw part Function drawROLLS() local y:int = 0 If ROLLSLEFT = 3 SetColor 255,0,0 y = 90 else If ROLLSLEFT = 2 SetColor 0,0,255 y = 110 else If ROLLSLEFT = 1 SetColor 0,255,0 y = 130 endif DrawText "*****Roll #"+(4-ROLLSLEFT)+"*****",0,y for local i:int = 0 to 4 if DiesHold[i] SetColor 150,150,150 DrawText (dice.numbers[i],0 + i*10,y+20) else SetColor 255,255,255 DrawText (dice.numbers[i],0 + i*10,y+20) endif Next SetColor 255,255,255 End Function bye MB |