Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0

    Error message when running this procedure


    As a part of the Yahtzee game, a score for 'three of a kind' is awarded if there are three dice the same. The score is the total of all the dice in the hand. I have written the following code to score this, but get the error:

    ---------------------------
    Access violation at address 00470A7E in module 'yahtzeeproj.exe'. Read of address 0000000F.
    ---------------------------

    I know there must be something wrong in my code, but I am a beginner, and can't see what. Thanks for any help at all.

    Code:
    procedure SortArray; {Sorting}
    Var
      Temp, I, J : Integer;
    begin
      For I := 1 to 4 do
    	  For J := I+1 to 5 do
    	      If DiceArray[J].Tag < DiceArray[I].Tag
    	        then begin
    		        Temp := DiceArray[I].Tag;
    		        DiceArray[I].Tag := DiceArray[J].Tag;
    		        DiceArray[J].Tag := Temp;
    		     end;
    end;
    
    
    
    procedure TYahtzeeFrm.ThreeKindEdtClick(Sender: TObject);
    Var
      DiceTotal, Num : Integer;
    begin
      DiceTotal := 0;
    
      SortArray;
    
      if ThreeKindEdt.Text = '' then
        begin
          For Num := 1 to 5 do begin
            if (DiceArray[Num].Tag = DiceArray[Num+1].Tag) and
               (DiceArray[Num+1].Tag = DiceArray[Num+2].Tag) then
                DiceTotal := DiceArray[Num].Tag + DiceTotal
                  end;
        end;
    Last edited by peglegmeg152; November 8th, 2011 at 05:20 AM. Reason: Left out section
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Mar 2006
    Posts
    2,469
    Rep Power
    1752
    I don't know the language in use but, a quick look makes me think that
    Code:
    (DiceArray[Num+1].Tag = DiceArray[Num+2].Tag)
    is causing in issue as the loop (for Num) is from 1 to 5, thus your subscripts will take on values up to 7, presumably outside the array - hence the access violation.
    The moon on the one hand, the dawn on the other:
    The moon is my sister, the dawn is my brother.
    The moon on my left and the dawn on my right.
    My brother, good morning: my sister, good night.
    -- Hilaire Belloc
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0
    Thanks, I have changed it and it now works, but does not add up each of the dice correctly. Can you see what the problem is?

    Code:
    procedure SortArray; {Sorting}
    Var
      Temp, I, J : Integer;
    begin
      For I := 1 to 4 do
    	  For J := I+1 to 5 do
    	      If DiceArray[J].Tag < DiceArray[I].Tag
    	        then begin
    		        Temp := DiceArray[I].Tag;
    		        DiceArray[I].Tag := DiceArray[J].Tag;
    		        DiceArray[J].Tag := Temp;
    		     end;
    end;
    
    procedure TYahtzeeFrm.ThreeKindEdtClick(Sender: TObject);
    Var
      DiceTotal, Num : Integer;
      Score : Boolean;
    begin
      DiceTotal := 0;
    
      SortArray;
    
      if ThreeKindEdt.Text = '' then
        begin
          For Num := 1 to 3 do begin
            if (DiceArray[Num].Tag = DiceArray[Num+1].Tag) and
               (DiceArray[Num+1].Tag = DiceArray[Num+2].Tag) then
                  Score := True else
                  Score := False;
                  end;
         end;
    
      if Score = True then
        For Num := 1 to 5 do
           DiceTotal := DiceArray[Num].Tag + DiceTotal;
    
      if Score = False then
        DiceTotal := 0;
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Mar 2006
    Posts
    2,469
    Rep Power
    1752
    Not adding up how?
    Just a personal style thing, I'd set Score to be false outside the loop and only set it to true inside the loop if your condition to check for three numbers being the same is true.
    Next, you need to exit the loop when you find three numbers the same - posit the situation when you have three 1s. Your loop will start at 1, and check for array[1]=array[2] and array[2]=array[3] which will be true, so yo set SCore to be true. All very good. Next time round the loop you'll check array[2]=array[3] (which will be true) and array[3]=array[4] (which will likely not be true) so you'll ste Score to false, ditto the next iteration. Thus, unless the three same numbers are the highest numbers rolled (appearing in array[3], array[4] and array[5]) you will end up with Score being false.

    You already preset the total to be 0 so there's no real need to have the check for Score being fale to set it to 0 again.
    The moon on the one hand, the dawn on the other:
    The moon is my sister, the dawn is my brother.
    The moon on my left and the dawn on my right.
    My brother, good morning: my sister, good night.
    -- Hilaire Belloc
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0
    Sorry to annoy you more, but I have another procedure that has to calculate if there is a low straight (a consecutive run of 4), and if so, give a score of 30. My code below gives 30 every time (i.e. never 0 if there is no straight). Can you see the issue?

    Code:
    procedure TYahtzeeFrm.LowStrtEdtClick(Sender: TObject);
    Var DiceTotal, Num : Integer;
        Score : Boolean;
    begin
      Score := False;
    
      SortArray;
    
      For Num := 1 to 4 do
        begin
          if DiceArray[Num].Tag = DiceArray[Num+1].Tag then
             DiceArray[Num].Tag := 10;
        end;
    
      SortArray;
    
      DiceTotal := 0;
    
      For Num := 1 to 2 do
        begin
          if (DiceArray[Num].Tag < DiceArray[Num+1].Tag) and
             (DiceArray[Num+1].Tag < DiceArray[Num+2].Tag) and
             (DiceArray[Num+2].Tag < DiceArray[Num+3].Tag) then
                Score := True;
         end;
    
      if Score then
        DiceTotal := 30 else
        DiceTotal := 0;
    end;
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0
    Also, going back to the original topic, here are some examples of the dice displayed and the score (sum) calculated:

    4,3,3,1,3 = 9
    1,2,1,4,1 = 4
    2,4,6,6,6 = 19

    I have changed the code a little:

    Code:
    procedure TYahtzeeFrm.ThreeKindEdtClick(Sender: TObject);
    Var
      DiceTotal, Num : Integer;
      Score : Boolean;
    begin
      DiceTotal := 0;
    
      SortArray;
    
      if ThreeKindEdt.Text = '' then
        begin
          Score := False;
          For Num := 1 to 3 do
          begin
            if (DiceArray[Num].Tag = DiceArray[Num+1].Tag) and
               (DiceArray[Num+1].Tag = DiceArray[Num+2].Tag) then
                  begin
                    Score := True;  //set to true if it is found
                    Break;          //leave for..loop, no sense continuing searvh
                  end
           end;
         end;
    
      if Score then
      begin
        For Num := 1 to 5 do
           DiceTotal := DiceArray[Num].Tag + DiceTotal;
      end
      else
        DiceTotal := 0;
    end;
    If you could give me ideas on this issue as well as the one i just posted, i would be very appreciative!!
  12. #7
  13. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Mar 2006
    Posts
    2,469
    Rep Power
    1752
    Originally Posted by peglegmeg152
    Sorry to annoy you more, but I have another procedure that has to calculate if there is a low straight (a consecutive run of 4), and if so, give a score of 30. My code below gives 30 every time (i.e. never 0 if there is no straight). Can you see the issue?
    [/code]
    Not an annoyance - don't worry!
    It may not be your whole issue, but that first for loop (and one of the sorts) can be tossed out! I think I know why you are doing it, but consider ... you have 5 dice, looking for 4 of them to be in a straight. What are the odds that the 5th die holds a value the same as one of the other 4? For example, 1, 1, 2, 3. 4 is still a low straight
    The moon on the one hand, the dawn on the other:
    The moon is my sister, the dawn is my brother.
    The moon on my left and the dawn on my right.
    My brother, good morning: my sister, good night.
    -- Hilaire Belloc
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Mar 2006
    Posts
    2,469
    Rep Power
    1752
    Originally Posted by peglegmeg152
    Also, going back to the original topic, here are some examples of the dice displayed and the score (sum) calculated:

    4,3,3,1,3 = 9
    1,2,1,4,1 = 4
    2,4,6,6,6 = 19

    .
    .
    .

    If you could give me ideas on this issue as well as the one i just posted, i would be very appreciative!!
    That looks better, one further small point, place the initial assignment of false to outside, just before, the if (just after the setting of DiceTotal to 0 would be good (I tend to like to have all that sort of thing in one, easy to find, place.

    Plus points for providing example numbers and totals! The third example, I think, exhibits the best display of the result of the issue - you have 5 EVEN numbers adding up to provide an ODD total ... cannot happen! Something is happening ,,, somewhere! Best way of debugging is to put a display of the numbers as they get processed in the loop that adds them up (output both the number to be added, and the result of the addition, with each loop round).
    The moon on the one hand, the dawn on the other:
    The moon is my sister, the dawn is my brother.
    The moon on my left and the dawn on my right.
    My brother, good morning: my sister, good night.
    -- Hilaire Belloc
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0
    Originally Posted by SimonJM
    Not an annoyance - don't worry!
    It may not be your whole issue, but that first for loop (and one of the sorts) can be tossed out! I think I know why you are doing it, but consider ... you have 5 dice, looking for 4 of them to be in a straight. What are the odds that the 5th die holds a value the same as one of the other 4? For example, 1, 1, 2, 3. 4 is still a low straight
    I put that in there because if the numbers are 1,2,2,3,4 for example, then i can't say if this number is less than this number, and this number is less than this number, and so on, because the two 2s would be equal! does that make sense? That's why i made it 10, so it would be out of the way, at the end. Do I not need to do this?


    Originally Posted by SimonJM
    The third example, I think, exhibits the best display of the result of the issue - you have 5 EVEN numbers adding up to provide an ODD total ... cannot happen! Something is happening ,,, somewhere! Best way of debugging is to put a display of the numbers as they get processed in the loop that adds them up (output both the number to be added, and the result of the addition, with each loop round).
    With this, sorry, but I don't know how to display the numbers? I am very new at this! can you just explain more what to do? thanks so much for all your help!
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Mar 2006
    Posts
    2,469
    Rep Power
    1752
    Ok - now sitting at leisure (as opposed to trying not to spill lunch over my keyboard ...) that (the setting duplicate numbers to 10 and re-sorting) is a nice bit of lateral thinking in determining a straight - so, ignore me and keep doing that!

    As for the displaying the values:

    Code:
      if Score then
      begin
        For Num := 1 to 5 do
           DiceTotal := DiceArray[Num].Tag + DiceTotal;
      end
    is what you have. After the addition you'd need to add an extra line, or two, (purely for debug purposes, so remove before releasing the code!) that will display the values. As I do not know the language you are using I don't know what the correct verb and syntax woudl be, but it'd be something like:

    Code:
    Print "Die value: " DiceArray[Num].Tag;
    Print "New running total: " DiceTotal;
    The moon on the one hand, the dawn on the other:
    The moon is my sister, the dawn is my brother.
    The moon on my left and the dawn on my right.
    My brother, good morning: my sister, good night.
    -- Hilaire Belloc
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0
    Thanks. So for the low straight, I still get 30 every time, even when there is none.

    Also, I am using Delphi - so I tried to use ShowMessage, but got a violation error:

    ---------------------------
    Access violation at address 00471A9D in module 'yahtzeeproj.exe'. Read of address 0000000D.
    ---------------------------

    This is the code I put in:

    Code:
     if Score then
      begin
        For Num := 1 to 5 do
           DiceTotal := DiceArray[Num].Tag + DiceTotal;
           ShowMessage('Die Value: ' + IntToStr(DiceArray[Num].Tag));
           ShowMessage('New running total: ' + IntToStr(DiceTotal));
      end
      else
        DiceTotal := 0;
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Mar 2006
    Posts
    2,469
    Rep Power
    1752
    I had a suspicion it might be Delphi, but had not seen any for years!
    Anyway ... not knowing the development environment is a bit of a hindrance so: do you have the option of setting breakpoints in the code and, once the breakpoint has been reached to interrogate the values of the variables?
    Failing that, a technique for debugging that I have used in the past with Visual Basic has been to have a List control and adding the debug output to that.
    As for the access violation ... not sure, but are you sure that those .Tag controls are actually a proper integer?
    The moon on the one hand, the dawn on the other:
    The moon is my sister, the dawn is my brother.
    The moon on my left and the dawn on my right.
    My brother, good morning: my sister, good night.
    -- Hilaire Belloc
  24. #13
  25. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0
    Thank you for your help, but I think I have figured out the issue. It was to do with the image lists and their indexes. I can't really explain it, but it was adding the value one less than what it was displaying. Like 4,2,4,4,4 = 13, which was actually adding 3,1,3,3,3 which DOES equal 13! Hahaha. Thanks for all your help and perseverance anyway! I will let you know if I have further issues if that's okay? Thanks again.
  26. #14
  27. No Profile Picture
    Contributing User
    Devshed Regular (2000 - 2499 posts)

    Join Date
    Mar 2006
    Posts
    2,469
    Rep Power
    1752
    Wholly explicable!
    Indexes, in computing tend to be zero-based, thus the first entry in aarry is the 0-th and an array with 10 rows is from array[0] to array[9].
    That is something I always ahd tp be careful of in VB, when looping over the elements in a List for example it had to be
    Code:
    for index = 0 to List.IndexCount -1


    But, the main thing is, you found and fixed the issue, and it works - so good job!
    The moon on the one hand, the dawn on the other:
    The moon is my sister, the dawn is my brother.
    The moon on my left and the dawn on my right.
    My brother, good morning: my sister, good night.
    -- Hilaire Belloc
  28. #15
  29. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2011
    Posts
    26
    Rep Power
    0
    I'm back already! Haha - this should be easy enough. I am trying to create new 'ResetUpper' and 'ResetLower' procedures and put all the general output stuff and resetting stuff in there and call them in the necessary procedures. I currently have all this repetitive code at the end of every procedure - it works fine there, but when I move it to a new procedure, everything becomes an 'undeclared identifier'. I am stumped! Any ideas?
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo