I'm trying to scan through the contents of my array for a 3x3 tictactoe game. The below procedure is called when the user has had their go and it's now time for the computer to move.
The gameBoard array should be full of '?' at this point, except for the 'X' that the human player just placed. I just wanted to check how many '?' are in the array, these would be the available spaces for the computer to choose. I wanted to place the result in label2 just so I could check that it is working, but it's not. At this point it should show '8' in the label.
Thanks in advance
var
i, iCount, j: Integer;
begin
label1.Caption := 'Computer''s turn';
// scan through gameboard to check available spaces
for i := 1 to 3 do
for j := 1 to 3 do
if (gameBoard[i, j] = '?') then
begin
iCount := iCount + 1;
end;
Label2.Caption := inttostr(iCount);
end;```
Local variables in Delphi are not initialized, so iCount could have any value when the procedure runs. Set iCount to zero before starting the loops.
Related
I have these 10 numbers (one in each line) in a Text File and I need them to be sorted in a chronological order starting with the highest number. I wrote a code which works just fine, but the problem is that the code isn't flexible, because once I add another number to the Text File it won't work since the code is set to sort 10 numbers only...this is due to my array of integers which is supposed to read the values before the sorting process starts, but won't allow me to add a variable to the array's properties so it will be able to read and sort any-size text file...I know there has to be a way of making a program which can sort any-size file of this structure, just please tell me how I could improve my code. (If you think my way isn't too efficient, it's because that's my homework from high school and I need to use these arrays to implement a bubblesort).
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
numbers, sortednumbers : TextFile;
count : integer=0;
number : array[1..10] of integer;
I : integer;
Procedure Swap(var X, Y : Integer);
var
Temp : integer;
begin
Temp := X;
X := Y;
Y := Temp;
end;
procedure Assign;
var I : Integer;
begin
reset(numbers);
for I := 1 to count do ReadLn(numbers, number[I]);
end;
procedure BubbleSort;
var I, J : integer;
begin
for I := 2 to count do
begin
for J := count downto I do
if (number[J] > number[J - 1]) then
Swap(number[J - 1], number[J]);
end;
end;
begin
AssignFile(numbers, 'Numbers.txt');
AssignFile(sortednumbers, 'Sorted-Numbers.txt');
Reset(numbers);
While not EoF(numbers) do
begin
ReadLn(numbers);
Inc(count);
end;
Reset(numbers);
ReWrite(sortednumbers);
Assign;
BubbleSort;
For I := 1 to count do writeln(sortednumbers, number[I]);
CloseFile(numbers);
CloseFile(sortednumbers);
end.
Use a dynamic array. This is an array that can change the number of elements it holds.
Instead of declaring:
number : array[1..10] of integer;
instead skip the bounds declaration:
Number : array of integer;
Then, before you start using it, set its length:
SetLength(Number, 10);
Once you are done, free the memory by setting it to have length 0:
SetLength(Number, 0);
Note that:
Indexes of a dynamic array start from 0, not 1. That is, Number[0] is the first element and Number[9] is the tenth. This is quite common in programming but can be confusing if it's not something you've come across before.
There are other 'quality' changes you can make to your code too. As commenter David Heffernan said, stop using global variables. I would also suggest using try/finally for resource allocation and cleanup, and using streams (and another link, wrap this over TFileStream) instead of the old-style file IO you're currently doing. Also, consider your variable names - Number for an array of numbers is odd - why not add the S and call it Numbers, for example?
That might be a bit much all at once, so go slowly in small steps, save and backup often (preferably into source control), and have fun!
And if it had not been a school project:
function Comparer(List: TStringList; index1, index2: integer): integer;
begin
try
Result:= StrToInt(List[index1]) - StrToInt(List[Index2]);
except
raise Exception.Create('Your file does not contain numbers');
end;
end;
function SortNumbers
var
lStringList: TStringlist;
begin
lStringList := TStringlist.create;
try
lStringList.LoadFromFile('Numbers.txt');
lStringList.CustomSort(Comparer);
lStringList.SaveToFile('Sorted-Numbers.txt');
finally
lStringList.Free;
end;
end;
However the Delphi RTL uses Quicksort, not Bubblesort.
I've been trying to make a program that will ask user to input elements of an array and then use that array to make a new one whose elements would be every 2nd element of inputted array. This is what I was writing:
program Keanu;
uses crt;
type Arr=array of integer;
var n,i:integer;
A,C:Arr;
begin
writeln('--Enter desired length of array--');
readln(n);
setlength(A,n);
setlength(C,n);
writeln('Elements of array A:');
for i:=1 to n do
readln(A[i]);
writeln('Elements of array C are:');
i:=1;
while (i<=n) do
begin
c[i]:=a[i];
i:=i+2;
end;
write('C = {');
for i:=1 to n do
begin
if c[i]=0 then continue else
begin
write(c[i],' ');
end;
end;
write('}');
readln;
end.
But as you can notice this is far from efficient way to make this program do the job.
First, because my new array will contain blank/empty elements(zeros) which I simply ignored with continue statement and I dont want to do that if possible.
Second,I have problem when inputting an even number for array length.Last element of new array in output window is very small,negative number and he shouldn't be there at all.I know this has to do something with my counter "i" crossing into "undefined" indexes of array.
I also tried replacing while loop with some variations of:
for i:=0 to n do
c[i]:=a[2*i-1] ;
Which is more elegant way but I still get , besides desired result , those large numbers , again because of crossing limits of an array.I suspect this has to be done with proper steps of how new array is made and moving those elements next to each other with no blank elements.
So, if anyone can give me some solutions of how to get these loop steps and limits into right order and make efficient,shortest algorithm, and preferably without using while loop if possible ,and definitely without ignoring those blank elements of new array.
Declaring variables by one character A, C: array of integer is a bad practice. The name of variable will tell you about it's type and meaning. (highly recommended)
And read about Hungarian notation, then you'll understand why TArr and arrA instead of Arr and A. Not necessary, but recommended. (also recommended)
As for the second arrC, you can use operator div to make it twice smaller than the first array arrA.
You can also crete a new variable that will be n div 2, in order not to change n div 2 in the whole code (good practice):
nDivided := n div 2;
SetLength(arrA,n);
SetLength(arrC, nDivided);
This will make your program quite a bit efficient: you'll save n - (n div 2) * sizeof(integer) bytes.
Here are both cases (for even and odd N). No "blank elements" and no "very small, negative number in the end of new array(-32768)".
N is 6 N is 5
Elements of array A: Elements of array A:
arrA[1]=1 arrA[1]=1
arrA[2]=2 arrA[2]=2
arrA[3]=3 arrA[3]=3
arrA[4]=4 arrA[4]=4
arrA[5]=5 arrA[5]=5
arrA[6]=6
Elements of array C are: Elements of array C are:
arrC[1]=2 arrC[1]=2
arrC[2]=4 arrC[2]=4
arrC[3]=6
Anyway, here is code (a little changed). Also not very good (efficent) but it does exactly what you need.
program WorkingWithArrays;
uses crt;
type
TArr = Array of Integer;
var
i, n: integer;
arrA, arrC: TArr;
begin
writeln('Enter the length of array:');
readln(n);
SetLength(arrA,n);
SetLength(arrC, n div 2);
writeln('Elements of array A:');
for i:=1 to (n) do begin
arrA[i]:=i;
writeln('#> arrA[',i,']=', arrA[i]);
end;
writeln('Elements of array C are:');
i:=1;
while (i <= n div 2) do
begin
arrC[i]:=arrA[i+i];
i:=i+1;
end;
for i:=0 to (n div 2) do begin
if arrC[i]=0 then continue else begin
writeln('#> arrC[',i,']=', arrC[i]);
end;
end;
readln;
end.
// compiled here: http://www.compileonline.com/compile_pascal_online.php
I need to remove element from array. I have tried to use array.delete(n) function, but it deletes all elements from identifier n. How to just delete exact element n ?
For example if array is 1 2 3 4 5, and n = 3, after delete it should look like following 1 2 4 5.
My code so far :
DECLARE
/* declare type array */
TYPE number_index_by_number IS TABLE OF number INDEX BY binary_integer;
v_n NUMBER := &sv_n;
v_m NUMBER := &sv_m;
v_min Number;
v_tmp Number;
v_array number_index_by_number;
v_sorted_array number_index_by_number;
begin
for i in 1..v_n
loop
v_array(i) := dbms_random.value(1,1000);
end loop;
for j in v_array.first..v_array.last
loop
DBMS_OUTPUT.put_line('v_array('||j||') :'||v_array(j));
end loop;
<<i_loop>> for i in 1..v_m
loop
/*set first array value to variable min*/
v_min := v_array(1);
v_tmp := 1;
<<j_loop>> for j in v_array.first..v_array.last
loop
DBMS_OUTPUT.put_line('v_array('||j||') :'||v_array(j));
if (v_min > v_array(j)) THEN
begin
v_min := v_array(j);
v_tmp := j;
DBMS_OUTPUT.put_line(j);
end;
end if;
end loop;
/*problem is in at this line*/
v_array.delete(v_tmp);
v_sorted_array(i) := v_min;
end loop;
for i in v_sorted_array.first..v_sorted_array.last
loop
DBMS_OUTPUT.put_line('v_sorted_array('||i||') :'||v_sorted_array(i));
end loop;
end;
I cannot reproduce any of the behaviour you describe. I could not get the delete collection method to do anything other than what it is documented to do.
However, there are a few errors in your code that could do with being tidied up.
Firstly, I should point out if you delete an element with key 3 from a PL/SQL associative array, there is then nothing with key 3 in the array. The remaining values don't 'shuffle' down to fill the gap. If there was an element with key 4 before the delete, the same element will still have key 4 afterwards. As a result, if you delete element j from a PL/SQL associative array v_array and then attempt to get v_array(j), you will get a 'no data found' error. You should check to see whether the element exists, using v_array.exists(j), before attempting to get a nonexistent element.
Secondly, the element with index 1 may get deleted before the last iteration of the outer loop. If this happens, v_array(1) will fail with a 'no data found' error. It would be better to assign NULL to v_min and v_tmp at the start of the loop, and assign to them during the loop if v_min is NULL or greater than v_array(j).
Finally, it seems your code returns the v_m smallest numbers from v_n. It would be worth verifying that v_m is less than or equal to v_n, as otherwise this doesn't make sense.
I'm affraid you cannot use a built-in method like this.
Instead of you shoud create a temp array to collect the elements prior to and afterwards the selected one from the original array, and return the temp array.
couldn't find similar posts, so posting my own question.
I got variable array of real:
price = array([58.9],[38.7],[8.95],[28.3])
I need to order it descending, with my code everything works well until last value of the array, I know even why, but can't find solution on my own. Anyway here's the code:
Procedure orderarray;
Var i,dz, j: Integer;
c :real;
v :string[25];
Begin
dz := 1;
For i := 1 to 3 do
Begin
For j:=i+1 to 4 do
if price[j]>price[dz] //searches for highest value in the array
then dz:=j;
c:=price[i]; price[i] := price[dz]; price[dz] := c; //switches current value with highest
End;
I've found solution to my own problem. Posting it just in case anyone will need it. I needed to reset dz to i, not j
Procedure orderarray;
Var i,dz, j: Integer;
c :real;
v :string[25];
Begin
For i := 1 to 3 do
Begin
dz:=i;
For j:=i+1 to 4 do
if price[j]>price[dz] //searches for highest value in the array
then dz:=j;
c:=price[i]; price[i] := price[dz]; price[dz] := c; //switches current value with highest
End;
Thank you everybody for your help, wouldn't get to the solution without you, anyway.
you need to reset dz to j everytime
for j:=i+1 to 4 do
begin
dz := j;
if price[j]>price[dz]
...;
c:=price[i]; ...;
end
In your sample dz will remain always 1, last element will never be moved since it is less then the first.
I'm making a simple calculator where you type values into an edit box. I need to split the string into a number of arrays depending on how many *+-/ there are in the sum for instance
I have 22+22*22-22/22 I want to break that into five different arrays because there are five different groups of numbers. Then later I am going to add array1 to array two multiply that by array3 and subtract that by array4 and divide that by array 5.
If you want to read something like that, especially if you want to evaluate mathematical expressions, you need more than just an array-splitter; you need a real parser. Doing it right requires a bit of compiler theory. I'd recommend you take a look at Let's Build A Compiler, a tutorial that covers everything you'll need to know about expression parsing (and a bit more, since he's actually building a simple compiler) and makes it easy to understand. All examples are in Turbo Pascal, so it should be easy for a Delphi coder to read.
Delphi XE has a SplitString function that does exactly what you need.
If you wish to get the result of that equation, you should try a non-visual component, called CalcExpress. It's free and you can get it from here:
CalcExpress
Download link is at the end of the page text
Here's a function which may help you on the way.
It breaks down an input string into an array of sub-strings, based upon a provided set of pre-defined character sets.
It will give you an array of strings, which will be ["22", "+", "22", "*", "22", "-", "22", "/", "22"].
From there on you'll have to identify the numbers and the operators, and you'll have to group and execute the calculations according to the rules for operator precedence.
TCharSet = Set of Char;
TStringArray = Array of String;
function GetSubStrings(InputString: String; CharacterSets: Array of TCharSet): TStringArray;
// Get Sub-strings
var
Index: Integer;
Character: Char;
SubString: String;
SubStringArray: TStringArray;
CharacterSetIndex: Integer;
PreviousCharacterSetIndex: Integer;
begin
// Get
SubString := '';
SetLength(SubStringArray, 0);
PreviousCharacterSetIndex := -1;
for Index := 1 to Length(InputString) do
begin
// Character
Character := InputString[Index];
// Character Set Index
CharacterSetIndex := GetCharacterSet(Character, CharacterSets);
// Add
if (CharacterSetIndex = PreviousCharacterSetIndex) or (Index = 1) then
// Add Character to SubString
SubString := SubString + Character
else
begin
// Add SubString To SubString Array
SetLength(SubStringArray, Length(SubStringArray) + 1);
SubStringArray[Length(SubStringArray) - 1] := SubString;
// New SubString
SubString := Character;
end;
// Previous Character Set Index
PreviousCharacterSetIndex := CharacterSetIndex;
// Add last SubString
if Index = Length(InputString) then
begin
// Add SubString To SubString Array
SetLength(SubStringArray, Length(SubStringArray) + 1);
SubStringArray[Length(SubStringArray) - 1] := SubString;
end;
end;
// Result
Result := SubStringArray;
end;
function GetCharacterSet(Character: Char; CharacterSets: Array of TCharSet): Integer;
// Get Character Set
var
Index: Integer;
CharacterSet: TCharSet;
begin
// Get
Result := -1;
for Index := 0 to Length(CharacterSets) - 1 do
begin
// Character Set
CharacterSet := CharacterSets[Index];
// Check
if Character in CharacterSet then
begin
// Result
Result := Index;
// Break
Break;
end;
end;
end;